first commit
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
#--------------------------------------------------------------------
|
||||
# Example Environment Configuration file
|
||||
#
|
||||
# This file can be used as a starting point for your own
|
||||
# custom .env files, and contains most of the possible settings
|
||||
# available in a default install.
|
||||
#
|
||||
# By default, all of the settings are commented out. If you want
|
||||
# to override the setting, you must un-comment it by removing the '#'
|
||||
# at the beginning of the line.
|
||||
#--------------------------------------------------------------------
|
||||
UID=1100
|
||||
#--------------------------------------------------------------------
|
||||
# ENVIRONMENT
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
CI_ENVIRONMENT = development
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# APP
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
# app.baseURL = ''
|
||||
# app.forceGlobalSecureRequests = false
|
||||
|
||||
# app.sessionDriver = 'CodeIgniter\Session\Handlers\FileHandler'
|
||||
# app.sessionCookieName = 'ci_session'
|
||||
# app.sessionExpiration = 7200
|
||||
# app.sessionSavePath = null
|
||||
# app.sessionMatchIP = false
|
||||
# app.sessionTimeToUpdate = 300
|
||||
# app.sessionRegenerateDestroy = false
|
||||
|
||||
# app.CSPEnabled = false
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# DATABASE
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
# database.default.hostname = localhost
|
||||
# database.default.database = ci4
|
||||
# database.default.username = root
|
||||
# database.default.password = root
|
||||
# database.default.DBDriver = MySQLi
|
||||
# database.default.DBPrefix =
|
||||
|
||||
# database.tests.hostname = localhost
|
||||
# database.tests.database = ci4
|
||||
# database.tests.username = root
|
||||
# database.tests.password = root
|
||||
# database.tests.DBDriver = MySQLi
|
||||
# database.tests.DBPrefix =
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# CONTENT SECURITY POLICY
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
# contentsecuritypolicy.reportOnly = false
|
||||
# contentsecuritypolicy.defaultSrc = 'none'
|
||||
# contentsecuritypolicy.scriptSrc = 'self'
|
||||
# contentsecuritypolicy.styleSrc = 'self'
|
||||
# contentsecuritypolicy.imageSrc = 'self'
|
||||
# contentsecuritypolicy.base_uri = null
|
||||
# contentsecuritypolicy.childSrc = null
|
||||
# contentsecuritypolicy.connectSrc = 'self'
|
||||
# contentsecuritypolicy.fontSrc = null
|
||||
# contentsecuritypolicy.formAction = null
|
||||
# contentsecuritypolicy.frameAncestors = null
|
||||
# contentsecuritypolicy.frameSrc = null
|
||||
# contentsecuritypolicy.mediaSrc = null
|
||||
# contentsecuritypolicy.objectSrc = null
|
||||
# contentsecuritypolicy.pluginTypes = null
|
||||
# contentsecuritypolicy.reportURI = null
|
||||
# contentsecuritypolicy.sandbox = false
|
||||
# contentsecuritypolicy.upgradeInsecureRequests = false
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# COOKIE
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
# cookie.prefix = ''
|
||||
# cookie.expires = 0
|
||||
# cookie.path = '/'
|
||||
# cookie.domain = ''
|
||||
# cookie.secure = false
|
||||
# cookie.httponly = false
|
||||
# cookie.samesite = 'Lax'
|
||||
# cookie.raw = false
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# ENCRYPTION
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
# encryption.key =
|
||||
# encryption.driver = OpenSSL
|
||||
# encryption.blockSize = 16
|
||||
# encryption.digest = SHA512
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# HONEYPOT
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
# honeypot.hidden = 'true'
|
||||
# honeypot.label = 'Fill This Field'
|
||||
# honeypot.name = 'honeypot'
|
||||
# honeypot.template = '<label>{label}</label><input type="text" name="{name}" value=""/>'
|
||||
# honeypot.container = '<div style="display:none">{template}</div>'
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# SECURITY
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
# security.csrfProtection = 'cookie'
|
||||
# security.tokenRandomize = false
|
||||
# security.tokenName = 'csrf_token_name'
|
||||
# security.headerName = 'X-CSRF-TOKEN'
|
||||
# security.cookieName = 'csrf_cookie_name'
|
||||
# security.expires = 7200
|
||||
# security.regenerate = true
|
||||
# security.redirect = true
|
||||
# security.samesite = 'Lax'
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# LOGGER
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
# logger.threshold = 4
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# CURLRequest
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
# curlrequest.shareOptions = true
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
.DS_Store
|
||||
|
||||
application/cache/*
|
||||
!application/cache/index.html
|
||||
|
||||
application/logs/*
|
||||
!application/logs/index.html
|
||||
|
||||
!application/*/.htaccess
|
||||
|
||||
composer.lock
|
||||
|
||||
user_guide_src/build/*
|
||||
user_guide_src/cilexer/build/*
|
||||
user_guide_src/cilexer/dist/*
|
||||
user_guide_src/cilexer/pycilexer.egg-info/*
|
||||
/vendor/
|
||||
|
||||
# IDE Files
|
||||
#-------------------------
|
||||
/nbproject/
|
||||
.idea/*
|
||||
|
||||
## Sublime Text cache files
|
||||
*.tmlanguage.cache
|
||||
*.tmPreferences.cache
|
||||
*.stTheme.cache
|
||||
*.sublime-workspace
|
||||
*.sublime-project
|
||||
/tests/tests/
|
||||
/tests/results/
|
||||
|
||||
SAVVY/user/log/GPS.log
|
||||
vendor
|
||||
|
||||
*.log
|
||||
*.bak
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<IfModule mod_rewrite.c>
|
||||
|
||||
RewriteEngine On
|
||||
RewriteBase /
|
||||
|
||||
#Removes access to the system folder by users.
|
||||
#Additionally this will allow you to create a System.php controller,
|
||||
#previously this would not have been possible.
|
||||
#'system' can be replaced if you have renamed your system folder.
|
||||
RewriteCond %{REQUEST_URI} ^system.*
|
||||
RewriteRule ^(.*)$ /index.php?/$1 [L]
|
||||
|
||||
#When your application folder isn't in the system folder
|
||||
#This snippet prevents user access to the application folder
|
||||
#Submitted by: Fabdrol
|
||||
#Rename 'application' to your applications folder name.
|
||||
RewriteCond %{REQUEST_URI} ^application.*
|
||||
RewriteRule ^(.*)$ /index.php?/$1 [L]
|
||||
|
||||
#Checks to
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule ^(.*)$ index.php?/$1 [L]
|
||||
|
||||
</IfModule>
|
||||
|
||||
<IfModule !mod_rewrite.c>
|
||||
# If we don't have mod_rewrite installed, all 404's
|
||||
# can be sent to index.php, and everything works as normal.
|
||||
# Submitted by: ElliotHaughin
|
||||
|
||||
ErrorDocument 404 /index.php
|
||||
|
||||
</IfModule>
|
||||
|
||||
Binary file not shown.
+209290
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] Account Audit job is starting.\n";
|
||||
include '../backend.php';
|
||||
define("FLOAT_SYSTEM_ACCOUNT_AUDIT", 92015);
|
||||
|
||||
function Fextension_call($in, &$out) {
|
||||
// logToFl("Merchant_Name count->" . $in["merchant_name"]);
|
||||
global $savvyext;
|
||||
$out = $savvyext->savvyext_api($in);
|
||||
$ret = $out["retval"];
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$inX["limit"] = 100;
|
||||
$inX["pid"] = 0;
|
||||
$inX["action"] = FLOAT_SYSTEM_ACCOUNT_AUDIT;
|
||||
$outX = array();
|
||||
|
||||
|
||||
$extension_call = true;
|
||||
|
||||
if ($extension_call == true) {
|
||||
// logToFl("merchant_name count->" . $res->merchant_name);
|
||||
Fextension_call($inX, $outX);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* members account imports
|
||||
*/
|
||||
include '../backend.php';
|
||||
define("FLOAT_SYSTEM_IMPORT_ACCONTTYPES", 91010);
|
||||
|
||||
function Fextension_call($in, &$out) {
|
||||
// logToFl("Merchant_Name count->" . $in["merchant_name"]);
|
||||
global $savvyext;
|
||||
$out = $savvyext->savvyext_api($in);
|
||||
$ret = $out["retval"];
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$inX["limit"] = 250;
|
||||
$inX["offset"] = 0;
|
||||
$inX["intel_imported"] = 'false';
|
||||
$outX = array();
|
||||
|
||||
accounts_benefits_importing($inX, $outX);
|
||||
|
||||
|
||||
logToFl("Total count->" . $outX->count);
|
||||
|
||||
if ($outX->count > 0) {
|
||||
|
||||
foreach ($outX->results as $res) {
|
||||
|
||||
// logToFl("API Result ->".$res);
|
||||
echo "Yes ---------------------------------------------- <br>";
|
||||
|
||||
$in = array();
|
||||
|
||||
$in = (array) $res;
|
||||
|
||||
// print_r( $in );
|
||||
|
||||
$in["pid"] = 100;
|
||||
$in["import_id"] = $in["id"];
|
||||
$out = array();
|
||||
$in["action"] = FLOAT_SYSTEM_IMPORT_ACCONTTYPES;
|
||||
$extension_call = true;
|
||||
|
||||
if ($extension_call == true && $in["member_id"] != '') {
|
||||
// logToFl("merchant_name count->" . $res->merchant_name);
|
||||
// echo "Here " .rand(1000,9999);
|
||||
Fextension_call($in, $out);
|
||||
if ($out["result_import_id"] != '' && $out["result_import_id"] > 0) {
|
||||
makedimported_accounts_types($in, $out); // call back to merk transaction imported
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
} // end for each
|
||||
} // if records avilable
|
||||
|
||||
function makedimported_accounts_types($in, &$out) {
|
||||
global $savvyext;
|
||||
$target_url = $savvyext->cfgReadChar('microservices.account') . "/api/v1/accounts/" . $in["import_id"] . "/"; //
|
||||
|
||||
$fields_string = "";
|
||||
//url-ify the data for the POST
|
||||
foreach ($in as $key => $value) {
|
||||
$fields_string .= $key . '=' . $value . '&';
|
||||
}
|
||||
rtrim($fields_string, '&');
|
||||
|
||||
// $target_url = $target_url . "/?" . $fields_string;
|
||||
|
||||
$returnData = json_encode(["intel_imported" => date("Y-m-d H:i:s")]);
|
||||
|
||||
//open connection
|
||||
$ch = curl_init();
|
||||
//set the url, number of POST vars, POST data
|
||||
curl_setopt($ch, CURLOPT_URL, $target_url);
|
||||
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
||||
'Content-Type: application/json',
|
||||
'Connection: Keep-Alive',
|
||||
'Authorization: Server-Token ' . $savvyext->cfgReadChar('system.bank_token'),
|
||||
'Accept: application/json'
|
||||
));
|
||||
|
||||
// curl_setopt($ch, CURLOPT_POST, count($in));
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $returnData);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
|
||||
//execute post
|
||||
$result = curl_exec($ch);
|
||||
//close connection
|
||||
curl_close($ch);
|
||||
|
||||
//logToFl("API Result ->".$result);
|
||||
|
||||
$out = json_decode($result);
|
||||
}
|
||||
|
||||
function accounts_benefits_importing($in, &$out) {
|
||||
global $savvyext;
|
||||
$target_url = $savvyext->cfgReadChar('microservices.account') . "/api/v1/accounts/?intel_imported=false"; //
|
||||
$fields_string = "";
|
||||
//url-ify the data for the POST
|
||||
foreach ($in as $key => $value) {
|
||||
$fields_string .= $key . '=' . $value . '&';
|
||||
}
|
||||
rtrim($fields_string, '&');
|
||||
|
||||
$target_url = $target_url . "/?" . $fields_string;
|
||||
|
||||
logToFl("API URL ->" . $target_url);
|
||||
|
||||
//open connection
|
||||
$ch = curl_init();
|
||||
//set the url, number of POST vars, POST data
|
||||
curl_setopt($ch, CURLOPT_URL, $target_url);
|
||||
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
||||
'Content-Type: application/json',
|
||||
'Connection: Keep-Alive',
|
||||
'Authorization: Server-Token ' . $savvyext->cfgReadChar('system.bank_token'),
|
||||
'Accept: application/json'
|
||||
));
|
||||
|
||||
|
||||
// curl_setopt($ch, CURLOPT_POST, count($in));
|
||||
// curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
|
||||
//execute post
|
||||
$result = curl_exec($ch);
|
||||
//close connection
|
||||
curl_close($ch);
|
||||
|
||||
//logToFl("API Result ->".$result);
|
||||
|
||||
$out = json_decode($result);
|
||||
|
||||
// print_r( $out );
|
||||
}
|
||||
|
||||
function logToFl($lg_strr) {
|
||||
/* $myfile = fopen("LOG/logf_benefit.txt", "a+");
|
||||
$txt = $lg_strr . "\n";
|
||||
fwrite($myfile, $txt);
|
||||
fclose($myfile);
|
||||
|
||||
*
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] Account Audit job is starting.\n";
|
||||
include '../backend.php';
|
||||
define("SAVVY_BKO_INITLOCATION_AUDIT", 100045);
|
||||
|
||||
function Fextension_call($in, &$out) {
|
||||
// logToFl("Merchant_Name count->" . $in["merchant_name"]);
|
||||
global $savvyext;
|
||||
$out = $savvyext->savvyext_api($in);
|
||||
$ret = $out["retval"];
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$inX["limit"] = 30;
|
||||
$inX["pid"] = 0;
|
||||
$inX["action"] = SAVVY_BKO_INITLOCATION_AUDIT;
|
||||
$outX = array();
|
||||
|
||||
|
||||
$extension_call = true;
|
||||
|
||||
if ($extension_call == true) {
|
||||
// logToFl("merchant_name count->" . $res->merchant_name);
|
||||
Fextension_call($inX, $outX);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] account_process_subscription job is starting.\n";
|
||||
require('../backend.php');
|
||||
|
||||
// We will not limit the SQL we will exhaust the allowed memory
|
||||
// we will process data in ${hard_limit} batches and hopefully catch up
|
||||
$hard_limit = 550;
|
||||
$span_limit = 30;
|
||||
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
|
||||
// Expire any late subscription here
|
||||
// Processing the transactions now
|
||||
$mysql = "SELECT ma.id AS assign_id, ma.*,mc.card_reciept AS providers FROM members_card_assign ma "
|
||||
. " LEFT JOIN main_cards mc ON mc.id = ma.card_id "
|
||||
. " WHERE ma.subscribe IS NOT NULL AND ma.completed IS NULL AND ma.reciept_count =0 "
|
||||
. " AND mc.card_reciept IS NOT NULL AND mc.button1_action IN ('GOOFFERS') "
|
||||
. " ORDER BY ma.updated ASC LIMIT $hard_limit";
|
||||
//echo $mysql;
|
||||
|
||||
$r0 = pg_query($readOnlyReplicaConn, $mysql);
|
||||
|
||||
if ($r0 && pg_num_rows($r0)) {
|
||||
|
||||
while ($f0 = pg_fetch_assoc($r0)) {
|
||||
$member_id = $f0["member_id"];
|
||||
$assign_id = $f0["assign_id"];
|
||||
$providers = $f0["providers"];
|
||||
$subscribe_date = $f0["subscribe"];
|
||||
|
||||
$provider_name = "";
|
||||
|
||||
// let just mar trhis so that w dont over procss same trasaction
|
||||
$mysql_up = "UPDATE members_card_assign SET updated = now() WHERE id = $assign_id AND member_id = $member_id";
|
||||
pg_query($conn, $mysql_up);
|
||||
|
||||
if ($providers != '' && $providers > 0) {
|
||||
// get the provider name
|
||||
// We have to visist this again to improve the srach string
|
||||
$mysql_find = "SELECT id, LOWER(name) , LOWER(name_alias) FROM transport_providers WHERE id = $providers";
|
||||
$alias_extra = "";
|
||||
|
||||
$rf = pg_query($readOnlyReplicaConn, $mysql_find);
|
||||
if ($rf && pg_num_rows($rf)) {
|
||||
|
||||
$r = pg_fetch_row($rf);
|
||||
$provider_name = $r[1]; // may be an array
|
||||
$alias_string = $r[2];
|
||||
|
||||
// $alias_string = "AA,BB,CC,";
|
||||
|
||||
if (strlen($alias_string) > 0) {
|
||||
$pieces = explode(",", $alias_string);
|
||||
$count_item = count($pieces);
|
||||
for ($ii = 0; $ii < $count_item; $ii++) {
|
||||
$this_element = trim(strtolower($pieces[$ii]));
|
||||
if (strlen($this_element) > 0) {
|
||||
$itm_str = "'" . $this_element . "'";
|
||||
if ($ii > 0) {
|
||||
$alias_extra .= ",";
|
||||
}
|
||||
$alias_extra .= $itm_str;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// echo $provider_name;
|
||||
|
||||
if ($provider_name != '') {
|
||||
$total_bank_recipts = countAccountReciepts($readOnlyReplicaConn, $member_id, $provider_name, $subscribe_date, $span_limit,$alias_extra);
|
||||
$total_email_recipts = countPearsedReciepts($readOnlyReplicaConn, $member_id, $providers, $subscribe_date, $span_limit);
|
||||
$total_bank_extra_recipts = countOtherAccountReciepts($readOnlyReplicaConn, $member_id, $provider_name, $subscribe_date, $span_limit,$alias_extra);
|
||||
$total_email_extra_recipts = countOtherPearsedReciepts($readOnlyReplicaConn, $member_id, $providers, $subscribe_date, $span_limit);
|
||||
$total_recipts = $total_bank_recipts + $total_email_recipts + $total_bank_extra_recipts + $total_email_extra_recipts;
|
||||
|
||||
if ($total_recipts > 0) {
|
||||
$mysql_up1 = "UPDATE members_card_assign SET updated = now(),reciept_count=$total_recipts WHERE id = $assign_id AND member_id = $member_id";
|
||||
pg_query($conn, $mysql_up1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function countAccountReciepts($readOnlyReplicaConn, $member_id, $provider_name, $subscribe_date, $span_limit,$alias_extra) {
|
||||
$total_rec = 0;
|
||||
|
||||
$provider_total = "'".$provider_name."'";
|
||||
if ( strlen($alias_extra) > 0 ){
|
||||
$provider_total= $provider_total.",".$alias_extra;
|
||||
}
|
||||
|
||||
$mysql = "SELECT count(id) AS total_rec FROM members_bankimport WHERE member_id=$member_id AND lower(merchant_name) IN ($provider_total) AND time >= '$subscribe_date'";
|
||||
$rf = pg_query($readOnlyReplicaConn, $mysql);
|
||||
if ($rf && pg_num_rows($rf)) {
|
||||
$r = pg_fetch_row($rf);
|
||||
$total_rec = $r[0];
|
||||
}
|
||||
return $total_rec;
|
||||
}
|
||||
|
||||
function countPearsedReciepts($readOnlyReplicaConn, $member_id, $provider, $subscribe_date, $span_limit) {
|
||||
|
||||
$total_rec = 0;
|
||||
$mysql = "SELECT count(pi.id) AS total_rec FROM parsedemail_item pi LEFT JOIN trackedemail_item ti ON ti.id=pi.trackedemail_item_id WHERE ti.member_id=$member_id AND pi.transport_provider_id=$provider AND pi.travel_date >= '$subscribe_date'";
|
||||
$rf = pg_query($readOnlyReplicaConn, $mysql);
|
||||
if ($rf && pg_num_rows($rf)) {
|
||||
$r = pg_fetch_row($rf);
|
||||
$total_rec = $r[0];
|
||||
}
|
||||
return $total_rec;
|
||||
}
|
||||
|
||||
function countOtherAccountReciepts($conn, $member_id, $provider_name, $subscribe_date, $span_limit,$alias_extra) {
|
||||
|
||||
$total_rec = 0;
|
||||
$provider_total = "'".$provider_name."'";
|
||||
if ( strlen($alias_extra) > 0 ){
|
||||
$provider_total= $provider_total.",".$alias_extra;
|
||||
}
|
||||
|
||||
$mysql = "SELECT count(id) AS total_rec FROM members_transactions_import_raw WHERE member_id=$member_id AND LOWER(merchant_name) IN ($provider_total) AND time >= '$subscribe_date'";
|
||||
//echo $mysql;
|
||||
$rf = pg_query($conn, $mysql);
|
||||
if ($rf && pg_num_rows($rf)) {
|
||||
$r = pg_fetch_row($rf);
|
||||
$total_rec = $r[0];
|
||||
}
|
||||
return $total_rec;
|
||||
}
|
||||
|
||||
function countOtherPearsedReciepts($conn, $member_id, $provider, $subscribe_date, $span_limit) {
|
||||
|
||||
$total_rec = 0;
|
||||
$mysql = "SELECT count(id) AS total_rec FROM parsedemail_item_payment WHERE member_id=$member_id AND transport_provider_id=$provider AND receipt_datetime >= '$subscribe_date'";
|
||||
//echo $mysql;
|
||||
$rf = pg_query($conn, $mysql);
|
||||
if ($rf && pg_num_rows($rf)) {
|
||||
$r = pg_fetch_row($rf);
|
||||
$total_rec = $r[0];
|
||||
}
|
||||
return $total_rec;
|
||||
}
|
||||
|
||||
pg_close($conn);
|
||||
pg_close($readOnlyReplicaConn);
|
||||
echo "[" . date("Y-m-d H:i:s") . "] account_process_subscription job complete.\n";
|
||||
?>
|
||||
@@ -0,0 +1,201 @@
|
||||
<?php
|
||||
|
||||
include '../backend.php';
|
||||
define("FLOAT_SYSTEM_IMPORT_TRANSACTIONS", 91000);
|
||||
|
||||
function Fextension_call($in, &$out) {
|
||||
// logToFl("Merchant_Name count->" . $in["merchant_name"]);
|
||||
global $savvyext;
|
||||
$out = $savvyext->savvyext_api($in);
|
||||
$ret = $out["retval"];
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$inX["limit"] = 250;
|
||||
$inX["offset"] = 0;
|
||||
$inX["intel_imported"] = 'false';
|
||||
$outX=array();
|
||||
|
||||
import_accounts_transactions($inX, $outX);
|
||||
// test_import_accounts_transactions($inX, $outX); // just for testing -- to be removed
|
||||
|
||||
|
||||
logToFl("Total count->".$outX->count);
|
||||
|
||||
if ($outX->count > 0) {
|
||||
|
||||
foreach ($outX->results as $res) {
|
||||
$in = array();
|
||||
$in["pid"] =100;
|
||||
$in["import_id"] = $res->id;
|
||||
$in["account"] = $res->account;
|
||||
$in["member_id"] = $res->member_id;
|
||||
$in["amount"] = (int)(100.0*$res->amount);
|
||||
$in["currency"] = $res->currency;
|
||||
$in["description"] = $res->description;
|
||||
$in["time"] = $res->time;
|
||||
$in["category"] = $res->category;
|
||||
$in["provider_category"] = $res->provider_category;
|
||||
$in["intel_imported"] = $res->intel_imported;
|
||||
$in["merchant_provider_id"] = $res->merchant_provider_id;
|
||||
$in["merchant_name"] = $res->merchant_name;
|
||||
$in["status"] = isset($res->status) ? $res->status : "0";
|
||||
|
||||
$in["fake"] = isset($res->extra->fake) ? $res->extra->fake : false;
|
||||
$in["mode"] = isset($res->extra->mode) ? $res->extra->mode : "";
|
||||
$in["duplicated"] = isset($res->extra->duplicated) ? $res->extra->duplicated : false;
|
||||
|
||||
|
||||
$out = array();
|
||||
$in["action"] = FLOAT_SYSTEM_IMPORT_TRANSACTIONS;
|
||||
|
||||
|
||||
$extension_call = true;
|
||||
|
||||
if ($extension_call == true && $in["member_id"] !='') {
|
||||
// logToFl("merchant_name count->" . $res->merchant_name);
|
||||
Fextension_call($in, $out);
|
||||
}
|
||||
|
||||
makedimported_accounts_transactions($in, $out); // call back to merk transaction imported
|
||||
} // end for each
|
||||
} // if records avilable
|
||||
|
||||
function makedimported_accounts_transactions($in, &$out) {
|
||||
global $savvyext;
|
||||
$target_url = $savvyext->cfgReadChar('microservices.account') . "/api/v1/transactions/".$in["import_id"]."/"; //
|
||||
|
||||
$fields_string = "";
|
||||
//url-ify the data for the POST
|
||||
foreach ($in as $key => $value) {
|
||||
$fields_string .= $key . '=' . $value . '&';
|
||||
}
|
||||
rtrim($fields_string, '&');
|
||||
|
||||
// $target_url = $target_url . "/?" . $fields_string;
|
||||
|
||||
$returnData = json_encode( [ "intel_imported"=> date("Y-m-d H:i:s") ] );
|
||||
|
||||
//open connection
|
||||
$ch = curl_init();
|
||||
//set the url, number of POST vars, POST data
|
||||
curl_setopt($ch, CURLOPT_URL, $target_url);
|
||||
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
||||
'Content-Type: application/json',
|
||||
'Connection: Keep-Alive',
|
||||
'Authorization: Server-Token ' . $savvyext->cfgReadChar('system.bank_token'),
|
||||
'Accept: application/json'
|
||||
));
|
||||
|
||||
// curl_setopt($ch, CURLOPT_POST, count($in));
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $returnData);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
|
||||
//execute post
|
||||
$result = curl_exec($ch);
|
||||
//close connection
|
||||
curl_close($ch);
|
||||
|
||||
//logToFl("API Result ->".$result);
|
||||
|
||||
$out = json_decode($result);
|
||||
}
|
||||
|
||||
|
||||
function import_accounts_transactions($in, &$out) {
|
||||
global $savvyext;
|
||||
$target_url = $savvyext->cfgReadChar('microservices.account') . "/api/v1/transactions"; //
|
||||
|
||||
$fields_string = "";
|
||||
//url-ify the data for the POST
|
||||
foreach ($in as $key => $value) {
|
||||
$fields_string .= $key . '=' . $value . '&';
|
||||
}
|
||||
rtrim($fields_string, '&');
|
||||
|
||||
$target_url = $target_url . "/?" . $fields_string;
|
||||
|
||||
logToFl("API URL ->".$target_url);
|
||||
|
||||
//open connection
|
||||
$ch = curl_init();
|
||||
//set the url, number of POST vars, POST data
|
||||
curl_setopt($ch, CURLOPT_URL, $target_url);
|
||||
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
||||
'Content-Type: application/json',
|
||||
'Connection: Keep-Alive',
|
||||
'Authorization: Server-Token ' . $savvyext->cfgReadChar('system.bank_token'),
|
||||
'Accept: application/json'
|
||||
));
|
||||
|
||||
|
||||
// curl_setopt($ch, CURLOPT_POST, count($in));
|
||||
// curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
|
||||
//execute post
|
||||
$result = curl_exec($ch);
|
||||
//close connection
|
||||
curl_close($ch);
|
||||
|
||||
//logToFl("API Result ->".$result);
|
||||
|
||||
$out = json_decode($result);
|
||||
}
|
||||
|
||||
function test_import_accounts_transactions($in, &$out) {
|
||||
$target_url = "http://chiefsoft.net/DATA/transactions.php"; //
|
||||
|
||||
$fields_string = "";
|
||||
//url-ify the data for the POST
|
||||
foreach ($in as $key => $value) {
|
||||
$fields_string .= $key . '=' . $value . '&';
|
||||
}
|
||||
rtrim($fields_string, '&');
|
||||
|
||||
$target_url = $target_url . "/?" . $fields_string;
|
||||
|
||||
//open connection
|
||||
$ch = curl_init();
|
||||
//set the url, number of POST vars, POST data
|
||||
curl_setopt($ch, CURLOPT_URL, $target_url);
|
||||
|
||||
// curl_setopt($ch, CURLOPT_POST, count($in));
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
|
||||
//execute post
|
||||
$result = curl_exec($ch);
|
||||
//close connection
|
||||
curl_close($ch);
|
||||
|
||||
//logToFl("Result ->".$result);
|
||||
|
||||
$out = json_decode($result);
|
||||
// Parse result
|
||||
/* foreach (explode("\n", $result) as $line) {
|
||||
if ($line == "" || strpos($line, "=") === false)
|
||||
continue;
|
||||
$key = trim(strtok($line, "="));
|
||||
if ($key != "") {
|
||||
$out[$key] = base64_decode(substr($line, 1 + strlen($key)));
|
||||
}
|
||||
}
|
||||
* */
|
||||
|
||||
}
|
||||
|
||||
|
||||
function logToFl($lg_strr) {
|
||||
$myfile = fopen("LOG/logf.txt", "a+");
|
||||
$txt = $lg_strr."\n";
|
||||
fwrite($myfile, $txt);
|
||||
fclose($myfile);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
// require_once( '/Users/osx/Sites/Float/adminsavvy/backend.php' );
|
||||
include '../backend.php';
|
||||
require_once('../vendor/autoload.php');
|
||||
require_once('common/Logger.php');
|
||||
|
||||
use \SendGrid\Mail\Mail;
|
||||
|
||||
/**
|
||||
* Send email Float App sign up emails last 24 hours daily report
|
||||
*/
|
||||
class EmailLast24hrsReport
|
||||
{
|
||||
|
||||
public $conn;
|
||||
public $repConn;
|
||||
|
||||
public $sendgrid_api;
|
||||
public $sender;
|
||||
public $sender_name;
|
||||
public $receivers;
|
||||
|
||||
protected $hard_limit = 550;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
global $savvyext;
|
||||
$this->conn = self::__cnn($savvyext);
|
||||
$this->repConn = self::__repCnn($savvyext);
|
||||
|
||||
$this->sendgrid_api = $savvyext->cfgReadChar('mailsend.api_key');
|
||||
$this->sender = $savvyext->cfgReadChar('mailsend.from');
|
||||
$this->sender_name = $savvyext->cfgReadChar('mailsend.name');
|
||||
$this->receivers = array(
|
||||
'jervis@float.sg' => 'Jervis',
|
||||
'tnguyen@float.sg' => 'Tri Nguyen',
|
||||
//'charlie.nguyen.goldenowl@gmail.com' => 'Charlie Nguyen',
|
||||
);
|
||||
}
|
||||
|
||||
private static function __cnn($savvyext)
|
||||
{
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = sprintf('host=%s port=%s dbname=%s user=%s password=%s', $db_host, $db_port, $db_name, $db_user, $db_pass);
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
return $conn;
|
||||
}
|
||||
|
||||
private static function __repCnn($savvyext)
|
||||
{
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$connstr = sprintf('host=%s port=%s dbname=%s user=%s password=%s', $db_host, $db_port, $db_name, $db_user, $db_pass);
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
return $conn;
|
||||
}
|
||||
|
||||
private function array2csv($data, $delimiter = ',', $enclosure = '"', $escape_char = "\\")
|
||||
{
|
||||
$f = fopen('php://memory', 'r+');
|
||||
foreach ($data as $item) {
|
||||
fputcsv($f, $item, $delimiter, $enclosure, $escape_char);
|
||||
}
|
||||
rewind($f);
|
||||
return stream_get_contents($f);
|
||||
}
|
||||
/**
|
||||
* Send email report via SendGrid
|
||||
* @param array $data list email fail
|
||||
* @return mixed
|
||||
*/
|
||||
protected function send($data)
|
||||
{
|
||||
$short_date = (new \DateTime())->format('Y-M-d');
|
||||
// create email layout
|
||||
ob_start();
|
||||
require_once(__DIR__ . '/email/sign_up_email_last_24hrs.php');
|
||||
$layout = ob_get_clean();
|
||||
// create sendgrid instance
|
||||
$sendgrid = new \SendGrid\Mail\Mail;
|
||||
$sendgrid->setFrom($this->sender, $this->sender_name);
|
||||
$sendgrid->setSubject('Float App sign up emails last 24 hours daily report');
|
||||
$sendgrid->addTos($this->receivers);
|
||||
$sendgrid->addContent('text/html', $layout);
|
||||
|
||||
|
||||
//HEADER of csv files
|
||||
array_unshift($data,[
|
||||
'Date','Email name', 'Total emails'
|
||||
]);
|
||||
$att1 = new \SendGrid\Mail\Attachment();
|
||||
//$att1->setContent( file_get_contents("test_files/1/1.txt") );
|
||||
$att1->setContent( $this->array2csv($data) );
|
||||
$att1->setType("text/csv");
|
||||
|
||||
$att1->setFilename("sign-up-emails-last-24-hrs-report-".$short_date.".csv");
|
||||
$att1->setDisposition("attachment");
|
||||
$sendgrid->addAttachment( $att1 );
|
||||
|
||||
// send
|
||||
$send = new \SendGrid($this->sendgrid_api);
|
||||
$response = $send->send($sendgrid);
|
||||
if ($response->statusCode() !== 202) {
|
||||
throw new Exception('Send email via Sendgrid get errors!');
|
||||
}
|
||||
}
|
||||
public function getemails()
|
||||
{
|
||||
try {
|
||||
// HH24:MI
|
||||
$sql = sprintf("
|
||||
SELECT to_char(added::DATE,'YYYY-Mon-DD') as date,'Welcome to Float' as email_name, count(id) as total FROM members
|
||||
WHERE added >= NOW() - INTERVAL '24 HOURS'
|
||||
GROUP BY added::DATE
|
||||
ORDER BY added::DATE ASC;
|
||||
");
|
||||
|
||||
$results = pg_query($this->repConn, $sql);
|
||||
|
||||
if ($error = pg_last_error($this->repConn)) {
|
||||
throw new Exception($error);
|
||||
}
|
||||
|
||||
return pg_fetch_all($results);
|
||||
|
||||
} catch (Exception $e) {
|
||||
Logger::debug($e->getMessage());
|
||||
}
|
||||
}
|
||||
private function getEmptyData(){
|
||||
return [
|
||||
'date' => (new \DateTime())->modify('-24 hours')->format('Y-M-d'), // H:i
|
||||
'email_name' => 'Welcome to Float',
|
||||
'total' => '0',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Excute jobs
|
||||
* @return mixed
|
||||
*/
|
||||
public function excute()
|
||||
{
|
||||
try {
|
||||
$data = $this->getemails();
|
||||
if (!$data) {
|
||||
$data = [$this->getEmptyData()];
|
||||
//throw new Exception('No Email Receipt which parsed failed!');
|
||||
}
|
||||
|
||||
|
||||
$send = $this->send($data);
|
||||
} catch (Exception $e) {
|
||||
Logger::debug($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$instace = new EmailLast24hrsReport;
|
||||
$instace->excute();
|
||||
@@ -0,0 +1,423 @@
|
||||
<?php
|
||||
include '../backend.php';
|
||||
require_once('../vendor/autoload.php');
|
||||
require_once(__DIR__ . '/lock.php');
|
||||
|
||||
use \SendGrid\Mail\Mail;
|
||||
|
||||
/**
|
||||
* Get Sendgrid Report
|
||||
*/
|
||||
class Custom_Report {
|
||||
|
||||
// curl setup private
|
||||
private $curl;
|
||||
|
||||
protected $api_url;
|
||||
protected $key;
|
||||
protected $replica_conn;
|
||||
protected $sendgrid_api;
|
||||
protected $sendgrid_from;
|
||||
protected $sendgrid_name;
|
||||
|
||||
public function __construct() {
|
||||
global $savvyext;
|
||||
$this->api_url = $savvyext->cfgReadChar('sendgrid.api_url');
|
||||
$this->key = $savvyext->cfgReadChar('sendgrid.api_key');
|
||||
|
||||
// connect replica database
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$db_conn = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$this->replica_conn = pg_connect($db_conn);
|
||||
|
||||
// get range of days to retrieve data
|
||||
$this->_2week = self::getDaysOfWeek( $week = -2 );
|
||||
$this->_1week = self::getDaysOfWeek( $week = -1 );
|
||||
|
||||
// sendgrid api
|
||||
$this->sendgrid_api = $savvyext->cfgReadChar('mailsend.api_key');
|
||||
$this->sendgrid_from = $savvyext->cfgReadChar('mailsend.from');
|
||||
$this->sendgrid_name = $savvyext->cfgReadChar('mailsend.name');
|
||||
}
|
||||
|
||||
/**
|
||||
* Write errors log
|
||||
* @param string $action action name
|
||||
* @param string $message error message
|
||||
* @return
|
||||
*/
|
||||
private static function logs( $message ) {
|
||||
$log = 'Date: ' .date("F j, Y, g:i a").PHP_EOL.
|
||||
'Attempt: '.PHP_EOL.
|
||||
sprintf('%s', is_array($message) ? json_encode($message): $message).PHP_EOL.
|
||||
'-------------------------'.PHP_EOL;
|
||||
file_put_contents( './logs/log_'.date('j.n.Y').'log', $log, FILE_APPEND );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return range days from monday to sunday of week
|
||||
* @param number $weekOffset number of week
|
||||
* @return array
|
||||
*/
|
||||
private static function getDaysOfWeek( $weekOffset ) {
|
||||
$date = new DateTime();
|
||||
$date->setIsoDate( $date->format('o'), $date->format('W') + $weekOffset );
|
||||
|
||||
return array(
|
||||
'monday' => $date->format('Y-m-d'),
|
||||
'sunday' => $date->modify('+6 day')->format('Y-m-d')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Separation array by range of dates
|
||||
* @param array $datas list data need to be separation
|
||||
* @param string $start start date
|
||||
* @param string $end end date
|
||||
* @return array new arrays
|
||||
*/
|
||||
private static function separationByDates( $datas, $start, $end ) {
|
||||
$new_array = array();
|
||||
foreach ( $datas as $key => $data ) {
|
||||
if ( $start <= $data['dates'] and $data['dates'] <= $end ) {
|
||||
array_push( $new_array, $data );
|
||||
unset( $datas[$key] );
|
||||
}
|
||||
}
|
||||
|
||||
return array( 'old_array' => $datas, 'new_array' => $new_array );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the time to run the cronjob
|
||||
* @return bool
|
||||
*/
|
||||
private static function check_weekly_time() {
|
||||
$timestamp = time();
|
||||
if ( date( 'D', $timestamp ) === 'Mon' ) {
|
||||
return true;
|
||||
}
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare cURL to call SendGrid API
|
||||
* @param string|null $endpoint api endpoint
|
||||
* @param array $params api params
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getSendgrid(string $endpoint = null, $params = array()) {
|
||||
// prepare url api
|
||||
$api_call = sprintf( '%s%s?%s', $this->api_url, $endpoint, http_build_query($params) );
|
||||
$ch = curl_init($api_call);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_VERBOSE, false);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
||||
'Content-Type: application/json',
|
||||
'Authorization: ' . $this->key
|
||||
));
|
||||
|
||||
// check cURL error
|
||||
$error = curl_error($ch);
|
||||
if ($error) {
|
||||
throw new Exception('Response with errors: ' . is_array($error) ? json_decode($error) : $error );
|
||||
}
|
||||
|
||||
$response = json_decode( curl_exec($ch), true );
|
||||
if (isset($response['errors'])) {
|
||||
$message = is_array($response['errors']) ? json_decode($response['errors']) : response['errors'];
|
||||
throw new Exception('Response with errors: ' . $message);
|
||||
}
|
||||
|
||||
if (isset($results['results']) && !count($results['results'])) {
|
||||
throw new Exception('Response with empty data');
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* execute pg query
|
||||
* @param string $query sql query
|
||||
* @return array results
|
||||
*/
|
||||
protected function execute_pg_query( $query ) {
|
||||
try {
|
||||
$do = pg_query( $this->replica_conn, $query );
|
||||
if ( $errors = pg_last_error( $this->replica_conn ) ) {
|
||||
throw new Exception( $errors );
|
||||
}
|
||||
$results = pg_fetch_all( $do );
|
||||
if ( ! $results ) {
|
||||
throw new Exception( 'Results not found!' );
|
||||
}
|
||||
// Separation results by dates
|
||||
$results = self::separationByDates( $results, $this->_1week['monday'], $this->_1week['sunday'] );
|
||||
return $results;
|
||||
} catch (Exception $e) {
|
||||
self::logs('Errors', $e->getMessage());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate chart image
|
||||
* @return string image src
|
||||
*/
|
||||
protected function generate_chart_images( $chartLabels, $chartValues ) {
|
||||
$chartConfig = array(
|
||||
'type' => 'line',
|
||||
'backgroundColor' => 'transparent',
|
||||
'data' => array(
|
||||
'labels' => $chartLabels,
|
||||
'datasets' => array(
|
||||
array(
|
||||
'label' => sprintf( 'from %s - to %s', $this->_2week['monday'], $this->_2week['sunday'] ),
|
||||
'backgroundColor' => '#36A2EB',
|
||||
'borderColor' => '#36A2EB',
|
||||
'borderDash' => [5, 5],
|
||||
'fill' => false,
|
||||
'data' => array_values( $chartValues['old_value'] )
|
||||
),
|
||||
array(
|
||||
'label' => sprintf( 'from %s - to %s', $this->_1week['monday'], $this->_1week['sunday'] ),
|
||||
'backgroundColor' => '#F93784',
|
||||
'borderColor' => '#F93784',
|
||||
'fill' => false,
|
||||
'data' => array_values( $chartValues['new_value'] )
|
||||
)
|
||||
)
|
||||
),
|
||||
'options' => array(
|
||||
'responsive' => true,
|
||||
'plugins' => array(
|
||||
'datalabels' => array(
|
||||
'display' => true,
|
||||
'align' => 'top',
|
||||
'backgroundColor' => '#FFFFFF',
|
||||
'borderRadius' => 3,
|
||||
'borderWidth' => 1,
|
||||
'borderColor' => '#B8B8B8',
|
||||
'font' => array(
|
||||
'size' => 8
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
$chartConfig = json_encode( $chartConfig );
|
||||
$result = preg_replace( '/(")(function.*?})(")/m', '$2', $chartConfig);
|
||||
$imageUrl = 'https://quickchart.io/chart?w=500&h=200&c=' . urlencode($result);
|
||||
|
||||
return $imageUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tracking installed os
|
||||
* @return array
|
||||
*/
|
||||
public function get_tracking_installed() {
|
||||
// prepare sql to retrieve data
|
||||
// by range days
|
||||
$query = sprintf("
|
||||
SELECT md.created as dates,
|
||||
SUM(case when mdp.platform = 'Android' then 1 else 0 end) as Android,
|
||||
SUM(case when mdp.platform = 'iOS' then 1 else 0 end) as iOS
|
||||
FROM members_devices md
|
||||
LEFT JOIN members_device_platforms mdp ON md.platform_id = mdp.id
|
||||
WHERE md.created BETWEEN '%s' AND '%s'
|
||||
AND md.member_id IN (SELECT id FROM members WHERE status = 1)
|
||||
GROUP BY dates
|
||||
", $this->_2week['monday'], $this->_1week['sunday']);
|
||||
// run query
|
||||
$results = $this->execute_pg_query( $query );
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number users who subscribed the deals
|
||||
* @return int numbers
|
||||
*/
|
||||
public function get_subscribe_deals() {
|
||||
$query = sprintf("
|
||||
SELECT mca.subscribe as dates, count(DISTINCT m.email)
|
||||
FROM members_card_assign mca
|
||||
LEFT JOIN main_cards mc ON mca.card_id = mc.id
|
||||
LEFT JOIN members m ON mca.member_id = m.id
|
||||
WHERE mca.subscribe IS NOT NULL AND mc.button1_action IN ('GOOFFERS')
|
||||
AND mca.subscribe BETWEEN '%s' AND '%s'
|
||||
GROUP BY dates
|
||||
", $this->_2week['monday'], $this->_1week['sunday']);
|
||||
// run query
|
||||
$results = $this->execute_pg_query( $query );
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number user who filled profile
|
||||
* @return int numbers
|
||||
*/
|
||||
public function get_user_filled_profile() {
|
||||
$query = sprintf("
|
||||
SELECT greatest(m.added, mba.added, ot.created, md.created) as Dates, count(DISTINCT m.email)
|
||||
FROM members m
|
||||
INNER JOIN members_bank_accounts mba ON m.id = mba.member_id
|
||||
INNER JOIN oauth2_tokens ot ON m.id = ot.member_id
|
||||
INNER JOIN members_devices md on m.id = md.member_id
|
||||
WHERE ((m.max_budget <> 0) IS NOT FALSE AND mba.status = 1 AND md.player_id is not null)
|
||||
AND (greatest(m.added, mba.added, ot.created, md.created) BETWEEN '%s' AND '%s')
|
||||
GROUP BY Dates
|
||||
", $this->_2week['monday'], $this->_1week['sunday'] );
|
||||
// run query
|
||||
$results = $this->execute_pg_query( $query );
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sendgrid tracking data
|
||||
* @return array properties of data
|
||||
*/
|
||||
public function get_sendgrid_tracking() {
|
||||
try {
|
||||
$params = array(
|
||||
'aggregated_by' => 'week',
|
||||
'start_date' => $this->_2week['monday'],
|
||||
'end_date' => $this->_1week['sunday']
|
||||
);
|
||||
$results = $this->getSendgrid( $endpoint = 'stats', $params );
|
||||
// check error api call
|
||||
if ( isset( $results['errors'] ) ) {
|
||||
$message = $results['errors'][0]['message'];
|
||||
throw new Exception( $message );
|
||||
}
|
||||
$combineResults = array();
|
||||
foreach ( $results as $key => $value ) {
|
||||
$combineResults[] = array(
|
||||
'dates' => $value['date'],
|
||||
'data' => $value['stats'][0]['metrics']
|
||||
);
|
||||
}
|
||||
$results = self::separationByDates( $combineResults, $this->_1week['monday'], $this->_1week['sunday'] );
|
||||
return $results;
|
||||
} catch (Exception $e) {
|
||||
self::logs($action_name, $e->getMessage());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* BKO tracking data
|
||||
* @return string chart image
|
||||
*/
|
||||
public function bko_tracking() {
|
||||
// tracking install device
|
||||
$install = $this->get_tracking_installed();
|
||||
// tracking user subscribe deals
|
||||
$subscribe = $this->get_subscribe_deals();
|
||||
// tracking user filled profile
|
||||
$profile = $this->get_user_filled_profile();
|
||||
|
||||
$data = array(
|
||||
'old_value' => array(
|
||||
'android' => count( array_filter( $install['old_array'], function($e) {return $e['android'] > 0; } ) ),
|
||||
'ios' => count( array_filter( $install['old_array'], function($e) {return $e['ios'] > 0; } ) ),
|
||||
'subs' => count( $subscribe['old_array'] ),
|
||||
'profile' => count( $profile['old_array'] )
|
||||
),
|
||||
'new_value' => array(
|
||||
'android' => count( array_filter( $install['new_array'], function($e) {return $e['android'] > 0; } ) ),
|
||||
'ios' => count( array_filter( $install['new_array'], function($e) {return $e['ios'] > 0; } ) ),
|
||||
'subs' => count( $subscribe['new_array'] ),
|
||||
'profile' => count( $profile['new_array'] )
|
||||
)
|
||||
);
|
||||
$labels = array( 'Android install', 'iOS install', 'Subscribe deals', 'Filled profile' );
|
||||
// get chart image
|
||||
$imgSrc = $this->generate_chart_images( $labels, $data );
|
||||
return $imgSrc;
|
||||
}
|
||||
|
||||
/**
|
||||
* SendGrid tracking data
|
||||
* @return string chart image
|
||||
*/
|
||||
public function sendgrid_tracking() {
|
||||
$tracking = $this->get_sendgrid_tracking();
|
||||
if ( ! $tracking ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$data = array();
|
||||
foreach ( $tracking as $key => $item ) {
|
||||
$data[ $key ] = array(
|
||||
'delivered' => array_sum( array_column( $item[0], 'delivered') ),
|
||||
'processed' => array_sum( array_column( $item[0], 'processed') ),
|
||||
'unique_clicks' => array_sum( array_column( $item[0], 'unique_clicks') ),
|
||||
'unique_opens' => array_sum( array_column( $item[0], 'unique_opens') ),
|
||||
);
|
||||
}
|
||||
$data = array(
|
||||
'old_value' => $data['old_array'],
|
||||
'new_value' => $data['new_array']
|
||||
);
|
||||
$labels = array( 'Delivered', 'Processed', 'Unique Clicks', 'Unique Opens' );
|
||||
// get chart image
|
||||
$imgSrc = $this->generate_chart_images( $labels, $data );
|
||||
return $imgSrc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send custom email report
|
||||
* @return mixed
|
||||
*/
|
||||
public function sendEmail() {
|
||||
// check weekly report time
|
||||
self::check_weekly_time();
|
||||
|
||||
$bko_tracking = $this->bko_tracking();
|
||||
$sendgrid_tracking = $this->sendgrid_tracking();
|
||||
// include email template
|
||||
ob_start();
|
||||
require_once('./email/custom-report.php');
|
||||
$mail_html = ob_get_clean();
|
||||
|
||||
try {
|
||||
$email = new \SendGrid\Mail\Mail();
|
||||
$email->setFrom( $this->sendgrid_from, $this->sendgrid_name );
|
||||
$email->setSubject( 'Float Weekly Report' );
|
||||
$toEmails = array(
|
||||
'stew@float.sg' => 'Stew',
|
||||
'olu@float.sg' => 'Olu',
|
||||
'valeriy@float.sg' => 'Valeriy',
|
||||
'tokslaw@float.sg' => 'Tokslaw',
|
||||
'jeff@float.sg' => 'Jeff',
|
||||
'chelsea@float.sg' => 'Chelsea'
|
||||
);
|
||||
$email->addTos( $toEmails );
|
||||
$email->addContent( 'text/html', $mail_html );
|
||||
$sendgrid = new \SendGrid( $this->sendgrid_api );
|
||||
$response = $sendgrid->send( $email );
|
||||
if ( $response->statusCode() !== 202 ) {
|
||||
throw new Exception( 'Send custom report get errors' );
|
||||
}
|
||||
echo 'Success';
|
||||
} catch (Exception $e) {
|
||||
echo 'Custom report could not be sent. Mailer Error: ', $e->getMessage();
|
||||
self::logs( 'Custom report could not be sent. Mailer Error: ', $e->getMessage() );
|
||||
exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$api = new Custom_Report();
|
||||
$api->sendEmail();
|
||||
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
$job_name = pathinfo(__FILE__, PATHINFO_FILENAME);
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job is starting.\n";
|
||||
|
||||
require('lock.php');
|
||||
$lock_file = lock_pid_file();
|
||||
|
||||
set_time_limit(0); // No limit!
|
||||
|
||||
require('../backend.php');
|
||||
require('common/Logger.php');
|
||||
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
$encryptionAlg = $savvyext->cfgReadChar('encryption.algorithm');
|
||||
$encryptionKey = $savvyext->cfgReadChar('encryption.key');
|
||||
$encryptionIV = $savvyext->cfgReadChar('encryption.iv');
|
||||
|
||||
$baseURL = $savvyext->cfgReadChar('system.api_url');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$q = "SELECT * FROM quotes WHERE completed IS NULL or travel_date IS NULL";
|
||||
//$q.= " AND transport_provider_id=2 "; // DEBUG
|
||||
$q.= " ORDER BY created DESC";
|
||||
|
||||
$r = pg_query($conn, $q);
|
||||
|
||||
if ($r && pg_num_rows($r)) {
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
list($res,$cost) = check_quote($f["id"]);
|
||||
if ($res>0) {
|
||||
if ($res==2) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote ${cost} for ID#".$f["id"].".\n";
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Unexpected result for ID#".$f["id"].".\n";
|
||||
}
|
||||
} else {
|
||||
if ($res==-1) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Final quote failure for ID#".$f["id"].".\n";
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] check_quote failed(${res}) for ID#".$f["id"].".\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function check_quote($id) {
|
||||
global $job_name;
|
||||
if ($id>0) { // minimal sanity
|
||||
list($payload,$decrypted,$result,$body) = main_api_get("/trips/api/quote/",$id);
|
||||
$log = [
|
||||
'job_name' => $job_name,
|
||||
'function' => __FUNCTION__,
|
||||
'request' => "/trips/api/quote/".$id,
|
||||
'input_data' => $id,
|
||||
'response_data' => $payload,
|
||||
];
|
||||
Logger::debug($log);
|
||||
if (is_array($payload) && array_key_exists('id',$payload) && $payload['id']>0) {
|
||||
if (array_key_exists('cost',$payload) && $payload['cost']>0) {
|
||||
return [2,$payload['cost']];
|
||||
}
|
||||
if (array_key_exists('travel_date',$payload) && $payload['travel_date']!='') {
|
||||
return [-1, NULL];
|
||||
}
|
||||
} else {
|
||||
return [-2, NULL];
|
||||
}
|
||||
}
|
||||
return [-3, NULL];
|
||||
}
|
||||
|
||||
function main_api_get($endpoint,$input) {
|
||||
global $baseURL, $encryptionAlg, $encryptionKey, $encryptionIV, $httpAuthToken;
|
||||
if ($endpoint!="" && $input!="") { // minimal sanity
|
||||
sleep(1);
|
||||
$url = $baseURL . $endpoint . $input;
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_VERBOSE, false);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
||||
'Content-Type: application/json',
|
||||
'Authorization: Server-Token ' . $httpAuthToken,
|
||||
"client_id: BATCH"
|
||||
)
|
||||
);
|
||||
|
||||
$body = curl_exec($ch);
|
||||
$result = json_decode($body,true);
|
||||
|
||||
$decrypted = openssl_decrypt(
|
||||
hex2bin(
|
||||
$result['payload']
|
||||
),
|
||||
$encryptionAlg,
|
||||
$encryptionKey,
|
||||
OPENSSL_RAW_DATA,
|
||||
$encryptionIV
|
||||
);
|
||||
$payload = json_decode($decrypted, true);
|
||||
return [$payload,$decrypted,$result,$body];
|
||||
}
|
||||
return [NULL,NULL,NULL,NULL];
|
||||
}
|
||||
|
||||
unlock_pid_file($lock_file);
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job complete.\n";
|
||||
@@ -0,0 +1,216 @@
|
||||
<?php
|
||||
$job_name = pathinfo(__FILE__, PATHINFO_FILENAME);
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job is starting.\n";
|
||||
|
||||
require('../lock.php');
|
||||
$lock_file = lock_pid_file();
|
||||
|
||||
set_time_limit(0); // No limit!
|
||||
|
||||
require('../../backend.php');
|
||||
require('../common/QuoteApi.php');
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
$encryptionAlg = $savvyext->cfgReadChar('encryption.algorithm');
|
||||
$encryptionKey = $savvyext->cfgReadChar('encryption.key');
|
||||
$encryptionIV = $savvyext->cfgReadChar('encryption.iv');
|
||||
|
||||
$baseURL = $savvyext->cfgReadChar('system.api_url');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$member_id = 0;
|
||||
$country = 'SG';
|
||||
$timezone = 'UTC';
|
||||
$distance = 1.2; // km
|
||||
$city_id = 1; // Singapore
|
||||
$pool = 1; // Main pool - does not matter (we do not have pools here...)
|
||||
$areas_count = 28;
|
||||
|
||||
$transport_providers = [3,4,5];
|
||||
|
||||
CONST SELECT_DISTINCT_AREAS = <<< EOS
|
||||
WITH whole_hours AS (
|
||||
SELECT hour, area_start_id, area_end_id, transport_provider_id
|
||||
FROM generate_series(0, 23) hour,
|
||||
generate_series(1, $1) area_start_id,
|
||||
generate_series(1, $1) area_end_id,
|
||||
unnest(ARRAY[3,4,5]) transport_provider_id
|
||||
ORDER BY transport_provider_id, area_start_id, area_end_id, hour
|
||||
)
|
||||
SELECT DISTINCT ah.area_start_id as area_id FROM whole_hours ah
|
||||
LEFT JOIN geofence_area_average_quotes gaaq ON ah.hour = gaaq.hour
|
||||
AND ah.area_start_id = gaaq.area_start_id AND ah.area_end_id = gaaq.area_end_id AND ah.transport_provider_id =gaaq.transport_provider_id
|
||||
WHERE gaaq.hour IS NULL
|
||||
AND ah.hour = date_part('hour', timezone($2, now()))
|
||||
UNION
|
||||
SELECT DISTINCT ah.area_end_id as area_id FROM whole_hours ah
|
||||
LEFT JOIN geofence_area_average_quotes gaaq ON ah.hour = gaaq.hour
|
||||
AND ah.area_start_id = gaaq.area_start_id AND ah.area_end_id = gaaq.area_end_id AND ah.transport_provider_id =gaaq.transport_provider_id
|
||||
WHERE gaaq.hour IS NULL
|
||||
AND ah.hour = date_part('hour', timezone($2, now()))
|
||||
ORDER BY area_id
|
||||
EOS;
|
||||
|
||||
CONST SELECT_MISSED_AREAS = <<< EOS
|
||||
WITH whole_hours AS (
|
||||
SELECT hour, area_start_id, area_end_id, transport_provider_id
|
||||
FROM generate_series(0, 23) hour,
|
||||
generate_series(1, $1) area_start_id,
|
||||
generate_series(1, $1) area_end_id,
|
||||
unnest(ARRAY[3,4,5]) transport_provider_id
|
||||
ORDER BY transport_provider_id, area_start_id, area_end_id, hour
|
||||
)
|
||||
SELECT DISTINCT ah.* FROM whole_hours ah
|
||||
LEFT JOIN geofence_area_average_quotes gaaq ON ah.hour = gaaq.hour
|
||||
AND ah.area_start_id = gaaq.area_start_id AND ah.area_end_id = gaaq.area_end_id AND ah.transport_provider_id =gaaq.transport_provider_id
|
||||
WHERE gaaq.hour IS NULL
|
||||
AND ah.hour = date_part('hour', timezone($2, now()))
|
||||
ORDER BY ah.transport_provider_id, ah.area_start_id, ah.area_end_id, ah.hour
|
||||
EOS;
|
||||
|
||||
$transport_providers_param = "{".implode(",", $transport_providers). "}";
|
||||
$area_ids = [];
|
||||
$resp = pg_query_params($conn, SELECT_DISTINCT_AREAS, [
|
||||
$areas_count,
|
||||
$timezone,
|
||||
// $transport_providers_param
|
||||
]);
|
||||
if ($resp && pg_num_rows($resp)) {
|
||||
while ($row=pg_fetch_row($resp)) {
|
||||
$area_ids[] = $row[0];
|
||||
}
|
||||
}
|
||||
QuoteApi::$job_name=$job_name;
|
||||
if (count($area_ids)) {
|
||||
// Step 1 & 2: area locations
|
||||
$locations_start = [];
|
||||
$locations_end = [];
|
||||
$area_locations = [];
|
||||
$q = "SELECT id, latitude, longitude, name, boundaries FROM geofence_area WHERE country='${country}' AND city_id=${city_id} AND district='t' AND id IN (".implode (", ", $area_ids).") ORDER BY id";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
$q1 = "select * from address where country='${country}' AND (%s) order by random() limit 2";
|
||||
while ($f=pg_fetch_row($r)) {
|
||||
// Singapore areas are postal!
|
||||
$b = json_decode($f[4],true); // {"postal_code":["60","61","62","63","64"]}
|
||||
$q2 = [];
|
||||
foreach ($b["postal_code"] as $code) {
|
||||
$q2[] = "LEFT(postal,".strlen($code).")='${code}'";
|
||||
}
|
||||
$r1 = pg_query($conn, sprintf($q1,implode(" OR ",$q2)));
|
||||
if ($r1 && pg_num_rows($r1)>1 && $f1=pg_fetch_assoc($r1)) {
|
||||
$locations_start[$f[0]] = $f1;
|
||||
$f1 = pg_fetch_assoc($r1);
|
||||
$locations_end[$f[0]] = $f1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$providers_areas = [];
|
||||
$resp = pg_query_params($conn, SELECT_MISSED_AREAS, [
|
||||
$areas_count,
|
||||
$timezone,
|
||||
]);
|
||||
if ($resp && pg_num_rows($resp)) {
|
||||
while ($row=pg_fetch_row($resp)) {
|
||||
|
||||
$star_area_id = $row[1];
|
||||
$end_area_id = $row[2];
|
||||
$transport_provider = $row[3];
|
||||
|
||||
if (!array_key_exists($transport_provider,$providers_areas)) {
|
||||
$providers_areas[$transport_provider] = [];
|
||||
}
|
||||
$d = distanceBetweenTwoGpsCoordinates(
|
||||
$locations_start[$star_area_id]["latitude"], $locations_start[$star_area_id]["longitude"],
|
||||
$locations_end[$end_area_id]["latitude"], $locations_end[$end_area_id]["longitude"],
|
||||
"K"
|
||||
);
|
||||
if ($locations_start[$star_area_id]["id"] != $locations_end[$end_area_id]["id"]
|
||||
&& $d > $distance || $star_area_id == $end_area_id ) {
|
||||
array_push($providers_areas[$transport_provider],
|
||||
[
|
||||
"start_area" => $locations_start[$star_area_id],
|
||||
"end_area" => $locations_end[$end_area_id]
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
// echo json_encode($providers_areas, JSON_PRETTY_PRINT) .PHP_EOL;
|
||||
}
|
||||
|
||||
if (count($providers_areas) > 0) {
|
||||
// Step 4: Schedule quotes
|
||||
$checkQuotes = [];
|
||||
foreach ($providers_areas as $provider_id => $provider_areas) {
|
||||
foreach ($provider_areas as $areas) {
|
||||
$origin_id = $areas["start_area"]["id"];
|
||||
$destination_id = $areas["end_area"]["id"];
|
||||
$origin = $areas["start_area"]["address"];
|
||||
$destination = $areas["end_area"]["address"];
|
||||
|
||||
$pool = $provider_id == 3 ? 2 : 1;
|
||||
|
||||
$q = "SELECT * FROM quotes ";
|
||||
$q.= " WHERE location_start_id=${origin_id} AND location_end_id=${destination_id} ";
|
||||
$q.= " AND transport_provider_id=${provider_id} AND cost>0 AND pool=${pool} ";
|
||||
$q.= " AND completed > (now() - '1 hour'::interval) ";
|
||||
$q.= " ORDER BY completed DESC LIMIT 1";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote ".$f["cost"]." already exists ID #".$f["id"]."\n";
|
||||
continue;
|
||||
}
|
||||
list($res,$id) = QuoteApi::schedule_quote($origin,$destination,$country,$member_id,$provider_id, 0,'t', $pool);
|
||||
if ($res>0) {
|
||||
if ($res==2) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote complete! ID #${id}\n";
|
||||
} else if ($res==1) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Scheduled quote ID #${id}\n";
|
||||
$checkQuotes[] = $id;
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Unexpected result for ID #${id} ($res)\n";
|
||||
}
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] schedule_quote failed: ${res}.\n";
|
||||
echo "[".date("Y-m-d H:i:s")."] $origin,$destination,$country,$member_id,$provider_id\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// Step 5: Check quotes
|
||||
foreach ($checkQuotes as $id) {
|
||||
list($res,$cost) = QuoteApi::check_quote($id);
|
||||
echo "[".date("Y-m-d H:i:s")."] Checking quote ID #${id} ($res) cost=${cost}\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function distanceBetweenTwoGpsCoordinates($lat1,$lon1,$lat2,$lon2,$unit) {
|
||||
//error_log("public function distanceBetweenTwoGpsCoordinates($lat1,$lon1,$lat2,$lon2,$unit)");
|
||||
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;
|
||||
$unit = strtoupper($unit);
|
||||
if ($unit == "K") {
|
||||
return ($miles * 1.609344);
|
||||
}
|
||||
if ($unit == "N") {
|
||||
($miles * 0.8684);
|
||||
}
|
||||
return $miles;
|
||||
}
|
||||
|
||||
unlock_pid_file($lock_file);
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job complete.\n";
|
||||
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
$job_name = pathinfo(__FILE__, PATHINFO_FILENAME);
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job is starting.\n";
|
||||
set_time_limit(0); // No limit!
|
||||
|
||||
require('../../backend.php');
|
||||
require('../common/QuoteApi.php');
|
||||
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
$encryptionAlg = $savvyext->cfgReadChar('encryption.algorithm');
|
||||
$encryptionKey = $savvyext->cfgReadChar('encryption.key');
|
||||
$encryptionIV = $savvyext->cfgReadChar('encryption.iv');
|
||||
|
||||
$baseURL = $savvyext->cfgReadChar('system.api_url');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$country = 'SG';
|
||||
$member_id = 0;
|
||||
|
||||
// ComfortDelGro & Gojek
|
||||
$transport_providers = [4,5];
|
||||
// Grab
|
||||
//$transport_providers = [3];
|
||||
|
||||
// Step 1: Load batch files
|
||||
$origins = load_batch_file("batch_quote_file_origins.txt");
|
||||
$destinations = load_batch_file("batch_quote_file_destinations.txt");
|
||||
|
||||
// Step 2: Geocode addresses
|
||||
$newOrigins = geocode_addresses($origins);
|
||||
$newDestinations = geocode_addresses($destinations);
|
||||
|
||||
// Step 3: Schedule quotes
|
||||
$checkQuotes = [];
|
||||
QuoteApi::$job_name = $job_name;
|
||||
foreach ($newOrigins as $origin_id=>$origin) {
|
||||
foreach ($newDestinations as $destination_id=>$destination) {
|
||||
foreach ($transport_providers as $transport_provider) {
|
||||
$q = "SELECT * FROM quotes ";
|
||||
$q.= " WHERE location_start_id=${origin_id} AND location_end_id=${destination_id} ";
|
||||
$q.= " AND transport_provider_id=${transport_provider} AND cost>0 ";
|
||||
$q.= " ORDER BY completed DESC LIMIT 1";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote ".$f["cost"]." already exists ID #".$f["id"]."\n";
|
||||
continue;
|
||||
}
|
||||
list($res,$id) = QuoteApi::schedule_quote($origin,$destination,$country,$member_id,$transport_provider);
|
||||
if ($res>0) {
|
||||
if ($res==2) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote complete! ID #${id}\n";
|
||||
} else if ($res==1) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Scheduled quote ID #${id}\n";
|
||||
$checkQuotes[] = $id;
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Unexpected result for ID #${id} ($res)\n";
|
||||
}
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] schedule_quote failed: ${res}.\n";
|
||||
echo "[".date("Y-m-d H:i:s")."] $origin,$destination,$country,$member_id,$transport_provider\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Check quotes
|
||||
foreach ($checkQuotes as $id) {
|
||||
list($res,$cost) = QuoteApi::check_quote($id);
|
||||
echo "[".date("Y-m-d H:i:s")."] Checking quote ID #${id} ($res) cost=${cost}\n";
|
||||
}
|
||||
|
||||
function load_batch_file($filename) {
|
||||
$results = [];
|
||||
$fn = fopen($filename,"r");
|
||||
while(! feof($fn)) {
|
||||
$result = fgets($fn);
|
||||
$results[] = trim($result);
|
||||
}
|
||||
fclose($fn);
|
||||
return $results;
|
||||
}
|
||||
|
||||
function geocode_addresses($addresses) {
|
||||
$geocodedAddresses = [];
|
||||
foreach ($addresses as $address) {
|
||||
$params = [
|
||||
"address" => $address,
|
||||
"member_id" => 0,
|
||||
"country" => "SG"
|
||||
];
|
||||
$input = http_build_query($params);
|
||||
list($payload,$decrypted,$result,$body) = main_api_get('/trips/api/geocode/?',$input);
|
||||
if (is_array($payload) && array_key_exists('geocode',$payload) && is_array($payload['geocode'])
|
||||
&& array_key_exists('id',$payload['geocode']) && $payload['geocode']['id']>0) {
|
||||
$geocodedAddresses[$payload['geocode']['id']] = $payload['geocode']['address'];
|
||||
}
|
||||
}
|
||||
return $geocodedAddresses;
|
||||
}
|
||||
|
||||
function main_api_get($endpoint,$input) {
|
||||
global $baseURL, $encryptionAlg, $encryptionKey, $encryptionIV, $httpAuthToken;
|
||||
if ($endpoint!="" && $input!="") { // minimal sanity
|
||||
sleep(1);
|
||||
$url = $baseURL . $endpoint . $input;
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_VERBOSE, false);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
||||
'Content-Type: application/json',
|
||||
'Authorization: Server-Token ' . $httpAuthToken,
|
||||
"client_id: BATCH"
|
||||
)
|
||||
);
|
||||
|
||||
$body = curl_exec($ch);
|
||||
$result = json_decode($body,true);
|
||||
|
||||
$decrypted = openssl_decrypt(
|
||||
hex2bin(
|
||||
$result['payload']
|
||||
),
|
||||
$encryptionAlg,
|
||||
$encryptionKey,
|
||||
OPENSSL_RAW_DATA,
|
||||
$encryptionIV
|
||||
);
|
||||
$payload = json_decode($decrypted, true);
|
||||
return [$payload,$decrypted,$result,$body];
|
||||
}
|
||||
return [NULL,NULL,NULL,NULL];
|
||||
}
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job complete.\n";
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
$job_name = pathinfo(__FILE__, PATHINFO_FILENAME);
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job is starting.\n";
|
||||
|
||||
set_time_limit(0); // No limit!
|
||||
|
||||
require('../../backend.php');
|
||||
require('../common/QuoteApi.php');
|
||||
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
$encryptionAlg = $savvyext->cfgReadChar('encryption.algorithm');
|
||||
$encryptionKey = $savvyext->cfgReadChar('encryption.key');
|
||||
$encryptionIV = $savvyext->cfgReadChar('encryption.iv');
|
||||
|
||||
$baseURL = $savvyext->cfgReadChar('system.api_url');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$country = 'SG';
|
||||
$member_id = 0;
|
||||
|
||||
// ComfortDelGro & Gojek
|
||||
$transport_providers = [4,5];
|
||||
// Grab
|
||||
$transport_providers = [3];
|
||||
QuoteApi::$job_name = $job_name;
|
||||
$q = "select id,automation_id from quotes where id>=11462 and id<=13761 and (cost<1 or cost is null)";
|
||||
$q = "select id,automation_id from quotes where id>=11462 and id<=13761 and (cost<1 or cost is null)";
|
||||
$r = pg_query($conn,$q);
|
||||
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
list($res,$cost) = QuoteApi::check_quote($f["id"]);
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$f["id"]."/".$f["automation_id"]." => ".$cost."\n";
|
||||
}
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job complete.\n";
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
Dempsey Hill, Dempsey Rd, #03-01 Blk 8D, Singapore 249679
|
||||
Botanic Gardens Mansion, 18 Taman Serasi, Singapore 257722
|
||||
Bandstand - Singapore Botanic Gardens, 6 Cluny Rd, Singapore 259573
|
||||
Palm Valley Gate, Tyersall Rd, Singapore
|
||||
Botanic Gardens Nassim Gate, 1B Cluny Rd, Singapore 259598
|
||||
IKEA Alexandra, 317 Alexandra Rd, Singapore 159965
|
||||
Anchorpoint Shopping Centre, 370 Alexandra Rd, Singapore 159953
|
||||
ABC Brickworks, 6 Jalan Bukit Merah, Singapore 150006
|
||||
Depot Road Zhen Shan Mei Claypot Laksa, 119 Bukit Merah Lane 1, #01-75 Fine Taste Eating House, Singapore 151119
|
||||
Alexandra Village, 1009 Bukit Merah Lane 3, Singapore 159723
|
||||
Haw Par Villa, 262 Pasir Panjang Rd, Singapore 118628
|
||||
TeleTech Park, 20 Science Park Rd, Singapore 117674
|
||||
Kopitiam, 1 Wholesale Centre #01-02 Blk, 1 Pasir Panjang Rd, Singapore 110001
|
||||
Zenxin Organic Food Singapore @ Pasir Panjang, 14 Pasir Panjang, #01-25, Wholesale Centre, Singapore 110014
|
||||
Queenstown MRT, 301 Commonwealth Ave, Singapore 149729
|
||||
Mr Bean, 301 Commonwealth Ave, #02-05, Singapore 149729
|
||||
Mei Ling Market & Food Centre, 159 Mei Ling St, Singapore 140159
|
||||
Vivarch Enrichment Group, Cendex Centre, 120 Lower Delta Rd, #12-13, Singapore 169208
|
||||
Connection One, 169 Bukit Merah Central, Singapore
|
||||
Redhill Market, 81 Redhill Ln, Singapore 150081
|
||||
Tiong Bahru MRT Station, 300 Tiong Bahru Rd, Singapore 168731
|
||||
SAFRA Mount Faber, 2 Telok Blangah Way, Singapore 098803
|
||||
LifestyleMart, 2 Telok Blangah Way, #02-07 SAFRA Mount Faber, Singapore 098803
|
||||
Giant Express Telok Blangah 8, #01-171 Telok Blangah Cres, Block 8, Singapore 090008
|
||||
Vivo City, 1 Harbourfront Walk, Singapore 098585
|
||||
HarbourFront Centre, 2 Maritime Square, Singapore 099255
|
||||
Seah Im Food Centre, 2 Seah Im Rd, Singapore 099114
|
||||
Harbourlights, 66 Telok Blangah Rd, Singapore 098830
|
||||
85 Redhill Ln, Singapore 150085
|
||||
SIME DARBY BUSINESS CENTRE, 315 Alexandra Rd
|
||||
Alexandra Hospital, 378 Alexandra Rd, Singapore 159964
|
||||
Everlast @ Queensway Shopping Centre, Queensway Shopping Center #01-23, 1 Queensway, Singapore 149053
|
||||
Block 79, 79 Ayer Rajah Crescent
|
||||
MDIS Campus, 501 Stirling Rd, Singapore 148951
|
||||
The Cheese Ark, 49 Stirling Rd, #01-489, Singapore 141049
|
||||
Tanglin Halt Neighbourhood Centre Historical Marker
|
||||
Sheng Siong, 88 Tanglin Halt Rd, Singapore 141088
|
||||
One North Station, 9 Ayer Rajah Avenue Singapore 138647 Ayer Rajah Ave, Singapore 138647
|
||||
Timbre+, 73A Ayer Rajah Crescent, JTC Launchpad, Singapore 139957
|
||||
Two Chefs Eating Place, 116 Commonwealth Cres, #01-129
|
||||
Dempsey Hill, Dempsey Rd, #03-01 Blk 8D, Singapore 249679
|
||||
Morsels, 25, #01-04 Dempsey Rd, Singapore 249670
|
||||
Huber's Butchery, 22 Dempsey Rd, Singapore 249679
|
||||
Raffles Holland V Mall, 118 Holland Ave, Singapore 278973
|
||||
The Nailist - Holland Road Shopping Centre, 211 Holland Avenue, Holland Rd, #03-31/32 Shopping centre, Singapore 278967
|
||||
Holland Village MRT Station, 200 Holland Avenue Singapore 278995 Holland Avenue, Singapore 278995
|
||||
Kai Life, Holland Avenue, 211 Holland Rd, #02-04 Shopping Centre, Singapore 278967
|
||||
Sunday Folks, 44 Jln Merah Saga, #01-52 Chip Bee Gardens, Singapore 278116
|
||||
Daily Scoop @ Chip Bee Garden, 70 Jln Merah Saga, 80, Singapore 278129
|
||||
Holland Drive Market and Food Centre, 44 Holland Dr, Singapore 270044
|
||||
Chip Bee Gardens, 43 Jln Merah Saga, Singapore 278115
|
||||
My Cosy Corner, 587 Bukit Timah Rd, #02-02 Coronation Plaza, Singapore 269707
|
||||
Singapore University of Social Sciences, 463 Clementi Rd, Blk C, Singapore 599494
|
||||
The Grandstand, 200 Turf Club Rd, Singapore 287994
|
||||
Premier Pitch Indoor, 200 Turf Club Road, Plot 9, Singapore 287994
|
||||
SkyPark Arena @ King Albert Park, 896 Dunearn Rd, #05-03 Tuan Sing Holdings, Singapore 589472
|
||||
Watsons Singapore, 1 Jalan Anak Bukit, Bukit Timah West, #B1-57, Singapore 588996
|
||||
Anytime Fitness Bukit Timah, Upper Bukit Timah Rd, #B1-01 Shopping Centre, Singapore 588179
|
||||
EQUIP, 78 Rifle Range Rd, Singapore 588384
|
||||
Sime Darby Centre, 896 Dunearn Rd, Singapore 589472
|
||||
Chin Huat, #01 Clementi Street 12, 30 zhizu massage centre, Singapore 120105
|
||||
West Coast Plaza, 154 West Coast Rd, Singapore 127371
|
||||
Sheng Siong, #01-144 Clementi West Street 2, Blk 720, Singapore 120720
|
||||
McDonald’s West Coast Park, 71 W Coast Ave, Singapore 126844
|
||||
Ayer Rajah Food Centre, W Coast Dr, Blk 503, Singapore 120503
|
||||
West Bowl Bowling, 12 W Coast Walk, Singapore 127157
|
||||
The Clementi Mall, 3155 Commonwealth Ave W, Singapore 129588
|
||||
Popular Bookstore, 2 Jurong East Street 21, #02-36 IMM Building, Singapore 609601
|
||||
Books Kinokuniya Jurong Store, 50 Jurong Gateway Rd, #04-23 JEM, Singapore 608549
|
||||
Westgate, 3 Gateway Dr, Singapore 608532
|
||||
Beng Hiang Restaurant, 135 Jurong Gateway Rd, #02-337, Singapore 600135
|
||||
Science Centre Singapore, 15 Science Centre Rd, Singapore 609081
|
||||
IMM, 2 Jurong East Street 21, Singapore 609601
|
||||
Sofzsleep, 21 Bukit Batok Cres, #24-82 Wecga Tower, Singapore 658065
|
||||
1345 Mookata, 25 Bukit Batok Crescent, Singapore 658077
|
||||
CopyPrinter Pte Ltd, Bukit Batok Cres, #09-04 Enterprise Center, No 20, Singapore 658080
|
||||
Unity Centre, 51 Bukit Batok Cres, Singapore 658077
|
||||
Acacia Lodge, 530-540 Bukit Batok Street 23, Singapore 659548
|
||||
West Mall, 1 Bukit Batok Central Link, Singapore 658713
|
||||
Bukit Batok MRT, 10 Bukit Batok Central, Singapore 659958
|
||||
Singapore Pools (Bukit Batok Central Branch), 642 Bukit Batok Central, #01-56, Singapore 188994
|
||||
McDonald's, 256 Jurong East Street 24, Singapore 600256
|
||||
Yuhua Village Market and Food Centre, 254 Jurong East Street 24, Singapore 600254
|
||||
Zai Shun Curry Fish Head, 253 Jurong East Street 24, #01-205, Singapore 600253
|
||||
@@ -0,0 +1,30 @@
|
||||
3 Conservatory Drive, Singapore 117376
|
||||
9 Engineering Drive 1, #07-26 EA, Singapore 117575
|
||||
4 Engineering Drive 3, Singapore 117583
|
||||
2 Engineering Drive 4, NUS Information Technology, Singapore 117584
|
||||
4 Architecture Dr, Singapore 117566 Architecture Dr, Singapore 117566
|
||||
4 Engineering Drive 4, Blk E5 #02-09, Singapore 117585 Engineering Drive 4, Singapore 117585
|
||||
12 Kent Ridge Cres, Singapore 119275
|
||||
11 Arts Link, #03-06 AS1, Singapore 117573
|
||||
3 Arts Link, Level 4 AS3, Singapore 117569
|
||||
5 Arts Link Block AS7, Level 5 The, Shaw Foundation Building, Singapore 117570
|
||||
9 Kent Ridge Dr, Singapore 119241
|
||||
15 Computing Dr, Singapore 117418
|
||||
3 Research Link, Singapore 117602
|
||||
15 Kent Ridge Dr, Singapore 119245
|
||||
21 Heng Mui Keng Terrace, Singapore 119613
|
||||
30 Heng Mui Keng Terrace, Singapore 119614
|
||||
29 Heng Mui Keng Terrace, Block D & E, Singapore 119620
|
||||
11 Science Park Rd, Singapore 117685
|
||||
27 Prince George's Park, National University of Singapore, Singapore 118425
|
||||
15 Prince George's Park, Singapore 118414
|
||||
1 Research Link, Singapore 117604
|
||||
31 Lower Kent Ridge Rd, Singapore 119078
|
||||
50 Kent Ridge Cres, Singapore 119279
|
||||
30 Lower Kent Ridge Rd, Singapore 119075
|
||||
21 Lower Kent Ridge Rd, Singapore 119077
|
||||
12 Science Drive 2, Singapore 117549
|
||||
10 Lower Kent Ridge Rd, Singapore 119076
|
||||
28 Medical Dr, Singapore 117456
|
||||
1E Kent Ridge Rd, Singapore 119228
|
||||
70 South Buona Vista Rd, Singapore 118176
|
||||
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
$job_name = pathinfo(__FILE__, PATHINFO_FILENAME);
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job is starting.\n";
|
||||
|
||||
set_time_limit(0); // No limit!
|
||||
|
||||
require('../../backend.php');
|
||||
require('../common/QuoteApi.php');
|
||||
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
$encryptionAlg = $savvyext->cfgReadChar('encryption.algorithm');
|
||||
$encryptionKey = $savvyext->cfgReadChar('encryption.key');
|
||||
$encryptionIV = $savvyext->cfgReadChar('encryption.iv');
|
||||
|
||||
$baseURL = $savvyext->cfgReadChar('system.api_url');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$member_id = 0;
|
||||
$country = 'SG';
|
||||
$timezone = 1; // Asia/Singapore
|
||||
$distance = 2; // km
|
||||
$top_count = 15;
|
||||
|
||||
#Grab, ComfortDelGro, GOJEK
|
||||
$transport_providers = [3,4,5];
|
||||
$transport_providers = [4,5];
|
||||
|
||||
// Step 1: top 15 start locations
|
||||
$locations_start = [];
|
||||
$q = "SELECT COUNT(*) AS num, ROUND(b.latitude,2) AS lat, ROUND(b.longitude,2) AS lng ";
|
||||
$q.= " FROM parsedemail_item a LEFT JOIN address b ON b.id=a.location_start_id ";
|
||||
$q.= " WHERE b.timezone=${timezone} AND a.private='f' AND dup_id IS NULL ";
|
||||
$q.= " GROUP BY b.latitude, b.longitude ORDER BY num DESC LIMIT ${top_count}";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
$q1 = "select * from address where round(latitude,2)=%0.02f and round(longitude,2)=%0.02f order by random() limit 1";
|
||||
while ($f=pg_fetch_row($r)) {
|
||||
$r1 = pg_query($conn, sprintf($q1,$f[1],$f[2]));
|
||||
if ($r1 && pg_num_rows($r1) && $f1=pg_fetch_assoc($r1)) {
|
||||
$locations_start[] = $f1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: top 15 end locations
|
||||
$locations_end = [];
|
||||
$q = "SELECT COUNT(*) AS num, ROUND(b.latitude,2) AS lat, ROUND(b.longitude,2) AS lng ";
|
||||
$q.= " FROM parsedemail_item a LEFT JOIN address b ON b.id=a.location_end_id ";
|
||||
$q.= " WHERE b.timezone=${timezone} AND a.private='f' AND dup_id IS NULL ";
|
||||
$q.= " GROUP BY b.latitude, b.longitude ORDER BY num DESC LIMIT ${top_count}";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
$q1 = "select * from address where round(latitude,2)=%0.02f and round(longitude,2)=%0.02f order by random() limit 1";
|
||||
while ($f=pg_fetch_row($r)) {
|
||||
$r1 = pg_query($conn, sprintf($q1,$f[1],$f[2]));
|
||||
if ($r1 && pg_num_rows($r1) && $f1=pg_fetch_assoc($r1)) {
|
||||
$locations_end[] = $f1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Step 3: distance between locations (if makes sense to quote)
|
||||
$pairs = [];
|
||||
foreach ($locations_start as $location_start) {
|
||||
foreach ($locations_end as $location_end) {
|
||||
// Spheroid function in PHP to speed up
|
||||
$d = distanceBetweenTwoGpsCoordinates(
|
||||
$location_start["latitude"], $location_start["longitude"],
|
||||
$location_end["latitude"], $location_end["longitude"],
|
||||
"K"
|
||||
);
|
||||
if ($d>$distance) {
|
||||
$pairs[] = [$location_start, $location_end];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Schedule quotes
|
||||
$checkQuotes = [];
|
||||
QuoteApi::$job_name = $job_name;
|
||||
foreach ($pairs as list($location_start, $location_end)) {
|
||||
$origin_id = $location_start["id"];
|
||||
$destination_id = $location_end["id"];
|
||||
$origin = $location_start["address"];
|
||||
$destination = $location_end["address"];
|
||||
foreach ($transport_providers as $transport_provider) {
|
||||
$q = "SELECT * FROM quotes ";
|
||||
$q.= " WHERE location_start_id=${origin_id} AND location_end_id=${destination_id} ";
|
||||
$q.= " AND transport_provider_id=${transport_provider} AND cost>0 ";
|
||||
$q.= " AND completed>(current_date-1) ";
|
||||
$q.= " ORDER BY completed DESC LIMIT 1";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote ".$f["cost"]." already exists ID #".$f["id"]."\n";
|
||||
continue;
|
||||
}
|
||||
list($res,$id) = QuoteApi::schedule_quote($origin,$destination,$country,$member_id,$transport_provider);
|
||||
if ($res>0) {
|
||||
if ($res==2) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote complete! ID #${id}\n";
|
||||
} else if ($res==1) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Scheduled quote ID #${id}\n";
|
||||
$checkQuotes[] = $id;
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Unexpected result for ID #${id} ($res)\n";
|
||||
}
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] schedule_quote failed: ${res}.\n";
|
||||
echo "[".date("Y-m-d H:i:s")."] $origin,$destination,$country,$member_id,$transport_provider\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5: Check quotes
|
||||
foreach ($checkQuotes as $id) {
|
||||
list($res,$cost) = QuoteApi::check_quote($id);
|
||||
echo "[".date("Y-m-d H:i:s")."] Checking quote ID #${id} ($res) cost=${cost}\n";
|
||||
}
|
||||
|
||||
function distanceBetweenTwoGpsCoordinates($lat1,$lon1,$lat2,$lon2,$unit) {
|
||||
//error_log("public function distanceBetweenTwoGpsCoordinates($lat1,$lon1,$lat2,$lon2,$unit)");
|
||||
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;
|
||||
$unit = strtoupper($unit);
|
||||
if ($unit == "K") {
|
||||
return ($miles * 1.609344);
|
||||
}
|
||||
if ($unit == "N") {
|
||||
($miles * 0.8684);
|
||||
}
|
||||
return $miles;
|
||||
}
|
||||
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job complete.\n";
|
||||
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
$job_name = pathinfo(__FILE__, PATHINFO_FILENAME);
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job is starting.\n";
|
||||
require('../lock.php');
|
||||
$lock_file = lock_pid_file();
|
||||
|
||||
set_time_limit(0); // No limit!
|
||||
|
||||
require('../../backend.php');
|
||||
require('../common/QuoteApi.php');
|
||||
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
$encryptionAlg = $savvyext->cfgReadChar('encryption.algorithm');
|
||||
$encryptionKey = $savvyext->cfgReadChar('encryption.key');
|
||||
$encryptionIV = $savvyext->cfgReadChar('encryption.iv');
|
||||
|
||||
$baseURL = $savvyext->cfgReadChar('system.api_url');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$member_id = 0;
|
||||
$country = 'US';
|
||||
$timezone = 2; // America/Los_Angeles
|
||||
$distance = 2; // km
|
||||
$city_id = 1096; // San Francisco
|
||||
$pool = 2; // Dedicated pool
|
||||
|
||||
$transport_providers = [1,2]; // Uber, Lyft
|
||||
|
||||
// Step 1: start locations
|
||||
$locations_start = [];
|
||||
$q = "SELECT id,latitude,longitude,name FROM geofence_area WHERE country='${country}' AND city_id=${city_id} AND district='t' ORDER BY id";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
$q1 = "select * from address where round(latitude,2)=%0.02f and round(longitude,2)=%0.02f order by random() limit 1";
|
||||
while ($f=pg_fetch_row($r)) {
|
||||
$r1 = pg_query($conn, sprintf($q1,$f[1],$f[2]));
|
||||
if ($r1 && pg_num_rows($r1) && $f1=pg_fetch_assoc($r1)) {
|
||||
$locations_start[$f[0].'_'.$f[3]] = $f1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: end locations
|
||||
$locations_end = $locations_start;
|
||||
|
||||
// Step 3: distance between locations (if makes sense to quote)
|
||||
$pairs = [];
|
||||
foreach ($locations_start as $location_start) {
|
||||
foreach ($locations_end as $location_end) {
|
||||
// Spheroid function in PHP to speed up
|
||||
$d = distanceBetweenTwoGpsCoordinates(
|
||||
$location_start["latitude"], $location_start["longitude"],
|
||||
$location_end["latitude"], $location_end["longitude"],
|
||||
"K"
|
||||
);
|
||||
/* if ($d>$distance) {
|
||||
$pairs[] = [$location_start, $location_end];
|
||||
}//*/
|
||||
if ($location_start["id"]!=$location_end["id"]) {
|
||||
$pairs[] = [$location_start, $location_end];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Schedule quotes
|
||||
$checkQuotes = [];
|
||||
QuoteApi::$job_name=$job_name;
|
||||
foreach ($pairs as list($location_start, $location_end)) {
|
||||
$origin_id = $location_start["id"];
|
||||
$destination_id = $location_end["id"];
|
||||
$origin = $location_start["address"];
|
||||
$destination = $location_end["address"];
|
||||
foreach ($transport_providers as $transport_provider) {
|
||||
$q = "SELECT * FROM quotes ";
|
||||
$q.= " WHERE location_start_id=${origin_id} AND location_end_id=${destination_id} ";
|
||||
$q.= " AND transport_provider_id=${transport_provider} AND cost>0 AND pool=${pool}";
|
||||
//$q.= " AND completed>(current_date-1) ";
|
||||
$q.= " AND completed>(now() - '1 hour'::interval) ";
|
||||
$q.= " ORDER BY completed DESC LIMIT 1";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote ".$f["cost"]." already exists ID #".$f["id"]."\n";
|
||||
continue;
|
||||
}
|
||||
list($res,$id) = QuoteApi::schedule_quote($origin,$destination,$country,$member_id,$transport_provider, 0,'t',$pool);
|
||||
if ($res>0) {
|
||||
if ($res==2) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote complete! ID #${id}\n";
|
||||
} else if ($res==1) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Scheduled quote ID #${id}\n";
|
||||
$checkQuotes[] = $id;
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Unexpected result for ID #${id} ($res)\n";
|
||||
}
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] schedule_quote failed: ${res}.\n";
|
||||
echo "[".date("Y-m-d H:i:s")."] $origin,$destination,$country,$member_id,$transport_provider\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5: Check quotes
|
||||
foreach ($checkQuotes as $id) {
|
||||
list($res,$cost) = QuoteApi::check_quote($id);
|
||||
echo "[".date("Y-m-d H:i:s")."] Checking quote ID #${id} ($res) cost=${cost}\n";
|
||||
}
|
||||
|
||||
function distanceBetweenTwoGpsCoordinates($lat1,$lon1,$lat2,$lon2,$unit) {
|
||||
//error_log("public function distanceBetweenTwoGpsCoordinates($lat1,$lon1,$lat2,$lon2,$unit)");
|
||||
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;
|
||||
$unit = strtoupper($unit);
|
||||
if ($unit == "K") {
|
||||
return ($miles * 1.609344);
|
||||
}
|
||||
if ($unit == "N") {
|
||||
($miles * 0.8684);
|
||||
}
|
||||
return $miles;
|
||||
}
|
||||
|
||||
|
||||
unlock_pid_file($lock_file);
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job complete.\n";
|
||||
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
$job_name = pathinfo(__FILE__, PATHINFO_FILENAME);
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job is starting.\n";
|
||||
require('../lock.php');
|
||||
$lock_file = lock_pid_file();
|
||||
|
||||
set_time_limit(0); // No limit!
|
||||
|
||||
require('../../backend.php');
|
||||
require('../common/QuoteApi.php');
|
||||
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
$encryptionAlg = $savvyext->cfgReadChar('encryption.algorithm');
|
||||
$encryptionKey = $savvyext->cfgReadChar('encryption.key');
|
||||
$encryptionIV = $savvyext->cfgReadChar('encryption.iv');
|
||||
|
||||
$baseURL = $savvyext->cfgReadChar('system.api_url');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$member_id = 0;
|
||||
$country = 'US';
|
||||
$timezone = 2; // America/Los_Angeles
|
||||
$distance = 2; // km
|
||||
$city_id = 1096; // San Francisco
|
||||
$pool = 2; // Dedicated pool
|
||||
|
||||
$transport_providers = [8]; // Autocab
|
||||
|
||||
// Step 1: start locations
|
||||
$locations_start = [];
|
||||
$q = "SELECT id,latitude,longitude,name FROM geofence_area WHERE country='${country}' AND city_id=${city_id} AND district='t' ORDER BY id";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
$q1 = "select * from address where round(latitude,2)=%0.02f and round(longitude,2)=%0.02f order by random() limit 1";
|
||||
while ($f=pg_fetch_row($r)) {
|
||||
$r1 = pg_query($conn, sprintf($q1,$f[1],$f[2]));
|
||||
if ($r1 && pg_num_rows($r1) && $f1=pg_fetch_assoc($r1)) {
|
||||
$locations_start[$f[0].'_'.$f[3]] = $f1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: end locations
|
||||
$locations_end = $locations_start;
|
||||
|
||||
// Step 3: distance between locations (if makes sense to quote)
|
||||
$pairs = [];
|
||||
foreach ($locations_start as $location_start) {
|
||||
foreach ($locations_end as $location_end) {
|
||||
// Spheroid function in PHP to speed up
|
||||
$d = distanceBetweenTwoGpsCoordinates(
|
||||
$location_start["latitude"], $location_start["longitude"],
|
||||
$location_end["latitude"], $location_end["longitude"],
|
||||
"K"
|
||||
);
|
||||
/* if ($d>$distance) {
|
||||
$pairs[] = [$location_start, $location_end];
|
||||
}//*/
|
||||
if ($location_start["id"]!=$location_end["id"]) {
|
||||
$pairs[] = [$location_start, $location_end];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Schedule quotes
|
||||
$checkQuotes = [];
|
||||
QuoteApi::$job_name=$job_name;
|
||||
foreach ($pairs as list($location_start, $location_end)) {
|
||||
$origin_id = $location_start["id"];
|
||||
$destination_id = $location_end["id"];
|
||||
$origin = $location_start["address"];
|
||||
$destination = $location_end["address"];
|
||||
foreach ($transport_providers as $transport_provider) {
|
||||
$q = "SELECT * FROM quotes ";
|
||||
$q.= " WHERE location_start_id=${origin_id} AND location_end_id=${destination_id} ";
|
||||
$q.= " AND transport_provider_id=${transport_provider} AND cost>0 AND pool=${pool}";
|
||||
//$q.= " AND completed>(current_date-1) ";
|
||||
$q.= " AND completed>(now() - '1 hour'::interval) ";
|
||||
$q.= " ORDER BY completed DESC LIMIT 1";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote ".$f["cost"]." already exists ID #".$f["id"]."\n";
|
||||
continue;
|
||||
}
|
||||
list($res,$id) = QuoteApi::schedule_quote($origin,$destination,$country,$member_id,$transport_provider, 0,'t',$pool);
|
||||
if ($res>0) {
|
||||
if ($res==2) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote complete! ID #${id}\n";
|
||||
} else if ($res==1) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Scheduled quote ID #${id}\n";
|
||||
$checkQuotes[] = $id;
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Unexpected result for ID #${id} ($res)\n";
|
||||
}
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] schedule_quote failed: ${res}.\n";
|
||||
echo "[".date("Y-m-d H:i:s")."] $origin,$destination,$country,$member_id,$transport_provider\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5: Check quotes
|
||||
foreach ($checkQuotes as $id) {
|
||||
list($res,$cost) = QuoteApi::check_quote($id);
|
||||
echo "[".date("Y-m-d H:i:s")."] Checking quote ID #${id} ($res) cost=${cost}\n";
|
||||
}
|
||||
|
||||
function distanceBetweenTwoGpsCoordinates($lat1,$lon1,$lat2,$lon2,$unit) {
|
||||
//error_log("public function distanceBetweenTwoGpsCoordinates($lat1,$lon1,$lat2,$lon2,$unit)");
|
||||
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;
|
||||
$unit = strtoupper($unit);
|
||||
if ($unit == "K") {
|
||||
return ($miles * 1.609344);
|
||||
}
|
||||
if ($unit == "N") {
|
||||
($miles * 0.8684);
|
||||
}
|
||||
return $miles;
|
||||
}
|
||||
|
||||
|
||||
unlock_pid_file($lock_file);
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job complete.\n";
|
||||
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
$job_name = pathinfo(__FILE__, PATHINFO_FILENAME);
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job is starting.\n";
|
||||
|
||||
require('../lock.php');
|
||||
$lock_file = lock_pid_file();
|
||||
|
||||
set_time_limit(0); // No limit!
|
||||
require('../../backend.php');
|
||||
require('../common/QuoteApi.php');
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
$encryptionAlg = $savvyext->cfgReadChar('encryption.algorithm');
|
||||
$encryptionKey = $savvyext->cfgReadChar('encryption.key');
|
||||
$encryptionIV = $savvyext->cfgReadChar('encryption.iv');
|
||||
|
||||
$baseURL = $savvyext->cfgReadChar('system.api_url');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
$member_id = 0;
|
||||
$country = 'SG';
|
||||
$timezone = 1; // Asia/Singapore
|
||||
$distance = 1.2; // km
|
||||
$city_id = 1; // Singapore
|
||||
$pool = 1; // Main pool - does not matter (we do not have pools here...)
|
||||
|
||||
//$transport_providers = [3,4,5]; // Grab, ComfortDelGro, Gojek
|
||||
$transport_providers = [4,5]; // ComfortDelGro, Gojek
|
||||
|
||||
// Step 1 & 2: start & end locations
|
||||
$locations_start = [];
|
||||
$locations_end = [];
|
||||
$q = "SELECT id,latitude,longitude,name,boundaries FROM geofence_area WHERE country='${country}' AND city_id=${city_id} AND district='t' ORDER BY id";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
$q1 = "select * from address where country='${country}' AND (%s) order by random() limit 2";
|
||||
while ($f=pg_fetch_row($r)) {
|
||||
// Singapore areas are postal!
|
||||
$b = json_decode($f[4],true); // {"postal_code":["60","61","62","63","64"]}
|
||||
$q2 = [];
|
||||
foreach ($b["postal_code"] as $code) {
|
||||
$q2[] = "LEFT(postal,".strlen($code).")='${code}'";
|
||||
}
|
||||
$r1 = pg_query($conn, sprintf($q1,implode(" OR ",$q2)));
|
||||
if ($r1 && pg_num_rows($r1)>1 && $f1=pg_fetch_assoc($r1)) {
|
||||
$locations_start[$f[0].'_'.$f[3]] = $f1;
|
||||
$f1 = pg_fetch_assoc($r1);
|
||||
$locations_end[$f[0].'_'.$f[3]] = $f1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3: distance between locations (if makes sense to quote)
|
||||
$pairs = [];
|
||||
foreach ($locations_start as $location_start) {
|
||||
foreach ($locations_end as $location_end) {
|
||||
// Spheroid function in PHP to speed up
|
||||
$d = distanceBetweenTwoGpsCoordinates(
|
||||
$location_start["latitude"], $location_start["longitude"],
|
||||
$location_end["latitude"], $location_end["longitude"],
|
||||
"K"
|
||||
);
|
||||
/* if ($d>$distance) {
|
||||
$pairs[] = [$location_start, $location_end];
|
||||
}//*/
|
||||
if ($location_start["id"]!=$location_end["id"] && $d>$distance) {
|
||||
$pairs[] = [$location_start, $location_end];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Schedule quotes
|
||||
$checkQuotes = [];
|
||||
QuoteApi::$job_name = $job_name;
|
||||
foreach ($pairs as list($location_start, $location_end)) {
|
||||
$origin_id = $location_start["id"];
|
||||
$destination_id = $location_end["id"];
|
||||
$origin = $location_start["address"];
|
||||
$destination = $location_end["address"];
|
||||
foreach ($transport_providers as $transport_provider) {
|
||||
$q = "SELECT * FROM quotes ";
|
||||
$q.= " WHERE location_start_id=${origin_id} AND location_end_id=${destination_id} ";
|
||||
$q.= " AND transport_provider_id=${transport_provider} AND cost>0 AND pool=${pool}";
|
||||
//$q.= " AND completed>(current_date-1) ";
|
||||
$q.= " AND completed>(now() - '1 hour'::interval) ";
|
||||
$q.= " ORDER BY completed DESC LIMIT 1";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote ".$f["cost"]." already exists ID #".$f["id"]."\n";
|
||||
continue;
|
||||
}
|
||||
list($res,$id) = QuoteApi::schedule_quote($origin,$destination,$country,$member_id,$transport_provider, 0,'t', $pool);
|
||||
if ($res>0) {
|
||||
if ($res==2) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote complete! ID #${id}\n";
|
||||
} else if ($res==1) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Scheduled quote ID #${id}\n";
|
||||
$checkQuotes[] = $id;
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Unexpected result for ID #${id} ($res)\n";
|
||||
}
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] schedule_quote failed: ${res}.\n";
|
||||
echo "[".date("Y-m-d H:i:s")."] $origin,$destination,$country,$member_id,$transport_provider\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5: Check quotes
|
||||
foreach ($checkQuotes as $id) {
|
||||
list($res,$cost) = QuoteApi::check_quote($id);
|
||||
echo "[".date("Y-m-d H:i:s")."] Checking quote ID #${id} ($res) cost=${cost}\n";
|
||||
}
|
||||
|
||||
function distanceBetweenTwoGpsCoordinates($lat1,$lon1,$lat2,$lon2,$unit) {
|
||||
//error_log("public function distanceBetweenTwoGpsCoordinates($lat1,$lon1,$lat2,$lon2,$unit)");
|
||||
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;
|
||||
$unit = strtoupper($unit);
|
||||
if ($unit == "K") {
|
||||
return ($miles * 1.609344);
|
||||
}
|
||||
if ($unit == "N") {
|
||||
($miles * 0.8684);
|
||||
}
|
||||
return $miles;
|
||||
}
|
||||
|
||||
unlock_pid_file($lock_file);
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job complete.\n";
|
||||
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
$job_name = pathinfo(__FILE__, PATHINFO_FILENAME);
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job is starting.\n";
|
||||
|
||||
require('../lock.php');
|
||||
$lock_file = lock_pid_file();
|
||||
|
||||
set_time_limit(0); // No limit!
|
||||
|
||||
require('../../backend.php');
|
||||
require('../common/QuoteApi.php');
|
||||
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
$encryptionAlg = $savvyext->cfgReadChar('encryption.algorithm');
|
||||
$encryptionKey = $savvyext->cfgReadChar('encryption.key');
|
||||
$encryptionIV = $savvyext->cfgReadChar('encryption.iv');
|
||||
|
||||
$baseURL = $savvyext->cfgReadChar('system.api_url');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$member_id = 0;
|
||||
$country = 'SG';
|
||||
$timezone = 1; // Asia/Singapore
|
||||
$distance = 1.2; // km
|
||||
$city_id = 1; // Singapore
|
||||
$pool = 2; // Second pool
|
||||
|
||||
$transport_providers = [3]; // Grab
|
||||
|
||||
// Step 1 & 2: start & end locations
|
||||
$locations_start = [];
|
||||
$locations_end = [];
|
||||
$q = "SELECT id,latitude,longitude,name,boundaries FROM geofence_area WHERE country='${country}' AND city_id=${city_id} AND district='t' ORDER BY id";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
$q1 = "select * from address where country='${country}' AND (%s) order by random() limit 2";
|
||||
while ($f=pg_fetch_row($r)) {
|
||||
// Singapore areas are postal!
|
||||
$b = json_decode($f[4],true); // {"postal_code":["60","61","62","63","64"]}
|
||||
$q2 = [];
|
||||
foreach ($b["postal_code"] as $code) {
|
||||
$q2[] = "LEFT(postal,".strlen($code).")='${code}'";
|
||||
}
|
||||
$r1 = pg_query($conn, sprintf($q1,implode(" OR ",$q2)));
|
||||
if ($r1 && pg_num_rows($r1)>1 && $f1=pg_fetch_assoc($r1)) {
|
||||
$locations_start[$f[0].'_'.$f[3]] = $f1;
|
||||
$f1 = pg_fetch_assoc($r1);
|
||||
$locations_end[$f[0].'_'.$f[3]] = $f1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3: distance between locations (if makes sense to quote)
|
||||
$pairs = [];
|
||||
foreach ($locations_start as $location_start) {
|
||||
foreach ($locations_end as $location_end) {
|
||||
// Spheroid function in PHP to speed up
|
||||
$d = distanceBetweenTwoGpsCoordinates(
|
||||
$location_start["latitude"], $location_start["longitude"],
|
||||
$location_end["latitude"], $location_end["longitude"],
|
||||
"K"
|
||||
);
|
||||
/* if ($d>$distance) {
|
||||
$pairs[] = [$location_start, $location_end];
|
||||
}//*/
|
||||
if ($location_start["id"]!=$location_end["id"] && $d>$distance) {
|
||||
$pairs[] = [$location_start, $location_end];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Schedule quotes
|
||||
$checkQuotes = [];
|
||||
QuoteApi::$job_name=$job_name;
|
||||
foreach ($pairs as list($location_start, $location_end)) {
|
||||
$origin_id = $location_start["id"];
|
||||
$destination_id = $location_end["id"];
|
||||
$origin = $location_start["address"];
|
||||
$destination = $location_end["address"];
|
||||
foreach ($transport_providers as $transport_provider) {
|
||||
$q = "SELECT * FROM quotes ";
|
||||
$q.= " WHERE location_start_id=${origin_id} AND location_end_id=${destination_id} ";
|
||||
$q.= " AND transport_provider_id=${transport_provider} AND cost>0 AND pool=${pool}";
|
||||
//$q.= " AND completed>(current_date-1) ";
|
||||
$q.= " AND completed>(now() - '1 hour'::interval) ";
|
||||
$q.= " ORDER BY completed DESC LIMIT 1";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote ".$f["cost"]." already exists ID #".$f["id"]."\n";
|
||||
continue;
|
||||
}
|
||||
list($res,$id) = QuoteApi::schedule_quote($origin,$destination,$country,$member_id,$transport_provider,0,'t',$pool);
|
||||
if ($res>0) {
|
||||
if ($res==2) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote complete! ID #${id}\n";
|
||||
} else if ($res==1) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Scheduled quote ID #${id}\n";
|
||||
$checkQuotes[] = $id;
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Unexpected result for ID #${id} ($res)\n";
|
||||
}
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] schedule_quote failed: ${res}.\n";
|
||||
echo "[".date("Y-m-d H:i:s")."] $origin,$destination,$country,$member_id,$transport_provider\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5: Check quotes
|
||||
foreach ($checkQuotes as $id) {
|
||||
list($res,$cost) = QuoteApi::check_quote($id);
|
||||
echo "[".date("Y-m-d H:i:s")."] Checking quote ID #${id} ($res) cost=${cost}\n";
|
||||
}
|
||||
|
||||
function distanceBetweenTwoGpsCoordinates($lat1,$lon1,$lat2,$lon2,$unit) {
|
||||
//error_log("public function distanceBetweenTwoGpsCoordinates($lat1,$lon1,$lat2,$lon2,$unit)");
|
||||
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;
|
||||
$unit = strtoupper($unit);
|
||||
if ($unit == "K") {
|
||||
return ($miles * 1.609344);
|
||||
}
|
||||
if ($unit == "N") {
|
||||
($miles * 0.8684);
|
||||
}
|
||||
return $miles;
|
||||
}
|
||||
|
||||
|
||||
unlock_pid_file($lock_file);
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] batch_quote_singapore_districts job complete.\n";
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
$job_name = pathinfo(__FILE__, PATHINFO_FILENAME);
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job is starting.\n";
|
||||
|
||||
set_time_limit(0); // No limit!
|
||||
|
||||
require('../../backend.php');
|
||||
require('../common/QuoteApi.php');
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
$encryptionAlg = $savvyext->cfgReadChar('encryption.algorithm');
|
||||
$encryptionKey = $savvyext->cfgReadChar('encryption.key');
|
||||
$encryptionIV = $savvyext->cfgReadChar('encryption.iv');
|
||||
|
||||
$baseURL = $savvyext->cfgReadChar('system.api_url');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$country = 'SG';
|
||||
$member_id = 0;
|
||||
|
||||
// Grab, ComfortDelGro & Gojek
|
||||
$transport_providers = [/*3,*/4,5];
|
||||
|
||||
// Step 1: Load trips
|
||||
$q = "select b.*,c.address AS origin, d.address AS destination ";
|
||||
$q.= " from (select root_id,count(*) as count from trip_price_comparison where root_type=1 group by root_id) as a, ";
|
||||
$q.= " parsedemail_item b, address c, address d ";
|
||||
$q.= " where a.count=1 and b.id=a.root_id and b.private='f' and c.id=b.location_start_id and d.id=b.location_end_id and c.country='${country}' ";
|
||||
$q.= " and b.dup_id is null ";
|
||||
$q.= " order by b.travel_date desc";
|
||||
echo $q."\n";
|
||||
//exit();
|
||||
$r = pg_query($conn, $q);
|
||||
|
||||
// Step 3: Schedule quotes
|
||||
$checkQuotes = [];
|
||||
|
||||
QuoteApi::$job_name=$job_name;
|
||||
if ($r && pg_num_rows($r)) {
|
||||
$n = pg_num_rows($r);
|
||||
echo "[".date("Y-m-d H:i:s")."] Processing ".$n." trips.\n";
|
||||
$i = 0;
|
||||
while ($f = pg_fetch_assoc($r)) {
|
||||
$i++;
|
||||
echo "[".date("Y-m-d H:i:s")."] Processing ${i}/${n} (".sprintf("%0.02f",100.0*$i/$n).") trip id=".$f["id"].".\n";
|
||||
if ($f["location_start_id"]==$f["location_end_id"]) continue;
|
||||
$location_start_id=$f["location_start_id"];
|
||||
$location_end_id=$f["location_end_id"];
|
||||
foreach ($transport_providers as $transport_provider) {
|
||||
$q = "SELECT * FROM quotes ";
|
||||
$q.= " WHERE location_start_id=${location_start_id} AND location_end_id=${location_end_id} ";
|
||||
$q.= " AND transport_provider_id=${transport_provider} AND cost>0 ";
|
||||
$q.= " AND completed>(current_date-1) ORDER BY completed DESC LIMIT 1";
|
||||
$quotes = pg_query($conn, $q);
|
||||
if ($quotes && pg_num_rows($quotes) && $quote=pg_fetch_assoc($quotes)) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote ".$quote["cost"]." already exists ID #".$quote["id"]."\n";
|
||||
continue;
|
||||
}
|
||||
list($res,$id) = QuoteApi::schedule_quote($f["origin"],$f["destination"],$country,$member_id,$transport_provider);
|
||||
if ($res>0) {
|
||||
if ($res==2) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote complete! ID #${id}\n";
|
||||
} else if ($res==1) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Scheduled quote ID #${id}\n";
|
||||
$checkQuotes[] = $id;
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Unexpected result for ID #${id} ($res)\n";
|
||||
}
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] schedule_quote failed: ${res}.\n";
|
||||
echo "[".date("Y-m-d H:i:s")."] $origin,$destination,$country,$member_id,$transport_provider\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Check quotes
|
||||
foreach ($checkQuotes as $id) {
|
||||
list($res,$cost) = QuoteApi::check_quote($id);
|
||||
echo "[".date("Y-m-d H:i:s")."] Checking quote ID #${id} ($res) cost=${cost}\n";
|
||||
}
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job complete.\n";
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
$job_name = pathinfo(__FILE__, PATHINFO_FILENAME);
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job is starting.\n";
|
||||
|
||||
set_time_limit(0); // No limit!
|
||||
|
||||
require('../../backend.php');
|
||||
require('../common/QuoteApi.php');
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
$encryptionAlg = $savvyext->cfgReadChar('encryption.algorithm');
|
||||
$encryptionKey = $savvyext->cfgReadChar('encryption.key');
|
||||
$encryptionIV = $savvyext->cfgReadChar('encryption.iv');
|
||||
|
||||
$baseURL = $savvyext->cfgReadChar('system.api_url');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$country = 'US';
|
||||
$member_id = 0;
|
||||
|
||||
// Uber & Lyft
|
||||
$transport_providers = [1,2];
|
||||
|
||||
// Step 1: Load trips
|
||||
$q = "select b.*,c.address AS origin, d.address AS destination ";
|
||||
$q.= " from (select root_id,count(*) as count from trip_price_comparison where root_type=1 group by root_id) as a, ";
|
||||
$q.= " parsedemail_item b, address c, address d ";
|
||||
$q.= " where a.count=1 and b.id=a.root_id and b.private='f' and c.id=b.location_start_id and d.id=b.location_end_id and c.country='${country}' ";
|
||||
$q.= " and b.dup_id is null ";
|
||||
$q.= " order by b.travel_date desc";
|
||||
$r = pg_query($conn, $q);
|
||||
|
||||
// Step 3: Schedule quotes
|
||||
$checkQuotes = [];
|
||||
QuoteApi::$job_name = $job_name;
|
||||
if ($r && pg_num_rows($r)) {
|
||||
$n = pg_num_rows($r);
|
||||
echo "[".date("Y-m-d H:i:s")."] Processing ".$n." trips.\n";
|
||||
$i = 0;
|
||||
while ($f = pg_fetch_assoc($r)) {
|
||||
$i++;
|
||||
echo "[".date("Y-m-d H:i:s")."] Processing ${i}/${n} (".sprintf("%0.02f",100.0*$i/$n).") trip id=".$f["id"].".\n";
|
||||
if ($f["location_start_id"]==$f["location_end_id"]) continue;
|
||||
$location_start_id=$f["location_start_id"];
|
||||
$location_end_id=$f["location_end_id"];
|
||||
foreach ($transport_providers as $transport_provider) {
|
||||
$q = "SELECT * FROM quotes ";
|
||||
$q.= " WHERE location_start_id=${location_start_id} AND location_end_id=${location_end_id} ";
|
||||
$q.= " AND transport_provider_id=${transport_provider} AND cost>0 ";
|
||||
$q.= " AND completed>(current_date-1) ORDER BY completed DESC LIMIT 1";
|
||||
$quotes = pg_query($conn, $q);
|
||||
if ($quotes && pg_num_rows($quotes) && $quote=pg_fetch_assoc($quotes)) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote ".$quote["cost"]." already exists ID #".$quote["id"]."\n";
|
||||
continue;
|
||||
}
|
||||
list($res,$id) = QuoteApi::schedule_quote($f["origin"],$f["destination"],$country,$member_id,$transport_provider);
|
||||
if ($res>0) {
|
||||
if ($res==2) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote complete! ID #${id}\n";
|
||||
} else if ($res==1) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Scheduled quote ID #${id}\n";
|
||||
$checkQuotes[] = $id;
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Unexpected result for ID #${id} ($res)\n";
|
||||
}
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] schedule_quote failed: ${res}.\n";
|
||||
echo "[".date("Y-m-d H:i:s")."] $origin,$destination,$country,$member_id,$transport_provider\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Check quotes
|
||||
foreach ($checkQuotes as $id) {
|
||||
list($res,$cost) = QuoteApi::check_quote($id);
|
||||
echo "[".date("Y-m-d H:i:s")."] Checking quote ID #${id} ($res) cost=${cost}\n";
|
||||
}
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job complete.\n";
|
||||
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
$job_name = pathinfo(__FILE__, PATHINFO_FILENAME);
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job is starting.\n";
|
||||
|
||||
set_time_limit(0); // No limit!
|
||||
|
||||
require('../../backend.php');
|
||||
require('../common/QuoteApi.php');
|
||||
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
$encryptionAlg = $savvyext->cfgReadChar('encryption.algorithm');
|
||||
$encryptionKey = $savvyext->cfgReadChar('encryption.key');
|
||||
$encryptionIV = $savvyext->cfgReadChar('encryption.iv');
|
||||
|
||||
$baseURL = $savvyext->cfgReadChar('system.api_url');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$country = 'SG';
|
||||
$member_id = 0;
|
||||
|
||||
// Grab, ComfortDelGro & Gojek
|
||||
$transport_providers = [/*3,*/4,5];
|
||||
|
||||
// Step 1: Load batch file
|
||||
$attractions = load_batch_file("batch_quote_tourist_attractions.txt");
|
||||
|
||||
// Step 2: Geocode addresses
|
||||
$newOrigins = geocode_addresses($attractions);
|
||||
|
||||
// Step 3: Schedule quotes
|
||||
$checkQuotes = [];
|
||||
QuoteApi::$job_name = $job_name;
|
||||
foreach ($newOrigins as $origin_id=>$origin) {
|
||||
foreach ($newOrigins as $destination_id=>$destination) {
|
||||
if ($origin_id==$destination_id) continue;
|
||||
foreach ($transport_providers as $transport_provider) {
|
||||
$q = "SELECT * FROM quotes ";
|
||||
$q.= " WHERE location_start_id=${origin_id} AND location_end_id=${destination_id} ";
|
||||
$q.= " AND transport_provider_id=${transport_provider} AND cost>0 ";
|
||||
$q.= " AND completed>(current_date-1) ORDER BY completed DESC LIMIT 1";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote ".$f["cost"]." already exists ID #".$f["id"]."\n";
|
||||
continue;
|
||||
}
|
||||
list($res,$id) = QuoteApi::schedule_quote($origin,$destination,$country,$member_id,$transport_provider);
|
||||
if ($res>0) {
|
||||
if ($res==2) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote complete! ID #${id}\n";
|
||||
} else if ($res==1) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Scheduled quote ID #${id}\n";
|
||||
$checkQuotes[] = $id;
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Unexpected result for ID #${id} ($res)\n";
|
||||
}
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] schedule_quote failed: ${res}.\n";
|
||||
echo "[".date("Y-m-d H:i:s")."] $origin,$destination,$country,$member_id,$transport_provider\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Check quotes
|
||||
foreach ($checkQuotes as $id) {
|
||||
list($res,$cost) = QuoteApi::check_quote($id);
|
||||
echo "[".date("Y-m-d H:i:s")."] Checking quote ID #${id} ($res) cost=${cost}\n";
|
||||
}
|
||||
|
||||
function load_batch_file($filename) {
|
||||
$results = [];
|
||||
$fn = fopen($filename,"r");
|
||||
while(! feof($fn)) {
|
||||
$result = fgets($fn);
|
||||
$results[strtok($result,"\t")] = trim(strtok("\t"));
|
||||
}
|
||||
fclose($fn);
|
||||
return $results;
|
||||
}
|
||||
|
||||
function geocode_addresses($addresses) {
|
||||
global $conn;
|
||||
$geocodedAddresses = [];
|
||||
foreach ($addresses as $desc=>$address) {
|
||||
$params = [
|
||||
"address" => $address,
|
||||
"member_id" => 0,
|
||||
"country" => "SG"
|
||||
];
|
||||
$input = http_build_query($params);
|
||||
list($payload,$decrypted,$result,$body) = main_api_get('/trips/api/geocode/?',$input);
|
||||
if (is_array($payload) && array_key_exists('geocode',$payload) && is_array($payload['geocode'])
|
||||
&& array_key_exists('id',$payload['geocode']) && $payload['geocode']['id']>0) {
|
||||
$geocodedAddresses[$payload['geocode']['id']] = $payload['geocode']['address'];
|
||||
$q = "INSERT INTO tourist_attraction (attraction,address_id) VALUES('".pg_escape_string($desc)."',".$payload["geocode"]["id"].")";
|
||||
$r = pg_query($conn,$q);
|
||||
}
|
||||
}
|
||||
return $geocodedAddresses;
|
||||
}
|
||||
|
||||
function main_api_get($endpoint,$input) {
|
||||
global $baseURL, $encryptionAlg, $encryptionKey, $encryptionIV, $httpAuthToken;
|
||||
if ($endpoint!="" && $input!="") { // minimal sanity
|
||||
sleep(1);
|
||||
$url = $baseURL . $endpoint . $input;
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_VERBOSE, false);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
||||
'Content-Type: application/json',
|
||||
'Authorization: Server-Token ' . $httpAuthToken,
|
||||
"client_id: BATCH"
|
||||
)
|
||||
);
|
||||
|
||||
$body = curl_exec($ch);
|
||||
$result = json_decode($body,true);
|
||||
|
||||
$decrypted = openssl_decrypt(
|
||||
hex2bin(
|
||||
$result['payload']
|
||||
),
|
||||
$encryptionAlg,
|
||||
$encryptionKey,
|
||||
OPENSSL_RAW_DATA,
|
||||
$encryptionIV
|
||||
);
|
||||
$payload = json_decode($decrypted, true);
|
||||
return [$payload,$decrypted,$result,$body];
|
||||
}
|
||||
return [NULL,NULL,NULL,NULL];
|
||||
}
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job complete.\n";
|
||||
@@ -0,0 +1,18 @@
|
||||
ArtScience Museum 6 Bayfront Ave, Singapore, 18974
|
||||
National Gallery Singapore 1 St Andrew's Rd, Singapore, 178957
|
||||
National Museum of Singapore 93 Stamford Rd, Singapore, 178897
|
||||
Haw Par Villa 262 Pasir Panjang Rd, Singapore, 118628
|
||||
Singapore Botanic Gardens 1 Cluny Rd, Singapore, 259569
|
||||
Chinese and Japanese Gardens 1 Chinese Garden Rd, Singapore, 619795
|
||||
Gardens by the Bay 18 Marina Gardens Dr, Singapore, 018953
|
||||
Fort Canning River Valley Rd, Singapore, 179037
|
||||
Singapore Zoo 80 Mandai Lake Rd, 729826
|
||||
River Safari 80 Mandai Lake Rd, Singapore, 729826
|
||||
Little India #02, 48 Serangoon Rd, 16, Little India Arcade, 217959
|
||||
Chinatown 133 New Bridge Rd, Singapore 059413
|
||||
Kampong Glam 18 Kandahar St, Singapore 198884
|
||||
Universal Studios Singapore 8 Sentosa Gateway, 098269
|
||||
Siloso Beach Siloso Beach 7R47+42 Southern Islands, SingaporeWalk, Singapore
|
||||
Adventure Cove Waterpark 8 Sentosa Gateway, 098269
|
||||
Marina Bay Sands Rooftop 10 Bayfront Ave, Singapore 018956
|
||||
1-Altitude 1 Raffles Place, #B1-12, Singapore, 048616
|
||||
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
$job_name = pathinfo(__FILE__, PATHINFO_FILENAME);
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job is starting.\n";
|
||||
|
||||
set_time_limit(0); // No limit!
|
||||
|
||||
require('../../backend.php');
|
||||
require('../common/QuoteApi.php');
|
||||
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
$encryptionAlg = $savvyext->cfgReadChar('encryption.algorithm');
|
||||
$encryptionKey = $savvyext->cfgReadChar('encryption.key');
|
||||
$encryptionIV = $savvyext->cfgReadChar('encryption.iv');
|
||||
|
||||
$baseURL = $savvyext->cfgReadChar('system.api_url');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$country = 'US';
|
||||
$member_id = 0;
|
||||
|
||||
// Uber, Lyft
|
||||
$transport_providers = [1,2];
|
||||
|
||||
// Step 1: Load batch file
|
||||
$attractions = load_batch_file("batch_quote_tourist_attractions_atl.txt");
|
||||
|
||||
// Step 2: Geocode addresses
|
||||
$newOrigins = geocode_addresses($attractions);
|
||||
|
||||
QuoteApi::$job_name=$job_name;
|
||||
// Step 3: Schedule quotes
|
||||
$checkQuotes = [];
|
||||
foreach ($newOrigins as $origin_id=>$origin) {
|
||||
foreach ($newOrigins as $destination_id=>$destination) {
|
||||
if ($origin_id==$destination_id) continue;
|
||||
foreach ($transport_providers as $transport_provider) {
|
||||
$q = "SELECT * FROM quotes ";
|
||||
$q.= " WHERE location_start_id=${origin_id} AND location_end_id=${destination_id} ";
|
||||
$q.= " AND transport_provider_id=${transport_provider} AND cost>0 ";
|
||||
$q.= " AND completed>(current_date-1) ORDER BY completed DESC LIMIT 1";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote ".$f["cost"]." already exists ID #".$f["id"]."\n";
|
||||
continue;
|
||||
}
|
||||
list($res,$id) = QuoteApi::schedule_quote($origin,$destination,$country,$member_id,$transport_provider);
|
||||
if ($res>0) {
|
||||
if ($res==2) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote complete! ID #${id}\n";
|
||||
} else if ($res==1) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Scheduled quote ID #${id}\n";
|
||||
$checkQuotes[] = $id;
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Unexpected result for ID #${id} ($res)\n";
|
||||
}
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] schedule_quote failed: ${res}.\n";
|
||||
echo "[".date("Y-m-d H:i:s")."] $origin,$destination,$country,$member_id,$transport_provider\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Check quotes
|
||||
foreach ($checkQuotes as $id) {
|
||||
list($res,$cost) = QuoteApi::check_quote($id);
|
||||
echo "[".date("Y-m-d H:i:s")."] Checking quote ID #${id} ($res) cost=${cost}\n";
|
||||
}
|
||||
|
||||
function load_batch_file($filename) {
|
||||
$results = [];
|
||||
$fn = fopen($filename,"r");
|
||||
while(! feof($fn)) {
|
||||
$result = fgets($fn);
|
||||
$results[strtok($result,"\t")] = trim(strtok("\t"));
|
||||
}
|
||||
fclose($fn);
|
||||
return $results;
|
||||
}
|
||||
|
||||
function geocode_addresses($addresses) {
|
||||
global $conn;
|
||||
$geocodedAddresses = [];
|
||||
foreach ($addresses as $desc=>$address) {
|
||||
$params = [
|
||||
"address" => $address,
|
||||
"member_id" => 0,
|
||||
"country" => "US"
|
||||
];
|
||||
$input = http_build_query($params);
|
||||
list($payload,$decrypted,$result,$body) = main_api_get('/trips/api/geocode/?',$input);
|
||||
if (is_array($payload) && array_key_exists('geocode',$payload) && is_array($payload['geocode'])
|
||||
&& array_key_exists('id',$payload['geocode']) && $payload['geocode']['id']>0) {
|
||||
$geocodedAddresses[$payload['geocode']['id']] = $payload['geocode']['address'];
|
||||
$q = "INSERT INTO tourist_attraction (attraction,address_id) VALUES('".pg_escape_string($desc)."',".$payload["geocode"]["id"].")";
|
||||
$r = pg_query($conn,$q);
|
||||
}
|
||||
}
|
||||
return $geocodedAddresses;
|
||||
}
|
||||
|
||||
function main_api_get($endpoint,$input) {
|
||||
global $baseURL, $encryptionAlg, $encryptionKey, $encryptionIV, $httpAuthToken;
|
||||
if ($endpoint!="" && $input!="") { // minimal sanity
|
||||
sleep(1);
|
||||
$url = $baseURL . $endpoint . $input;
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_VERBOSE, false);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
||||
'Content-Type: application/json',
|
||||
'Authorization: Server-Token ' . $httpAuthToken,
|
||||
"client_id: BATCH"
|
||||
)
|
||||
);
|
||||
|
||||
$body = curl_exec($ch);
|
||||
$result = json_decode($body,true);
|
||||
|
||||
$decrypted = openssl_decrypt(
|
||||
hex2bin(
|
||||
$result['payload']
|
||||
),
|
||||
$encryptionAlg,
|
||||
$encryptionKey,
|
||||
OPENSSL_RAW_DATA,
|
||||
$encryptionIV
|
||||
);
|
||||
$payload = json_decode($decrypted, true);
|
||||
return [$payload,$decrypted,$result,$body];
|
||||
}
|
||||
return [NULL,NULL,NULL,NULL];
|
||||
}
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job complete.\n";
|
||||
@@ -0,0 +1,5 @@
|
||||
Mercedes-Benz Stadium 1 AMB Dr NW, Atlanta, GA 30313
|
||||
Cumberland Mall 2860 Cumberland Mall, Atlanta, GA 30339
|
||||
SunTrust Park 755 Battery Ave SE, Atlanta, GA 30339
|
||||
Georgia Aquarium 225 Baker St NW, Atlanta, GA 30313
|
||||
CNN Studio 190 Marietta St NW, Atlanta, GA 30303
|
||||
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
$job_name = pathinfo(__FILE__, PATHINFO_FILENAME);
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job is starting.\n";
|
||||
|
||||
set_time_limit(0); // No limit!
|
||||
|
||||
require('../../backend.php');
|
||||
require('../common/QuoteApi.php');
|
||||
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
$encryptionAlg = $savvyext->cfgReadChar('encryption.algorithm');
|
||||
$encryptionKey = $savvyext->cfgReadChar('encryption.key');
|
||||
$encryptionIV = $savvyext->cfgReadChar('encryption.iv');
|
||||
|
||||
$baseURL = $savvyext->cfgReadChar('system.api_url');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$country = 'US';
|
||||
$member_id = 0;
|
||||
|
||||
// Uber, Lyft
|
||||
$transport_providers = [1,2];
|
||||
|
||||
// Step 1: Load batch file
|
||||
$attractions = load_batch_file("batch_quote_tourist_attractions_sf.txt");
|
||||
|
||||
// Step 2: Geocode addresses
|
||||
$newOrigins = geocode_addresses($attractions);
|
||||
|
||||
// Step 3: Schedule quotes
|
||||
$checkQuotes = [];
|
||||
QuoteApi::$job_name = $job_name;
|
||||
foreach ($newOrigins as $origin_id=>$origin) {
|
||||
foreach ($newOrigins as $destination_id=>$destination) {
|
||||
if ($origin_id==$destination_id) continue;
|
||||
foreach ($transport_providers as $transport_provider) {
|
||||
$q = "SELECT * FROM quotes ";
|
||||
$q.= " WHERE location_start_id=${origin_id} AND location_end_id=${destination_id} ";
|
||||
$q.= " AND transport_provider_id=${transport_provider} AND cost>0 ";
|
||||
$q.= " AND completed>(current_date-1) ORDER BY completed DESC LIMIT 1";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote ".$f["cost"]." already exists ID #".$f["id"]."\n";
|
||||
continue;
|
||||
}
|
||||
list($res,$id) = QuoteApi::schedule_quote($origin,$destination,$country,$member_id,$transport_provider);
|
||||
if ($res>0) {
|
||||
if ($res==2) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Quote complete! ID #${id}\n";
|
||||
} else if ($res==1) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Scheduled quote ID #${id}\n";
|
||||
$checkQuotes[] = $id;
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Unexpected result for ID #${id} ($res)\n";
|
||||
}
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] schedule_quote failed: ${res}.\n";
|
||||
echo "[".date("Y-m-d H:i:s")."] $origin,$destination,$country,$member_id,$transport_provider\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Check quotes
|
||||
foreach ($checkQuotes as $id) {
|
||||
list($res,$cost) = QuoteApi::check_quote($id);
|
||||
echo "[".date("Y-m-d H:i:s")."] Checking quote ID #${id} ($res) cost=${cost}\n";
|
||||
}
|
||||
|
||||
function load_batch_file($filename) {
|
||||
$results = [];
|
||||
$fn = fopen($filename,"r");
|
||||
while(! feof($fn)) {
|
||||
$result = fgets($fn);
|
||||
$results[strtok($result,"\t")] = trim(strtok("\t"));
|
||||
}
|
||||
fclose($fn);
|
||||
return $results;
|
||||
}
|
||||
|
||||
function geocode_addresses($addresses) {
|
||||
global $conn;
|
||||
$geocodedAddresses = [];
|
||||
foreach ($addresses as $desc=>$address) {
|
||||
$params = [
|
||||
"address" => $address,
|
||||
"member_id" => 0,
|
||||
"country" => "US"
|
||||
];
|
||||
$input = http_build_query($params);
|
||||
list($payload,$decrypted,$result,$body) = main_api_get('/trips/api/geocode/?',$input);
|
||||
if (is_array($payload) && array_key_exists('geocode',$payload) && is_array($payload['geocode'])
|
||||
&& array_key_exists('id',$payload['geocode']) && $payload['geocode']['id']>0) {
|
||||
$geocodedAddresses[$payload['geocode']['id']] = $payload['geocode']['address'];
|
||||
$q = "INSERT INTO tourist_attraction (attraction,address_id) VALUES('".pg_escape_string($desc)."',".$payload["geocode"]["id"].")";
|
||||
$r = pg_query($conn,$q);
|
||||
}
|
||||
}
|
||||
return $geocodedAddresses;
|
||||
}
|
||||
|
||||
function main_api_get($endpoint,$input) {
|
||||
global $baseURL, $encryptionAlg, $encryptionKey, $encryptionIV, $httpAuthToken;
|
||||
if ($endpoint!="" && $input!="") { // minimal sanity
|
||||
sleep(1);
|
||||
$url = $baseURL . $endpoint . $input;
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_VERBOSE, false);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
||||
'Content-Type: application/json',
|
||||
'Authorization: Server-Token ' . $httpAuthToken,
|
||||
"client_id: BATCH"
|
||||
)
|
||||
);
|
||||
|
||||
$body = curl_exec($ch);
|
||||
$result = json_decode($body,true);
|
||||
|
||||
$decrypted = openssl_decrypt(
|
||||
hex2bin(
|
||||
$result['payload']
|
||||
),
|
||||
$encryptionAlg,
|
||||
$encryptionKey,
|
||||
OPENSSL_RAW_DATA,
|
||||
$encryptionIV
|
||||
);
|
||||
$payload = json_decode($decrypted, true);
|
||||
return [$payload,$decrypted,$result,$body];
|
||||
}
|
||||
return [NULL,NULL,NULL,NULL];
|
||||
}
|
||||
echo "[".date("Y-m-d H:i:s")."] ".$job_name." job complete.\n";
|
||||
@@ -0,0 +1,27 @@
|
||||
Golden Gate Post Card Viewpoint Golden Gate Bridge, Coastal Trail, San Francisco, CA 94129, USA
|
||||
Battery Spencer RGH7+FH Sausalito, California, USA
|
||||
Madame Tussauds San Francisco 145 Jefferson St, San Francisco, CA 94133, USA
|
||||
Ghirardelli Square 900 North Point St Suite 52, San Francisco, CA 94109, USA
|
||||
Ferry Building 1 Ferry Building, San Francisco, CA 94111, USA
|
||||
Nob Hill 1621 Polk St, San Francisco, CA 94109, USA
|
||||
Lombard Street 2139 Lombard St, San Francisco, CA 94123, USA
|
||||
Chinatown 826 Grant Ave, San Francisco, CA 94108, USA
|
||||
Golden Gate Park 50 Stow Lake Dr E, San Francisco, CA 94118, USA
|
||||
San Francisco Botanical Garden 1199 9th Ave, San Francisco, CA 94122, USA
|
||||
California Palace of the Legion of Honor 100 34th Ave, San Francisco, CA 94121, USA
|
||||
The Palace Of Fine Arts 3601 Lyon St, San Francisco, CA 94123, USA
|
||||
California Academy of Sciences 55 Music Concourse Dr, San Francisco, CA 94118, USA
|
||||
San Francisco Museum of Modern Art 151 3rd St, San Francisco, CA 94103, USA
|
||||
de Young Fine Arts Museum of San Francisco 50 Hagiwara Tea Garden Dr, San Francisco, CA 94118, USA
|
||||
Twin Peaks 501 Twin Peaks Blvd, San Francisco, CA 94114, USA
|
||||
Asian Art Museum 200 Larkin St, San Francisco, CA 94102, USA
|
||||
Exploratorium Pier 15, The Embarcadero, San Francisco, CA 94111, USA
|
||||
High Tea at a Historic Hotel 2 New Montgomery St, San Francisco, CA 94105, USA
|
||||
AT&T Park 24 Willie Mays Plaza, San Francisco, CA 94107, USA
|
||||
Walt Disney Family Museum 104 Montgomery St, San Francisco, CA 94129, USA
|
||||
Yerba Buena Gardens 750 Howard St, San Francisco, CA 94103, USA
|
||||
San Francisco Symphony 201 Van Ness Ave, San Francisco, CA 94102, USA
|
||||
San Francisco Zoo and Gardens Sloat Blvd & Great Highway, San Francisco, CA 94132, USA
|
||||
Union Square 333 Post St, San Francisco, CA 94108, USA
|
||||
Baker Beach Gibson Rd, San Francisco, CA 94129, USA
|
||||
Japantown 1610 Geary Blvd, San Francisco, CA 94115, USA
|
||||
@@ -0,0 +1 @@
|
||||
HERE
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] blog_rotattion job is starting.\n";
|
||||
|
||||
require('../backend.php');
|
||||
|
||||
define('EMAIL_PENDING', 1);
|
||||
define('EMAIL_SENT', 5);
|
||||
|
||||
// We will not limit the SQL we will exhaust the allowed memory
|
||||
// we will process data in ${hard_limit} batches and hopefully catch up
|
||||
$hard_limit = 500000;
|
||||
// GPS coordinate precision to assume the same location
|
||||
$precision = 3;
|
||||
$tag_message = false;
|
||||
|
||||
$email_templates_dir = $savvyext->cfgReadChar('mailsend.templates_dir');
|
||||
$template_name = "DealTemplate.html"; // This is test template.
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
|
||||
|
||||
$mysql = "SELECT *,id AS member_id FROM members LIMIT 10";
|
||||
|
||||
|
||||
$r = pg_query($readOnlyReplicaConn, $mysql);
|
||||
|
||||
$acc = array();
|
||||
if ($r && pg_num_rows($r)) {
|
||||
|
||||
// Load Email template
|
||||
$htm_template = file_get_contents($email_templates_dir . "/" . $template_name);
|
||||
|
||||
while ($f = pg_fetch_assoc($r)) {
|
||||
$member_id = $f["member_id"];
|
||||
$notify_id = $f["notify_id"];
|
||||
$reciever_email = $f["reciever_email"];
|
||||
$notice_type = $f["notice_type"];
|
||||
$category = $f["category"];
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
class Api
|
||||
{
|
||||
|
||||
private static $instance;
|
||||
private static $httpAuthToken;
|
||||
private static $encryptionAlg;
|
||||
private static $encryptionKey;
|
||||
private static $encryptionIV;
|
||||
private static $baseURL;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public static function initConfig()
|
||||
{
|
||||
global $savvyext;
|
||||
self::$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
self::$encryptionAlg = $savvyext->cfgReadChar('encryption.algorithm');
|
||||
self::$encryptionKey = $savvyext->cfgReadChar('encryption.key');
|
||||
self::$encryptionIV = $savvyext->cfgReadChar('encryption.iv');
|
||||
self::$baseURL = $savvyext->cfgReadChar('system.api_url');
|
||||
}
|
||||
|
||||
public static function getInstance()
|
||||
{
|
||||
if (null === static::$instance) {
|
||||
static::$instance = new static;
|
||||
self::initConfig();
|
||||
return static::$instance;
|
||||
}
|
||||
return static::$instance;
|
||||
}
|
||||
|
||||
public static function postData($endpoint, $payload)
|
||||
{
|
||||
self::getInstance();
|
||||
$encrypted_payload = bin2hex(
|
||||
openssl_encrypt(
|
||||
$payload,
|
||||
self::$encryptionAlg,
|
||||
self::$encryptionKey,
|
||||
OPENSSL_RAW_DATA,
|
||||
self::$encryptionIV
|
||||
));
|
||||
$postdata = "{\"encrypted_payload\": \"${encrypted_payload}\"}";
|
||||
$url = self::$baseURL . $endpoint;
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_VERBOSE, false);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
||||
'Content-Type: application/json',
|
||||
'Content-Length: ' . strlen($postdata),
|
||||
'Authorization: Server-Token ' . self::$httpAuthToken,
|
||||
"client_id: BATCH"
|
||||
)
|
||||
);
|
||||
|
||||
$body = curl_exec($ch);
|
||||
$result = json_decode($body, true);
|
||||
|
||||
$decrypted = openssl_decrypt(
|
||||
hex2bin(
|
||||
$result['payload']
|
||||
),
|
||||
self::$encryptionAlg,
|
||||
self::$encryptionKey,
|
||||
OPENSSL_RAW_DATA,
|
||||
self::$encryptionIV
|
||||
);
|
||||
$payload = json_decode($decrypted, true);
|
||||
return $payload;
|
||||
}
|
||||
|
||||
public static function getData($endpoint)
|
||||
{
|
||||
self::getInstance();
|
||||
if ($endpoint != "") { // minimal sanity
|
||||
sleep(1);
|
||||
$url = self::$baseURL . $endpoint;
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_VERBOSE, false);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
||||
'Content-Type: application/json',
|
||||
'Authorization: Server-Token ' . self::$httpAuthToken,
|
||||
"client_id: BATCH"
|
||||
)
|
||||
);
|
||||
|
||||
$body = curl_exec($ch);
|
||||
$result = json_decode($body, true);
|
||||
$decrypted = openssl_decrypt(
|
||||
hex2bin(
|
||||
$result['payload']
|
||||
),
|
||||
self::$encryptionAlg,
|
||||
self::$encryptionKey,
|
||||
OPENSSL_RAW_DATA,
|
||||
self::$encryptionIV
|
||||
);
|
||||
$payload = json_decode($decrypted, true);
|
||||
return [$payload, $decrypted, $result, $body];
|
||||
}
|
||||
return [null, null, null, null];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
class Geocode
|
||||
{
|
||||
public static function geocodeAddress($address)
|
||||
{
|
||||
global $httpAuthToken, $oauth_api;
|
||||
if (!empty($address)) {
|
||||
$data = http_build_query(
|
||||
array(
|
||||
'address' => $address,
|
||||
)
|
||||
);
|
||||
$url = $oauth_api . "geocode?" . $data;
|
||||
$opts = array(
|
||||
'http' => array(
|
||||
'method' => "GET",
|
||||
'timeout' => 60, /* 1 minute */
|
||||
'header' =>
|
||||
"Content-Type: application/x-www-form-urlencoded\r\n" .
|
||||
"Accept: application/json\r\n" .
|
||||
"Authorization: Server-Token ${httpAuthToken}\r\n",
|
||||
),
|
||||
);
|
||||
$context = stream_context_create($opts);
|
||||
$body = file_get_contents($url, false, $context);
|
||||
$geocoded = json_decode($body, true);
|
||||
if (is_array($geocoded) && isset($geocoded["data"]) && !isset($geocoded["error"])) {
|
||||
return $geocoded["data"];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function reverseGPS($latitude, $longitude)
|
||||
{
|
||||
global $httpAuthToken, $oauth_api;
|
||||
|
||||
$body = null;
|
||||
if (!empty($latitude && !empty($longitude))) {
|
||||
$data = http_build_query(
|
||||
array(
|
||||
'lat' => $latitude,
|
||||
'lng' => $longitude,
|
||||
)
|
||||
);
|
||||
|
||||
$url = $oauth_api . "reverse?" . $data;
|
||||
$opts = array(
|
||||
'http' => array(
|
||||
'method' => "GET",
|
||||
'timeout' => 60, /* 1 minute */
|
||||
'header' =>
|
||||
"Content-Type: application/x-www-form-urlencoded\r\n" .
|
||||
"Accept: application/json\r\n" .
|
||||
"Authorization: Server-Token ${httpAuthToken}\r\n",
|
||||
),
|
||||
);
|
||||
$context = stream_context_create($opts);
|
||||
$body = file_get_contents($url, false, $context);
|
||||
$geocoded = json_decode($body, true);
|
||||
|
||||
if (is_array($geocoded) && isset($geocoded["data"]) && !isset($geocoded["error"])) {
|
||||
return $geocoded["data"];
|
||||
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getTimeZone($lat, $lng)
|
||||
{
|
||||
global $googleKey;
|
||||
$result = array("message" => "Unexpected error", "dstOffset" => 0, "rawOffset" => 0, "status" => "Error", "timeZoneId" => "", "timeZoneName" => "");
|
||||
$url = "https://maps.googleapis.com/maps/api/timezone/json?location=${lat},${lng}×tamp=" . time() . "&key=" . $googleKey;
|
||||
$resp_json = file_get_contents($url);
|
||||
$resp = json_decode($resp_json, true);
|
||||
if ($resp["status"] == 'OK') {
|
||||
$result = $resp;
|
||||
if ($resp["timeZoneId"] != "") {
|
||||
$result["message"] = "";
|
||||
} else {
|
||||
$result["message"] = "Failed to get timezone offset for: ${lat},${lng}\n";
|
||||
}
|
||||
} else {
|
||||
$result["message"] = "Invalid service response code\n";
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function getGeoInfoBigDataCloud($latitude, $longitude)
|
||||
{
|
||||
global $city_keywords;
|
||||
$url = "https://api.bigdatacloud.net/data/reverse-geocode-client?latitude=" . $latitude . "&longitude=" . $longitude . "&localityLanguage=en";
|
||||
$opts = array(
|
||||
'http' => array(
|
||||
'method' => "GET",
|
||||
),
|
||||
);
|
||||
|
||||
$context = stream_context_create($opts);
|
||||
$body = file_get_contents($url, false, $context);
|
||||
$geoinfo = json_decode($body, true);
|
||||
if (count($geoinfo) > 0 && isset($geoinfo['localityInfo'])) {
|
||||
$localities = $geoinfo['localityInfo']['administrative'];
|
||||
foreach ($localities as $k => $v) {
|
||||
$name = isset($v['name']) ? $v['name'] : "";
|
||||
$description = isset($v['description']) ? $v['description'] : "";
|
||||
$info = strtolower($name . $description);
|
||||
foreach ($city_keywords as $key) {
|
||||
if (strpos($info, $key) !== false) {
|
||||
return $v['name'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
require __DIR__ . '../../../vendor/autoload.php';
|
||||
class Logger
|
||||
{
|
||||
protected static $instance;
|
||||
private static $logger;
|
||||
|
||||
const ERROR = 0;
|
||||
const WARNING = 1;
|
||||
const INFO = 2;
|
||||
const DEBUG = 3;
|
||||
const DEBUG1 = 4;
|
||||
const DEBUG2 = 5;
|
||||
const DEBUG3 = 6;
|
||||
const DEBUG4 = 7;
|
||||
const SQL = 8;
|
||||
const FLOG_MAX = 9;
|
||||
|
||||
const LEVELS = [
|
||||
'ERROR', 'WARNING', 'INFO', 'DEBUG', 'DEBUG1', 'DEBUG2', 'DEBUG3', 'DEBUG4', 'SQL', 'FLOG_MAX'
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public static function getLogger()
|
||||
{
|
||||
if (!self::$instance) {
|
||||
self::initLogger();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public static function initLogger()
|
||||
{
|
||||
global $savvyext;
|
||||
$fluent_host = $savvyext->cfgReadChar('phplogger.host');
|
||||
$fluent_port = $savvyext->cfgReadLong('phplogger.port');
|
||||
$log_enabled = $savvyext->cfgReadLong('phplogger.enabled');
|
||||
|
||||
if ($log_enabled == 1) {
|
||||
self::$logger = new Fluent\Logger\FluentLogger($fluent_host, $fluent_port);
|
||||
}
|
||||
self::$instance = self::$logger;
|
||||
}
|
||||
|
||||
public static function __callStatic($name, $arguments){
|
||||
if(is_array($arguments) && count($arguments)>0 && in_array(strtoupper($name), Logger::LEVELS)) {
|
||||
$data = $arguments[0];
|
||||
$name = NULL;
|
||||
$tag = NULL;
|
||||
if (count($arguments)>1) {
|
||||
$name = $arguments[1];
|
||||
}
|
||||
if (count($arguments)>2) {
|
||||
$tag = $arguments[2];
|
||||
}
|
||||
$level = Logger::levelByName($name);
|
||||
return Logger::log($level, $data, $name, $tag);
|
||||
}
|
||||
error_log("Logger::__callStatic($name, \$arguments) => Invalid method name!");
|
||||
}
|
||||
|
||||
public static function levelByName($name) {
|
||||
$val = strtoupper($name);
|
||||
if(in_array($val, Logger::LEVELS)) {
|
||||
return array_search($val, Logger::LEVELS, false);
|
||||
} else {
|
||||
return Logger::FLOG_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
public static function nameByLevel($level) {
|
||||
$level = (int)$level;
|
||||
return Logger::ERROR < $level || $level > Logger::FLOG_MAX ? Logger::LEVELS[Logger::FLOG_MAX] : Logger::LEVELS[$level];
|
||||
}
|
||||
|
||||
public static function log($level, $data = [], $name = NULL, $tag = NULL)
|
||||
{
|
||||
global $savvyext;
|
||||
$clevel = $savvyext->cfgReadLong('phplogger.level');
|
||||
$ilevel = (int)$level;
|
||||
if ($ilevel > $clevel) {
|
||||
error_log("Logger::log() invalid log level! '$level' => '$ilevel' > '$clevel'");
|
||||
return;
|
||||
}
|
||||
$tag = $tag ?? $savvyext->cfgReadChar('phplogger.tag');
|
||||
$name = $name ?? $savvyext->cfgReadChar('phplogger.name');
|
||||
$data = [
|
||||
"log" => $name,
|
||||
"level" => Logger::nameByLevel($level),
|
||||
"pid" => getmypid(),
|
||||
"zz" => is_array($data) || is_object($data) ? json_encode($data) : $data,
|
||||
];
|
||||
if (self::getLogger()) {
|
||||
self::getLogger()->post($tag, $data);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
require_once('../common/Api.php');
|
||||
require_once('../common/Logger.php');
|
||||
class QuoteApi
|
||||
{
|
||||
public static $job_name="";
|
||||
public static function schedule_quote($origin, $destination, $country, $member_id, $transport_provider, $trackedemail_item_id = 0, $prefill = 't', $pool = 1)
|
||||
{
|
||||
if ($origin != "" && $destination != "" && $transport_provider > 0) { // minimal sanity
|
||||
$payload = "{
|
||||
\"origin\":\"${origin}\",
|
||||
\"destination\":\"${destination}\",
|
||||
\"member_id\":${member_id},
|
||||
\"transport_provider_id\":${transport_provider},
|
||||
\"trackedemail_item_id\":${trackedemail_item_id},
|
||||
\"country\":\"${country}\",
|
||||
\"group_quote_id\":0,
|
||||
\"prefill\":\"${prefill}\",
|
||||
\"pool\":${pool}
|
||||
}";
|
||||
|
||||
$input_data = $payload;
|
||||
$endpoint = "/trips/api/quote";
|
||||
$payload = Api::postData($endpoint, $input_data);
|
||||
$log = [
|
||||
'job_name' => self::$job_name,
|
||||
'function' => __FUNCTION__,
|
||||
'request' => $endpoint,
|
||||
'input_data' => $input_data,
|
||||
'response_data' => $payload,
|
||||
];
|
||||
Logger::debug($log);
|
||||
if (is_array($payload) && array_key_exists('id', $payload) && $payload['id'] > 0) {
|
||||
if (array_key_exists('cost', $payload) && $payload['cost'] > 0) {
|
||||
return [2, $payload['id']];//completed
|
||||
}
|
||||
if (array_key_exists('travel_date', $payload) && $payload['travel_date'] != '') {
|
||||
return [-1, $payload['id']];
|
||||
}
|
||||
return [1, $payload['id']];
|
||||
} else {
|
||||
return [-2, null];
|
||||
}
|
||||
}
|
||||
return [-3, null];
|
||||
}
|
||||
|
||||
public static function check_quote($id)
|
||||
{
|
||||
if ($id > 0) { // minimal sanity
|
||||
list($payload, $decrypted, $result, $body) = Api::getData("/trips/api/quote/" . $id);
|
||||
$log = [
|
||||
'job_name' => self::$job_name,
|
||||
'function' => __FUNCTION__,
|
||||
'request' => "/trips/api/quote/" . $id,
|
||||
'input_data' => $id,
|
||||
'response_data' => $payload,
|
||||
];
|
||||
Logger::debug($log);
|
||||
if (is_array($payload) && array_key_exists('id', $payload) && $payload['id'] > 0) {
|
||||
if (array_key_exists('cost', $payload) && $payload['cost'] > 0) {
|
||||
return [2, $payload['cost']];//completed
|
||||
}
|
||||
if (array_key_exists('travel_date', $payload) && $payload['travel_date'] != '') {
|
||||
return [-1, null];
|
||||
}
|
||||
} else {
|
||||
return [-2, null];
|
||||
}
|
||||
}
|
||||
return [-3, null];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
/***
|
||||
* Class SVY21
|
||||
* todo: convert SVY21 Singapore TM to Lat Long
|
||||
*/
|
||||
class SVY21
|
||||
{
|
||||
const ELLIPSOID_SEMIMAJORAXIS = 6378137.0;
|
||||
const ELLIPSOID_ECCENTRICITY = 0.0818191908426215;
|
||||
const ELLIPSOID_FLATTENING = 0.00335281066474746;
|
||||
const PROJ_NATURALORIGINLATITUDE = 1.36666666666667;
|
||||
const PROJ_NATURALORIGINLONGITUDE = 103.833333333333;
|
||||
const PROJ_SCALEFACTOR = 1.0;
|
||||
const PROJ_FALSEEASTINGS = 28001.642;
|
||||
const PROJ_FALSENORTHINGS = 38744.572;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/***
|
||||
* @param $N of svy21
|
||||
* @param $E of svy21
|
||||
* @return float[]|int[] return [lat, long]
|
||||
*/
|
||||
public function CnvEN2LL($N, $E)
|
||||
{
|
||||
$l = $this->SecondEccentricity();
|
||||
$a = $this->calc_e1();
|
||||
$b = $this->calc_M1($E);
|
||||
$c = $this->calc_u1($b);
|
||||
$d = $this->calc_lat1($c, $a);
|
||||
$e = $this->calc_T1($d);
|
||||
$f = $this->calc_c1($d);
|
||||
$g = $this->calc_v1($d);
|
||||
$h = $this->calc_p1($d);
|
||||
$i = ($N - self::PROJ_FALSEEASTINGS) / ($g * self::PROJ_SCALEFACTOR);
|
||||
$j = ($i * $i / 2.0) - (5.0 + 3.0 * $e + 10.0 * $f - 4.0 * $f * $f - 9.0 * pow($l, 2)) * (pow($i, 4) / 24.0) + (61.0 + 90.0 * $e + 298.0 * $f + 45.0 * $e * $e - 252.0 * pow($l, 2) - 3.0 * $f * $f) * (pow($i, 6) / 720.0);
|
||||
$j = $d - $g * tan($d) * $j / $h;
|
||||
$lat = $this->CnvRadToDeg($j);
|
||||
$k = ($i - (1.0 + 2.0 * $e + $f) * pow($i, 3) / 6.0 + (5.0 - 2.0 * $f + 28.0 * $e - 3.0 * $f * $f + 8.0 * pow($l, 2) + 24.0 * $e * $e) * pow($i, 5) / 120.0) / cos($d);
|
||||
$k = $this->CnvDegToRad(self::PROJ_NATURALORIGINLONGITUDE) + $k;
|
||||
$long = $this->CnvRadToDeg($k);
|
||||
$r1 = floor($lat);
|
||||
$r2 = floor(($lat - $r1) * 60);
|
||||
$r3 = (round(((($lat - $r1) - ($r2 / 60)) * 60 * 60) * 100) / 100);
|
||||
$r3 = $this->roundNumber($r3, 4);
|
||||
$r4 = floor($long);
|
||||
$r4 = floor(($long - $r4) * 60);
|
||||
$r5 = (round(((($long - $r4) - ($r4 / 60)) * 60 * 60) * 100) / 100);
|
||||
$r5 = $this->roundNumber($r5, 4);
|
||||
return [$lat, $long];
|
||||
}
|
||||
|
||||
private function SecondEccentricity()
|
||||
{
|
||||
return (sqrt(self::ELLIPSOID_ECCENTRICITY * self::ELLIPSOID_ECCENTRICITY / (1.0 - self::ELLIPSOID_ECCENTRICITY * self::ELLIPSOID_ECCENTRICITY)));
|
||||
}
|
||||
|
||||
private function roundNumber($a, $b)
|
||||
{
|
||||
return round($a * pow(10, $b)) / pow(10, $b);
|
||||
}
|
||||
|
||||
private function CnvRadToDeg($a)
|
||||
{
|
||||
return (180.0 * $a / pi());
|
||||
}
|
||||
|
||||
private function CnvDegToRad($a)
|
||||
{
|
||||
return (pi() * $a) / 180.0;
|
||||
}
|
||||
|
||||
private function calc_M($a)
|
||||
{
|
||||
$c = self::ELLIPSOID_ECCENTRICITY;
|
||||
$d = 1.0 - (pow($c, 2) / 4.0) - (3.0 * pow($c, 4) / 64.0) - (5.0 * pow($c, 6) / 256);
|
||||
$e = (3.0 * pow($c, 2) / 8.0) + (3.0 * pow($c, 4) / 32.0) + (45.0 * pow($c, 6) / 1024.0);
|
||||
$f = (15.0 * pow($c, 4.0) / 256.0) + (45.0 * pow($c, 6) / 1024.0);
|
||||
$g = (35.0 * pow($c, 6) / 3072);
|
||||
$b = $d * $a - $e * sin(2.0 * $a) + $f * sin(4.0 * $a) - $g * sin(6 * $a);
|
||||
return $b * self::ELLIPSOID_SEMIMAJORAXIS;
|
||||
}
|
||||
|
||||
private function calc_T1($a)
|
||||
{
|
||||
$b = tan($a);
|
||||
return $b * $b;
|
||||
}
|
||||
|
||||
private function calc_v1($a)
|
||||
{
|
||||
$b = self::ELLIPSOID_ECCENTRICITY * sin($a);
|
||||
$b = sqrt(1.0 - $b * $b);
|
||||
return self::ELLIPSOID_SEMIMAJORAXIS / $b;
|
||||
}
|
||||
|
||||
private function calc_p1($a)
|
||||
{
|
||||
$c = self::ELLIPSOID_ECCENTRICITY;
|
||||
$b = 1.0 - $c * $c * pow(sin($a), 2);
|
||||
$b = pow($b, 3.0 / 2.0);
|
||||
return self::ELLIPSOID_SEMIMAJORAXIS * (1.0 - $c * $c) / $b;
|
||||
}
|
||||
|
||||
private function calc_c1($a)
|
||||
{
|
||||
$b = $this->SecondEccentricity();
|
||||
$b = $b * cos($a);
|
||||
return $b * $b;
|
||||
}
|
||||
|
||||
private function calc_e1()
|
||||
{
|
||||
$a = 1.0 - sqrt(1.0 - pow(self::ELLIPSOID_ECCENTRICITY, 2));
|
||||
return $a / (1.0 + sqrt(1.0 - pow(self::ELLIPSOID_ECCENTRICITY, 2)));
|
||||
}
|
||||
|
||||
private function calc_M1($a)
|
||||
{
|
||||
$c = $this->calc_M($this->CnvDegToRad(self::PROJ_NATURALORIGINLATITUDE));
|
||||
return ($c + ($a - self::PROJ_FALSENORTHINGS) / self::PROJ_SCALEFACTOR);
|
||||
}
|
||||
|
||||
private function calc_u1($a)
|
||||
{
|
||||
$c = self::ELLIPSOID_ECCENTRICITY;
|
||||
$b = self::ELLIPSOID_SEMIMAJORAXIS * (1.0 - ($c * $c / 4.0) - (3.0 * pow($c, 4) / 64.0) - (5.0 * pow($c, 6) / 256.0));
|
||||
return $a / $b;
|
||||
}
|
||||
|
||||
private function calc_lat1($a, $b)
|
||||
{
|
||||
$c = $a + ((3.0 * $b / 2.0) - 27.0 * $b * $b / 32.0) * sin(2.0 * $a);
|
||||
$c = $c + ((21.0 * $b * $b / 16.0) - 55.0 * pow($b, 4.0) / 32.0) * sin(4.0 * $a);
|
||||
$c = $c + (151.0 * pow($b, 3) / 96.0) * sin(6.0 * $a);
|
||||
$c = $c + (1097.0 * pow($b, 4) / 512.0) * sin(8.0 * $a);
|
||||
return $c;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,449 @@
|
||||
<?php
|
||||
|
||||
function getAddressId($address)
|
||||
{
|
||||
global $googleKey, $readOnlyReplicaConn;
|
||||
// Check the address exsts
|
||||
$q = "SELECT id FROM address WHERE lower(address)=lower('${address}') ";
|
||||
$q .= "AND latitude<>0 AND longitude<>0 AND geocoding_date IS NOT NULL ";
|
||||
$q .= "ORDER BY geocoding_date DESC LIMIT 1";
|
||||
error_log($q);
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
if ($r && pg_num_rows($r) && $f = pg_fetch_row($r)) {
|
||||
return $f[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/* save data to table address */
|
||||
function saveAddress($result)
|
||||
{
|
||||
global $conn;
|
||||
|
||||
syslog(LOG_WARNING, 'MessageDataSaver::saveAddress($result)');
|
||||
$db_lat = floatval($result["lat"]);
|
||||
$db_lng = floatval($result["lng"]);
|
||||
$db_address = pg_escape_string($result["address"]);
|
||||
$db_postal = pg_escape_string($result["postal"]);
|
||||
$db_city = pg_escape_string($result["city"]);
|
||||
$db_city_lat = floatval($result["city_lat"]);
|
||||
$db_city_lng = floatval($result["city_lng"]);
|
||||
$db_country = pg_escape_string($result["country"]);
|
||||
$db_tz = getTimeZoneID($result["timeZoneId"]);
|
||||
$city_id = getCityId($db_city, $db_country, $db_city_lat, $db_city_lng);
|
||||
if (empty($db_postal)) {
|
||||
$db_postal = getPostalCode($db_lat, $db_lng, $db_country);
|
||||
}
|
||||
$q = "INSERT INTO address (address,latitude,longitude,timezone,geocoding_date,postal,country,geometry, city_id) VALUES (";
|
||||
$q .= "'${db_address}',${db_lat},${db_lng}," . ($db_tz == null ? "NULL" : $db_tz) . ",now(),'${db_postal}','${db_country}',ST_SetSRID(ST_MakePoint(${db_lng},${db_lat}), 4326),'${city_id}')";
|
||||
$q .= " RETURNING id";
|
||||
error_log($q);
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r) && $f = pg_fetch_row($r)) {
|
||||
return $f[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getTzByAddressId($id)
|
||||
{
|
||||
global $readOnlyReplicaConn;
|
||||
|
||||
$q = "SELECT timezone FROM address_timezone WHERE id=(SELECT timezone FROM address WHERE id=" . ((int) $id) . ")";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
if ($r && pg_num_rows($r) && $f = pg_fetch_row($r)) {
|
||||
return $f[0];
|
||||
}
|
||||
return 'America/Los_Angeles'; // 2
|
||||
}
|
||||
|
||||
function getTimeZoneID($name)
|
||||
{
|
||||
global $readOnlyReplicaConn, $conn;
|
||||
|
||||
$q = "SELECT id FROM address_timezone WHERE timezone='" . pg_escape_string($name) . "'";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
if ($r && pg_num_rows($r) && $f = pg_fetch_row($r)) {
|
||||
return $f[0];
|
||||
}
|
||||
$q = "INSERT INTO address_timezone (timezone) VALUES('" . pg_escape_string($name) . "') RETURNING id";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r) && $f = pg_fetch_row($r)) {
|
||||
return $f[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getCityId($city, $country_code, $latitude, $longitude)
|
||||
{
|
||||
global $readOnlyReplicaConn, $conn;
|
||||
$q = "SELECT id FROM geofence_area_city WHERE LOWER(city) ILIKE '" . strtolower(pg_escape_string($city)) . "' AND country='" . $country_code . "' OR (latitude='" . $latitude . "' AND longitude='" . $longitude . "') LIMIT 1";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
if ($r && pg_num_rows($r) && $f = pg_fetch_assoc($r)) {
|
||||
return $f['id'];
|
||||
}
|
||||
$i = "INSERT INTO geofence_area_city (city,country,latitude,longitude,location) VALUES ('" . pg_escape_string($city) . "','${country_code}',${latitude},${longitude},ST_SetSRID(ST_MakePoint(${longitude},${latitude}), 4326)) RETURNING id";
|
||||
$r = pg_query($conn, $i);
|
||||
if ($r && pg_num_rows($r) && $f = pg_fetch_row($r)) {
|
||||
return $f[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function deleteCities($ids)
|
||||
{
|
||||
global $conn;
|
||||
if (is_array($ids) && count($ids) > 0) {
|
||||
$q1 = "DELETE FROM geofence_area_city WHERE id IN (" . implode(",", $ids) . ")";
|
||||
$r1 = pg_query($conn, $q1);
|
||||
if ($r1 && pg_affected_rows($r1)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function deleteDataTable($table_name, $condition = "")
|
||||
{
|
||||
global $conn;
|
||||
if (!empty($condition)) {
|
||||
$q1 = "DELETE FROM " . $table_name . " WHERE " . $condition;
|
||||
$r1 = pg_query($conn, $q1);
|
||||
if ($r1 && pg_affected_rows($r1)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function updateDataTable($table_name, $condition, $data)
|
||||
{
|
||||
global $conn, $readOnlyReplicaConn;
|
||||
$q = "select column_name, data_type, character_maximum_length from INFORMATION_SCHEMA.COLUMNS where table_name = '" . $table_name . "'";
|
||||
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
while ($f = pg_fetch_assoc($r)) {
|
||||
$columns[$f['column_name']] = $f['data_type'];
|
||||
}
|
||||
$q = "UPDATE " . $table_name . " SET id=id";
|
||||
foreach ($data as $key => $val) {
|
||||
if ($key == "id") {
|
||||
continue;
|
||||
}
|
||||
if (array_key_exists($key, $data) && !in_array($columns[$key], ['character varying', 'date', 'timestamp with time zone', 'timestamp without time zone'])) {
|
||||
$q .= ", ${key} = " . ($val == "" ? "NULL" : $val);
|
||||
} else {
|
||||
$q .= ", ${key} = '" . pg_escape_string($val) . "'";
|
||||
}
|
||||
}
|
||||
$q .= " WHERE " . $condition . "";
|
||||
echo $q . "\n";
|
||||
$r = pg_query($conn, $q);
|
||||
|
||||
$updated = pg_affected_rows($r);
|
||||
echo "[" . date("Y-m-d H:i:s") . "] update {$updated} rows of {$table_name} with {$condition} .\n";
|
||||
return $updated;
|
||||
}
|
||||
|
||||
function getForeignTables($table_name)
|
||||
{
|
||||
global $readOnlyReplicaConn;
|
||||
$q = "SELECT
|
||||
tc.table_name, kcu.column_name,
|
||||
ccu.table_name AS foreign_table_name,
|
||||
ccu.column_name AS foreign_column_name
|
||||
FROM
|
||||
information_schema.table_constraints AS tc
|
||||
JOIN information_schema.key_column_usage AS kcu
|
||||
ON tc.constraint_name = kcu.constraint_name
|
||||
JOIN information_schema.constraint_column_usage AS ccu
|
||||
ON ccu.constraint_name = tc.constraint_name
|
||||
WHERE constraint_type = 'FOREIGN KEY' AND ccu.table_name='" . $table_name . "'";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
|
||||
$result = [];
|
||||
while ($f = pg_fetch_assoc($r)) {
|
||||
$result[] = $f;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
function getGeoName($city, $country_code)
|
||||
{
|
||||
global $readOnlyReplicaConn;
|
||||
$q = "SELECT name,country,latitude,longitude,location FROM geoname WHERE LOWER(name) ILIKE '" . strtolower(pg_escape_string($city)) . "' AND country='" . $country_code . "' LIMIT 1";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
if ($r && pg_num_rows($r) && $f = pg_fetch_assoc($r)) {
|
||||
return $f;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function insertPostalCode($geoname, $postal, $latitude, $longitude, $country)
|
||||
{
|
||||
global $conn, $readOnlyReplicaConn;
|
||||
|
||||
if (strlen($geoname) > 100) {
|
||||
$geoname = substr($geoname, 0, 99);
|
||||
}
|
||||
$q = "SELECT id FROM geoname_postal_code WHERE postal ILIKE '" . pg_escape_string($postal) . "' AND latitude='" . $latitude . "' AND longitude='" . $longitude . "' LIMIT 1";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
if ($r && pg_num_rows($r) && $f = pg_fetch_assoc($r)) {
|
||||
return $f['id'];
|
||||
}
|
||||
$i = "INSERT INTO geoname_postal_code (geoname, postal, latitude,longitude, country, geometry) VALUES ('" . pg_escape_string($geoname) . "','" . pg_escape_string($postal) . "',${latitude},${longitude},'" . pg_escape_string($country) . "',ST_SetSRID(ST_MakePoint(${longitude},${latitude}), 4326)) RETURNING id";
|
||||
$r = pg_query($conn, $i);
|
||||
if ($r && pg_num_rows($r) && $f = pg_fetch_row($r)) {
|
||||
return $f[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getPostalCode($latitude, $longitude, $country, $distance = 50000)
|
||||
{
|
||||
global $readOnlyReplicaConn;
|
||||
|
||||
$q = "SELECT postal,
|
||||
ST_DistanceSphere(geometry::geometry, ST_SetSRID(ST_MakePoint(" . $longitude . ", " . $latitude . "),4326)) AS distance
|
||||
FROM geoname_postal_code
|
||||
WHERE ST_DistanceSphere(geometry::geometry, ST_SetSRID(ST_MakePoint(" . $longitude . ", " . $latitude . "),4326)) BETWEEN 0 AND " . $distance . " AND country='" . $country . "'
|
||||
ORDER BY distance
|
||||
LIMIT 1;";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
if ($r && pg_num_rows($r) && $f = pg_fetch_assoc($r)) {
|
||||
return $f['postal'];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* get postal array from latitude, longitude
|
||||
*/
|
||||
function getPostalFromLatLng($latitude, $longitude, int $distance_in_km)
|
||||
{
|
||||
global $conn, $readOnlyReplicaConn;
|
||||
$earth_radius = 6371;
|
||||
$km_per_degree_lat = 111.2;
|
||||
$pi = 3.14 / 180;
|
||||
|
||||
$query = " SELECT postal FROM (
|
||||
SELECT (
|
||||
$earth_radius * acos(
|
||||
cos( radians( {$latitude}) )
|
||||
* cos( radians( latitude ) )
|
||||
* cos( radians( longitude ) - radians( {$longitude} ) )
|
||||
+ sin( radians( {$latitude}) )
|
||||
* sin( radians( latitude ) )
|
||||
)
|
||||
) AS distance
|
||||
, *
|
||||
FROM postal_code
|
||||
WHERE
|
||||
postal IS NOT NULL
|
||||
AND latitude BETWEEN " . ($latitude - ($distance_in_km / $km_per_degree_lat)) .
|
||||
" AND " . ($latitude + ($distance_in_km / $km_per_degree_lat));
|
||||
|
||||
$delta = round($distance_in_km / ($km_per_degree_lat * COS(deg2rad($longitude))), 10);
|
||||
|
||||
// Bounding box for speed - latitude within range (longtitude to km not linear)
|
||||
if (cos($longitude * $pi) > 0) {
|
||||
|
||||
$from = $longitude - $delta;
|
||||
$to = $longitude + $delta;
|
||||
|
||||
$query .=
|
||||
" AND address.longitude" .
|
||||
" BETWEEN " . $from .
|
||||
" AND " . $to;
|
||||
|
||||
} else {
|
||||
|
||||
$from = $longitude + $delta;
|
||||
$to = $longitude - $delta;
|
||||
|
||||
$query .=
|
||||
" AND address.longitude" .
|
||||
" BETWEEN " . $from .
|
||||
" AND " . $to;
|
||||
|
||||
}
|
||||
|
||||
// distance limit for circle
|
||||
$query .= " ) address
|
||||
WHERE distance < " . $distance_in_km;
|
||||
|
||||
$rs = pg_query($readOnlyReplicaConn, $query) or die("Cannot execute query: $query\n");
|
||||
|
||||
if (!$rs) {
|
||||
echo "An error occurred.\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
return array_column(pg_fetch_all($rs), 'postal');
|
||||
}
|
||||
|
||||
function insertActionLog($table_name="quotes",$operation="",$input_data="", $response_data="", $url="")
|
||||
{
|
||||
global $conn;
|
||||
|
||||
$input_data = is_array($input_data) || is_object($input_data) ? json_encode($input_data) : $input_data;
|
||||
$response_data = is_array($response_data) || is_object($response_data) ? json_encode($response_data) : $response_data;
|
||||
$q = "INSERT INTO action_logs (created,table_name,operation,input_data,response_data, url) ";
|
||||
$q.= " VALUES(NOW(),'".$table_name."','".$operation."',";
|
||||
$q.= "'".pg_escape_string($input_data)."','".pg_escape_string($response_data)."','".$url."') RETURNING id";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) {
|
||||
return true;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function parseAddressByCountry($address = "", $country_code = "")
|
||||
{
|
||||
$city = $state = $country = "";
|
||||
if ($country_code == "AE") { //United Arab Emirates
|
||||
$address_info = explode("-", $address);
|
||||
} else {
|
||||
$address_info = explode(",", $address);
|
||||
}
|
||||
|
||||
switch ($country_code) {
|
||||
case "AU": //Australia
|
||||
$country = trim(array_pop($address_info));
|
||||
$state_city = explode(" ", trim(array_pop($address_info)));
|
||||
$postal = trim(array_pop($state_city));
|
||||
$state = trim(array_pop($state_city));
|
||||
$city = trim(array_pop($state_city));
|
||||
break;
|
||||
case "BR": //Brazil
|
||||
$country = trim(array_pop($address_info));
|
||||
$state = trim(array_pop($address_info));
|
||||
$city = array_pop($address_info);
|
||||
$city = explode('-', $city);
|
||||
$city = trim($city[0]);
|
||||
break;
|
||||
case "SG":
|
||||
$country = $city = "Singapore";
|
||||
break;
|
||||
case "HK":
|
||||
$country = $city = "Hong Kong";
|
||||
break;
|
||||
case "US":
|
||||
$country = trim(array_pop($address_info));
|
||||
$state = trim(array_pop($address_info));
|
||||
$city = $state;
|
||||
if (preg_replace('/[^0-9]/', '', $state) != "") {
|
||||
$city = trim(array_pop($address_info));
|
||||
}
|
||||
break;
|
||||
case "CA": //Canada
|
||||
case "IN": //India
|
||||
case "ZA": //South Africa
|
||||
case "MY": //Malaysia
|
||||
case "PH": //Philippines
|
||||
$country = trim(array_pop($address_info));
|
||||
$state = trim(array_pop($address_info));
|
||||
$city = trim(array_pop($address_info));
|
||||
if ($country_code == "MY") {
|
||||
$city = parseName($city);
|
||||
}
|
||||
break;
|
||||
case "ID": //Indonesia
|
||||
$country = trim(array_pop($address_info));
|
||||
$city = trim(array_pop($address_info));
|
||||
$city = parseName($city);
|
||||
$city_info = explode(" ", $city);
|
||||
$city = trim(array_pop($city_info));
|
||||
break;
|
||||
case "AT": //Autria
|
||||
case "FI": //Finland
|
||||
case "SE": //Sweden
|
||||
case "BE": //Belgium
|
||||
case "DE": //Germany
|
||||
case "FR": //France
|
||||
case "TH": //Thailand
|
||||
case "NP": //Nepal
|
||||
$country = trim(array_pop($address_info));
|
||||
$city = trim(array_pop($address_info));
|
||||
$city = parseName($city);
|
||||
break;
|
||||
|
||||
case "NZ": //New Zealand
|
||||
$country = trim(array_pop($address_info));
|
||||
$city = trim(array_pop($address_info));
|
||||
$city = parseName($city);
|
||||
if ($city == "") {
|
||||
$city = trim(array_pop($address_info));
|
||||
}
|
||||
break;
|
||||
|
||||
case "NL": //Netherlands
|
||||
$country = trim(array_pop($address_info));
|
||||
$city = trim(array_pop($address_info));
|
||||
$city = parseName($city);
|
||||
$city = explode(' ', $city);
|
||||
$city = trim(array_pop($city));
|
||||
break;
|
||||
|
||||
/*case "TR"://Turkey
|
||||
$country = trim(array_pop($address_info));
|
||||
$city = array_pop($address_info);
|
||||
$city = explode('/', $city);
|
||||
$city = trim(array_pop($city));
|
||||
break;*/
|
||||
case "UA": //Ukraina
|
||||
$count_address = count($address_info);
|
||||
|
||||
if ($count_address < 5) {
|
||||
$country = trim(array_pop($address_info));
|
||||
$city = trim(array_pop($address_info));
|
||||
} else {
|
||||
if ($count_address == 5) {
|
||||
$country = $address_info[$count_address - 2];
|
||||
$city = $address_info[$count_address - 3];
|
||||
} else {
|
||||
$country = $address_info[$count_address - 2];
|
||||
$city = $address_info[$count_address - 4];
|
||||
}
|
||||
}
|
||||
$city = parseName($city);
|
||||
break;
|
||||
case "GB": //Great Britain
|
||||
$country = trim(array_pop($address_info));
|
||||
$city = trim(array_pop($address_info));
|
||||
$city = explode(' ', $city);
|
||||
$city = trim($city[0]);
|
||||
break;
|
||||
|
||||
case "UA": //Ukraina
|
||||
case "TR": //Turkey
|
||||
case "PL": //Poland
|
||||
case "RO": //Romania
|
||||
$city = "";
|
||||
break;
|
||||
case "TW": //Taiwan
|
||||
$country = trim(array_pop($address_info));
|
||||
$city = array_pop($address_info);
|
||||
break;
|
||||
default:
|
||||
$country = trim(array_pop($address_info));
|
||||
$city = trim(array_pop($address_info));
|
||||
}
|
||||
|
||||
return [
|
||||
"address" => $address,
|
||||
"city" => $city,
|
||||
"state" => $state,
|
||||
"country_code" => $country_code,
|
||||
"country" => $country,
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
function parseName($name)
|
||||
{
|
||||
$name = trim(preg_replace('/[0-9]+/', '', $name));
|
||||
return $name;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
require '../backend.php';
|
||||
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
$oauth_api = $savvyext->cfgReadChar('system.oauth2_url');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
// Create readOnlyReplicaConn for readonly database
|
||||
$db_read_only_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_read_only_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_read_only_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_read_only_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_read_only_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readonlyconnstr = "host=${db_read_only_host} port=${db_read_only_port} dbname=${db_read_only_name} user=${db_read_only_user} password=${db_read_only_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readonlyconnstr);
|
||||
|
||||
$city_keywords = ["city", "province", "capital", "town"];
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
function parseEmail($email_id)
|
||||
{
|
||||
global $httpAuthToken,$oauth_api;
|
||||
$url = $oauth_api."parse/" . $email_id;
|
||||
$opts = array(
|
||||
'http' => array(
|
||||
'method' => "GET",
|
||||
'timeout' => 60, /* 1 minute */
|
||||
'header' =>
|
||||
"Content-Type: application/x-www-form-urlencoded\r\n" .
|
||||
"Accept: application/json\r\n" .
|
||||
"Authorization: Server-Token ${httpAuthToken}\r\n",
|
||||
),
|
||||
);
|
||||
|
||||
$context = stream_context_create($opts);
|
||||
$body = file_get_contents($url, false, $context);
|
||||
$geocoded = json_decode($body, true);
|
||||
if (is_array($geocoded) && is_array($geocoded["data"]) && !isset($geocoded["error"])) {
|
||||
return $geocoded["data"];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
function updateParsedEmail($id, $location_start_id, $location_end_id)
|
||||
{
|
||||
global $conn;
|
||||
$q = "UPDATE parsedemail_item SET updated=NOW(), location_start_id=" . $location_start_id . ", location_end_id=" . $location_end_id . "
|
||||
WHERE id = " . $id . "";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r) && $f = pg_fetch_assoc($r)) {
|
||||
return [$f, null];
|
||||
}
|
||||
return [null, pg_last_error($conn)];
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
function d($value, $exit = 0)
|
||||
{
|
||||
if (is_array($value)) {
|
||||
print_r($value);
|
||||
} else if (is_object($value)) {
|
||||
var_dump($value);
|
||||
} else {
|
||||
echo $value;
|
||||
}
|
||||
echo "<br/>";
|
||||
if ($exit) {
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
function convertUtcToLocal($datetime, $timezone = '', $format = 'Y-m-d H:i:s')
|
||||
{
|
||||
if (!empty($datetime) && !empty($timezone)) {
|
||||
$datetime = date($format, strtotime($datetime));
|
||||
$utc_date = DateTime::createFromFormat(
|
||||
$format,
|
||||
$datetime,
|
||||
new DateTimeZone('UTC')
|
||||
);
|
||||
if ($utc_date) {
|
||||
$utc_date->setTimeZone(new DateTimeZone($timezone));
|
||||
return $utc_date->format($format);
|
||||
}
|
||||
}
|
||||
return $datetime;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
# use /bin/bash to run commands, no matter what /etc/passwd says
|
||||
SHELL=/bin/bash
|
||||
# mail any output to `paul', no matter whose crontab this is
|
||||
MAILTO=olu@float.sg
|
||||
# run five minutes after midnight, every day
|
||||
5 0 * * * /home/savvy/backup.sh
|
||||
*/2 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f account_record_import.php)
|
||||
*/5 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f transactions_record_import.php)
|
||||
#*/60 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/batch && php -f batch_quote_popular.php > batch_quote_popular.log 2>&1)
|
||||
##*/60 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/batch && php -f batch_quote_sanfrancisco_districts.php > batch_quote_sanfrancisco_districts.log 2>&1)
|
||||
##*/30 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f background_quote_check.php > background_quote_check.log 2>&1)
|
||||
*/5 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f member_notification.php)
|
||||
*/5 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f member_prepare_notification.php)
|
||||
*/5 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f member_lifecyle_emails.php)
|
||||
*/5 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f account_benefit_import.php)
|
||||
*/35 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f account_process_subscription.php)
|
||||
## */5 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f account_benefit_import.php)
|
||||
# run five minutes after 4am (12 pm Singapore), every day
|
||||
##5 4 * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/batch && php -f batch_quote_tourist_attractions.php > batch_quote_tourist_attractions.log 2>&1)
|
||||
*/4 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f decision_generator.php > decisison_generator.log 2>&1)
|
||||
#*/60 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f member_tracking_duration.php)
|
||||
*/15 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f geocode_address.php)
|
||||
*/5 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f account_audit.php)
|
||||
*/5 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f points_audit.php)
|
||||
*/6 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f update_address_data.php)
|
||||
*/20 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f update_cheapest_data.php > update_cheapest_data.log 2>&1)
|
||||
*/5 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f gps_parsedemail_item_sync.php)
|
||||
*/60 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f gps_parsedemail_item_sync_skipped.php)
|
||||
*/5 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f account_location_audit.php)
|
||||
*/60 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f members_devices_check.php)
|
||||
#45 10 * * * /usr/local/bin/report
|
||||
3 1 * * * /usr/bin/supervisorctl restart worker_weather:
|
||||
1 1 * * * /bin/systemctl restart supervisord.service
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# use /bin/bash to run commands, no matter what /etc/passwd says
|
||||
SHELL=/bin/bash
|
||||
# mail any output to `paul', no matter whose crontab this is
|
||||
MAILTO=olu@float.sg
|
||||
# run five minutes after midnight, every day
|
||||
5 0 * * * /home/savvy/backup.sh
|
||||
*/2 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f account_record_import.php)
|
||||
#*/60 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/batch && php -f batch_quote_popular.php > batch_quote_popular.log 2>&1)
|
||||
##*/60 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/batch && php -f batch_quote_sanfrancisco_districts.php > batch_quote_sanfrancisco_districts.log 2>&1)
|
||||
##*/30 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f background_quote_check.php > background_quote_check.log 2>&1)
|
||||
*/30 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/batch && php -f batch_absent_quote_singapore_districts.php > batch_absent_quote_singapore_districts.log 2>&1)
|
||||
*/5 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f member_notification.php)
|
||||
*/5 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f member_prepare_notification.php)
|
||||
*/5 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f member_lifecyle_emails.php)
|
||||
*/5 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f account_benefit_import.php)
|
||||
*/5 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f transactions_record_import.php)
|
||||
*/5 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f subscribed_summary.php)
|
||||
# run 6:00 pm Singapore, every day
|
||||
0 14 * * MON (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f send_email_parse_fail_report.php)
|
||||
# run five minutes after 4am (12 pm Singapore), every day
|
||||
##5 4 * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/batch && php -f batch_quote_tourist_attractions.php > batch_quote_tourist_attractions.log 2>&1)
|
||||
*/4 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f decision_generator.php > decisison_generator.log 2>&1)
|
||||
#*/60 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f member_tracking_duration.php)
|
||||
*/15 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f geocode_address.php)
|
||||
*/5 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f account_audit.php)
|
||||
*/5 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f points_audit.php)
|
||||
*/6 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f update_address_data.php)
|
||||
*/20 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f update_cheapest_data.php > update_cheapest_data.log 2>&1)
|
||||
*/5 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f gps_parsedemail_item_sync.php)
|
||||
*/60 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f gps_parsedemail_item_sync_skipped.php)
|
||||
*/5 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f account_location_audit.php)
|
||||
*/60 * * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f members_devices_check.php)
|
||||
0 1 * * 1 (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f automation_report.php)
|
||||
0 0 1 * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f parking_lot.php)
|
||||
#45 10 * * * /usr/local/bin/report
|
||||
3 1 * * * /usr/bin/supervisorctl restart worker_weather:
|
||||
1 1 * * * /bin/systemctl restart supervisord.service
|
||||
# run At 18:00 NZST ~ 14:00 SG
|
||||
0 14 * * * (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f app_report_sign_up_emails_last_24hrs.php)
|
||||
0 14 * * MON (cd /home/savvy/FloatWeb/adminsavvy/CRONS/ && php -f email_lists_for_customer_journey_emails.php)
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
echo "[".date("Y-m-d H:i:s")."] Daily Report job is starting.\n";
|
||||
include '../backend.php';
|
||||
define("FLOAT_SYSTEM_DAILY_REPORT", 91011);
|
||||
|
||||
function Fextension_call($in, &$out) {
|
||||
// logToFl("Merchant_Name count->" . $in["merchant_name"]);
|
||||
global $savvyext;
|
||||
$out = $savvyext->savvyext_api($in);
|
||||
$ret = $out["retval"];
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$inX["limit"] = 750;
|
||||
$inX["offset"] = 0;
|
||||
$outX=array();
|
||||
|
||||
|
||||
$extension_call = true;
|
||||
|
||||
if ($extension_call == true ) {
|
||||
// logToFl("merchant_name count->" . $res->merchant_name);
|
||||
Fextension_call($inX, $outX);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
echo "[".date("Y-m-d H:i:s")."] Decision Generator job is starting.\n";
|
||||
include '../backend.php';
|
||||
define("FLOAT_SYSTEM_DESCISION_GENERATOR", 92012);
|
||||
|
||||
function Fextension_call($in, &$out) {
|
||||
global $savvyext;
|
||||
$out = $savvyext->savvyext_api($in);
|
||||
$ret = $out["retval"];
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$inX["limit"] = 50;
|
||||
$inX["pid"] = 0;
|
||||
$inX["action"] = FLOAT_SYSTEM_DESCISION_GENERATOR;
|
||||
$outX=array();
|
||||
|
||||
|
||||
$extension_call = true;
|
||||
|
||||
if ($extension_call == true ) {
|
||||
Fextension_call($inX, $outX);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:v="urn:schemas-microsoft-com:vml">
|
||||
<head>
|
||||
<!--[if gte mso 9]><xml><o:OfficeDocumentSettings><o:AllowPNG/><o:PixelsPerInch>96</o:PixelsPerInch></o:OfficeDocumentSettings></xml><![endif]-->
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
|
||||
<meta content="width=device-width" name="viewport"/>
|
||||
<!--[if !mso]><!-->
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible"/>
|
||||
<!--<![endif]-->
|
||||
<title></title>
|
||||
<!--[if !mso]><!-->
|
||||
<!--<![endif]-->
|
||||
<style type="text/css">
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
table,
|
||||
td,
|
||||
tr {
|
||||
vertical-align: top;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
* {
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
a[x-apple-data-detectors=true] {
|
||||
color: inherit !important;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
</style>
|
||||
<style id="media-query" type="text/css">
|
||||
@media (max-width: 660px) {
|
||||
|
||||
.block-grid,
|
||||
.col {
|
||||
min-width: 320px !important;
|
||||
max-width: 100% !important;
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.block-grid {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.col {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.col>div {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
img.fullwidth,
|
||||
img.fullwidthOnMobile {
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
.no-stack .col {
|
||||
min-width: 0 !important;
|
||||
display: table-cell !important;
|
||||
}
|
||||
|
||||
.no-stack.two-up .col {
|
||||
width: 50% !important;
|
||||
}
|
||||
|
||||
.no-stack .col.num4 {
|
||||
width: 33% !important;
|
||||
}
|
||||
|
||||
.no-stack .col.num8 {
|
||||
width: 66% !important;
|
||||
}
|
||||
|
||||
.no-stack .col.num4 {
|
||||
width: 33% !important;
|
||||
}
|
||||
|
||||
.no-stack .col.num3 {
|
||||
width: 25% !important;
|
||||
}
|
||||
|
||||
.no-stack .col.num6 {
|
||||
width: 50% !important;
|
||||
}
|
||||
|
||||
.no-stack .col.num9 {
|
||||
width: 75% !important;
|
||||
}
|
||||
|
||||
.video-block {
|
||||
max-width: none !important;
|
||||
}
|
||||
|
||||
.mobile_hide {
|
||||
min-height: 0px;
|
||||
max-height: 0px;
|
||||
max-width: 0px;
|
||||
display: none;
|
||||
overflow: hidden;
|
||||
font-size: 0px;
|
||||
}
|
||||
|
||||
.desktop_hide {
|
||||
display: block !important;
|
||||
max-height: none !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="clean-body" style="margin: 0; padding: 0; -webkit-text-size-adjust: 100%; background-color: #FFFFFF;">
|
||||
<!--[if IE]><div class="ie-browser"><![endif]-->
|
||||
<table bgcolor="#FFFFFF" cellpadding="0" cellspacing="0" class="nl-container" role="presentation" style="table-layout: fixed; vertical-align: top; min-width: 320px; Margin: 0 auto; border-spacing: 0; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; background-color: #FFFFFF; width: 100%;" valign="top" width="100%">
|
||||
<tbody>
|
||||
<tr style="vertical-align: top;" valign="top">
|
||||
<td style="word-break: break-word; vertical-align: top;" valign="top">
|
||||
<!--[if (mso)|(IE)]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td align="center" style="background-color:#FFFFFF"><![endif]-->
|
||||
<div style="background-color:transparent;">
|
||||
<div class="block-grid" style="Margin: 0 auto; min-width: 320px; max-width: 640px; overflow-wrap: break-word; word-wrap: break-word; word-break: break-word; background-color: transparent;">
|
||||
<div style="border-collapse: collapse;display: table;width: 100%;background-color:transparent;">
|
||||
<!--[if (mso)|(IE)]><table width="100%" cellpadding="0" cellspacing="0" border="0" style="background-color:transparent;"><tr><td align="center"><table cellpadding="0" cellspacing="0" border="0" style="width:740px"><tr class="layout-full-width" style="background-color:transparent"><![endif]-->
|
||||
<!--[if (mso)|(IE)]><td align="center" width="740" style="background-color:transparent;width:740px; border-top: 0px solid transparent; border-left: 0px solid transparent; border-bottom: 0px solid transparent; border-right: 0px solid transparent;" valign="top"><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding-right: 0px; padding-left: 0px; padding-top:5px; padding-bottom:5px;"><![endif]-->
|
||||
<div class="col num12" style="min-width: 320px; max-width: 640px; display: table-cell; vertical-align: top; width: 740px;">
|
||||
<div style="width:100% !important;">
|
||||
<!--[if (!mso)&(!IE)]><!-->
|
||||
<div style="border-top:0px solid transparent; border-left:0px solid transparent; border-bottom:0px solid transparent; border-right:0px solid transparent; padding-top:5px; padding-bottom:5px; padding-right: 0px; padding-left: 0px;">
|
||||
<!--<![endif]-->
|
||||
<table border="0" cellpadding="0" cellspacing="0" class="divider" role="presentation" style="table-layout: fixed; vertical-align: top; border-spacing: 0; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; min-width: 100%; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;" valign="top" width="100%">
|
||||
<tbody>
|
||||
<tr style="vertical-align: top;" valign="top">
|
||||
<td class="divider_inner" style="word-break: break-word; vertical-align: top; min-width: 100%; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px;" valign="top">
|
||||
<table align="center" border="0" cellpadding="0" cellspacing="0" class="divider_content" role="presentation" style="table-layout: fixed; vertical-align: top; border-spacing: 0; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; border-top: 0px solid #FFFFFF; width: 100%;" valign="top" width="100%">
|
||||
<tbody>
|
||||
<tr style="vertical-align: top;" valign="top">
|
||||
<td style="word-break: break-word; vertical-align: top; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;" valign="top"><span></span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<!--[if (!mso)&(!IE)]><!-->
|
||||
</div>
|
||||
<!--<![endif]-->
|
||||
</div>
|
||||
</div>
|
||||
<!--[if (mso)|(IE)]></td></tr></table><![endif]-->
|
||||
<!--[if (mso)|(IE)]></td></tr></table></td></tr></table><![endif]-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php $job_name = pathinfo(__FILE__, PATHINFO_FILENAME); ?>
|
||||
<div style="background-color:transparent;">
|
||||
<div class="block-grid mixed-two-up" style="Margin: 0 auto; min-width: 320px; max-width: 640px; overflow-wrap: break-word; word-wrap: break-word; word-break: break-word; background-color: #5c98c7;">
|
||||
<div style="border-collapse: collapse;display: table;width: 100%;background-color:#5c98c7;">
|
||||
<!--[if (mso)|(IE)]><table width="100%" cellpadding="0" cellspacing="0" border="0" style="background-color:transparent;"><tr><td align="center"><table cellpadding="0" cellspacing="0" border="0" style="width:740px"><tr class="layout-full-width" style="background-color:#5c98c7"><![endif]-->
|
||||
<!--[if (mso)|(IE)]><td align="center" width="426" style="background-color:#5c98c7;width:426px; border-top: 0px solid transparent; border-left: 0px solid transparent; border-bottom: 0px solid transparent; border-right: 0px solid transparent;" valign="top"><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding-right: 30px; padding-left: 30px; padding-top:20px; padding-bottom:20px;"><![endif]-->
|
||||
<div class="col num8" style="display: table-cell; vertical-align: top; min-width: 320px; max-width: 424px; width: 426px;">
|
||||
<div style="width:100% !important;">
|
||||
<!--[if (!mso)&(!IE)]><!-->
|
||||
<div style="border-top:0px solid transparent; border-left:0px solid transparent; border-bottom:0px solid transparent; border-right:0px solid transparent; padding-top:20px; padding-bottom:20px; padding-right: 30px; padding-left: 30px;">
|
||||
<!--<![endif]-->
|
||||
<!--[if mso]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding-right: 10px; padding-left: 10px; padding-top: 10px; padding-bottom: 0px; font-family: Tahoma, Verdana, sans-serif"><![endif]-->
|
||||
<div style="color:#ffffff;font-family:Lato, Tahoma, Verdana, Segoe, sans-serif;line-height:1.2;padding-top:10px;padding-right:10px;padding-bottom:0px;padding-left:10px;">
|
||||
<div style="font-size: 14px; line-height: 1.2; color: #ffffff; font-family: Lato, Tahoma, Verdana, Segoe, sans-serif; mso-line-height-alt: 17px;">
|
||||
<p style="font-size: 20px; line-height: 1.2; word-break: break-word; text-align: left; mso-line-height-alt: 24px; margin: 0;"><span style="font-size: 20px;"><strong><?php echo "[" . date("Y-m-d H:i:s") . "] " . $job_name . " job is starting.\n"; ?></strong></span></p>
|
||||
</div>
|
||||
</div>
|
||||
<!--[if mso]></td></tr></table><![endif]-->
|
||||
<!--[if mso]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding-right: 10px; padding-left: 10px; padding-top: 0px; padding-bottom: 10px; font-family: Tahoma, Verdana, sans-serif"><![endif]-->
|
||||
<!-- <div style="color:#ffffff;font-family:Lato, Tahoma, Verdana, Segoe, sans-serif;line-height:1.5;padding-top:0px;padding-right:10px;padding-bottom:10px;padding-left:10px;">
|
||||
<div style="font-size: 14px; line-height: 1.5; color: #ffffff; font-family: Lato, Tahoma, Verdana, Segoe, sans-serif; mso-line-height-alt: 21px;">
|
||||
<p style="font-size: 14px; line-height: 1.5; word-break: break-word; text-align: left; mso-line-height-alt: 21px; margin: 0;">Company Name LLC, represented by John Doe,</p>
|
||||
<p style="font-size: 14px; line-height: 1.5; word-break: break-word; text-align: left; mso-line-height-alt: 21px; margin: 0;">ID: 020 5793 9378, Prairie Drive Far,</p>
|
||||
<p style="font-size: 14px; line-height: 1.5; word-break: break-word; text-align: left; mso-line-height-alt: 21px; margin: 0;">Rockaway, Y 11691, US</p>
|
||||
</div>
|
||||
</div>
|
||||
--> <!--[if mso]></td></tr></table><![endif]-->
|
||||
<!--[if (!mso)&(!IE)]><!-->
|
||||
</div>
|
||||
<!--<![endif]-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Start Automations Table -->
|
||||
<div style="background-color:transparent;">
|
||||
<div class="block-grid four-up no-stack" style="Margin: 0 auto; min-width: 320px; max-width: 640px; overflow-wrap: break-word; word-wrap: break-word; word-break: break-word; background-color: #5c98c7; text-align: center; color: #ffffff; padding-bottom: 10px; font-size: 22px;">
|
||||
<strong>SendGrid Tracking Report</strong>
|
||||
</div>
|
||||
<div align="center" class="img-container center autowidth" style="padding-right: 0px;padding-left: 0px;">
|
||||
<!--[if mso]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr style="line-height:0px"><td style="padding-right: 0px;padding-left: 0px;" align="center"><![endif]--><img align="center" alt="Image" border="0" class="center autowidth" src="<?php echo $sendgrid_tracking; ?>" style="text-decoration: none; -ms-interpolation-mode: bicubic; height: auto; border: 0; width: 100%; max-width: 640px; display: block;" title="Image" width="481"/>
|
||||
<!--[if mso]></td></tr></table><![endif]-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Start Installed OS -->
|
||||
<div style="background-color:transparent;">
|
||||
<div class="block-grid four-up no-stack" style="Margin: 0 auto; min-width: 320px; max-width: 640px; overflow-wrap: break-word; word-wrap: break-word; word-break: break-word; background-color: #5c98c7; text-align: center; color: #ffffff; padding-bottom: 10px; font-size: 22px; padding-top: 20px;">
|
||||
<strong>BKO Tracking Report</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div align="center" class="img-container center autowidth" style="padding-right: 0px;padding-left: 0px;">
|
||||
<!--[if mso]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr style="line-height:0px"><td style="padding-right: 0px;padding-left: 0px;" align="center"><![endif]--><img align="center" alt="Image" border="0" class="center autowidth" src="<?php echo $bko_tracking; ?>" style="text-decoration: none; -ms-interpolation-mode: bicubic; height: auto; border: 0; width: 100%; max-width: 640px; display: block;" title="Image" width="481"/>
|
||||
<!--[if mso]></td></tr></table><![endif]-->
|
||||
</div>
|
||||
<!-- End Installed OS -->
|
||||
|
||||
<div style="background-color:transparent;">
|
||||
<div class="block-grid" style="Margin: 0 auto; min-width: 320px; max-width: 640px; overflow-wrap: break-word; word-wrap: break-word; word-break: break-word; background-color: #5c98c7;">
|
||||
<div style="border-collapse: collapse;display: table;width: 100%;background-color:#5c98c7;">
|
||||
<!--[if (mso)|(IE)]><table width="100%" cellpadding="0" cellspacing="0" border="0" style="background-color:transparent;"><tr><td align="center"><table cellpadding="0" cellspacing="0" border="0" style="width:740px"><tr class="layout-full-width" style="background-color:#5c98c7"><![endif]-->
|
||||
<!--[if (mso)|(IE)]><td align="center" width="740" style="background-color:#5c98c7;width:740px; border-top: 0px solid transparent; border-left: 0px solid transparent; border-bottom: 0px solid transparent; border-right: 0px solid transparent;" valign="top"><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding-right: 0px; padding-left: 0px; padding-top:0px; padding-bottom:0px;"><![endif]-->
|
||||
<div class="col num12" style="min-width: 320px; max-width: 640px; display: table-cell; vertical-align: top; width: 740px;">
|
||||
</div>
|
||||
<!--[if (mso)|(IE)]></td></tr></table><![endif]-->
|
||||
<!--[if (mso)|(IE)]></td></tr></table></td></tr></table><![endif]-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--[if (mso)|(IE)]></td></tr></table><![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<!--[if (IE)]></div><![endif]-->
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,179 @@
|
||||
<mjml>
|
||||
<mj-head>
|
||||
<mj-font name="Open Sans" href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,800" />
|
||||
<mj-attributes>
|
||||
<mj-all font-family="Open Sans, sans-serif" color="#fff" />
|
||||
</mj-attributes>
|
||||
<mj-style>
|
||||
|
||||
</mj-style>
|
||||
</mj-head>
|
||||
<mj-body width="1000px">
|
||||
<mj-wrapper padding="0">
|
||||
|
||||
<mj-section padding="0" background-color="#6da3cd">
|
||||
<mj-column width="20%">
|
||||
<mj-text font-weight="bold" align="center">
|
||||
Merchant Name
|
||||
</mj-text>
|
||||
</mj-column>
|
||||
<mj-column width="20%">
|
||||
<mj-text font-weight="bold" align="center">
|
||||
Transport
|
||||
</mj-text>
|
||||
</mj-column>
|
||||
<mj-column width="20%">
|
||||
<mj-text font-weight="bold" align="center">
|
||||
Total Emails
|
||||
</mj-text>
|
||||
</mj-column>
|
||||
<mj-column width="20%">
|
||||
<mj-text font-weight="bold" align="center">
|
||||
Success
|
||||
</mj-text>
|
||||
</mj-column>
|
||||
<mj-column width="20%">
|
||||
<mj-text font-weight="bold" align="center">
|
||||
Fail
|
||||
</mj-text>
|
||||
</mj-column>
|
||||
</mj-section>
|
||||
|
||||
<mj-section padding="0" background-color="#5c98c7" border-bottom="1px solid #6da3cd">
|
||||
<mj-raw>
|
||||
<?php if ( isset( $data['summary'] ) and ! empty( $data['summary'] ) ): ?>
|
||||
<?php foreach ( $data['summary'] as $key => $item ): ?>
|
||||
</mj-raw>
|
||||
<mj-column width="20%">
|
||||
<mj-text align="center">
|
||||
<mj-raw>
|
||||
<?php echo $item['name']; ?>
|
||||
</mj-raw>
|
||||
</mj-text>
|
||||
</mj-column>
|
||||
<mj-column width="20%">
|
||||
<mj-text align="center">
|
||||
<mj-raw>
|
||||
<?php echo $item['transport']; ?>
|
||||
</mj-raw>
|
||||
</mj-text>
|
||||
</mj-column>
|
||||
<mj-column width="20%">
|
||||
<mj-text align="center">
|
||||
<mj-raw>
|
||||
<?php echo $item['total']; ?>
|
||||
</mj-raw>
|
||||
</mj-text>
|
||||
</mj-column>
|
||||
<mj-column width="20%">
|
||||
<mj-text align="center">
|
||||
<mj-raw>
|
||||
<?php echo $item['success']; ?>
|
||||
</mj-raw>
|
||||
</mj-text>
|
||||
</mj-column>
|
||||
<mj-column width="20%">
|
||||
<mj-text align="center">
|
||||
<mj-raw>
|
||||
<?php echo $item['fail']; ?>
|
||||
</mj-raw>
|
||||
</mj-text>
|
||||
</mj-column>
|
||||
<mj-raw>
|
||||
<?php endforeach ?>
|
||||
<?php endif ?>
|
||||
</mj-raw>
|
||||
</mj-section>
|
||||
|
||||
</mj-wrapper>
|
||||
|
||||
<mj-wrapper padding-top="30px">
|
||||
|
||||
<mj-section padding="0" background-color="#6da3cd">
|
||||
<mj-column width="17%">
|
||||
<mj-text font-weight="bold" align="center">
|
||||
Merchant Name
|
||||
</mj-text>
|
||||
</mj-column>
|
||||
<mj-column width="15%">
|
||||
<mj-text font-weight="bold" align="center">
|
||||
Email ID
|
||||
</mj-text>
|
||||
</mj-column>
|
||||
<mj-column width="20%">
|
||||
<mj-text font-weight="bold" align="center">
|
||||
User
|
||||
</mj-text>
|
||||
</mj-column>
|
||||
<mj-column width="20%">
|
||||
<mj-text font-weight="bold" align="center">
|
||||
Subject
|
||||
</mj-text>
|
||||
</mj-column>
|
||||
<mj-column width="15%">
|
||||
<mj-text font-weight="bold" align="center">
|
||||
Send Date
|
||||
</mj-text>
|
||||
</mj-column>
|
||||
<mj-column width="13%">
|
||||
<mj-text font-weight="bold" align="center">
|
||||
Reported
|
||||
</mj-text>
|
||||
</mj-column>
|
||||
</mj-section>
|
||||
|
||||
<mj-section padding="0" background-color="#5c98c7" border-bottom="1px solid #6da3cd">
|
||||
<mj-raw>
|
||||
<?php if ( isset( $data['emails'] ) and ! empty( $data['emails'] ) ): ?>
|
||||
<?php foreach ( $data['emails'] as $key => $item ): ?>
|
||||
</mj-raw>
|
||||
<mj-column width="17%">
|
||||
<mj-text align="center">
|
||||
<mj-raw>
|
||||
<?php echo $item['merchant_name']; ?>
|
||||
</mj-raw>
|
||||
</mj-text>
|
||||
</mj-column>
|
||||
<mj-column width="15%">
|
||||
<mj-text align="center">
|
||||
<mj-raw>
|
||||
<?php echo $item['trackedemail_item_id']; ?>
|
||||
</mj-raw>
|
||||
</mj-text>
|
||||
</mj-column>
|
||||
<mj-column width="20%">
|
||||
<mj-text align="center">
|
||||
<mj-raw>
|
||||
<?php echo $item['email']; ?> (ID: <?php echo $item['user_id']; ?>)
|
||||
</mj-raw>
|
||||
</mj-text>
|
||||
</mj-column>
|
||||
<mj-column width="20%">
|
||||
<mj-text align="center">
|
||||
<mj-raw>
|
||||
<?php echo $item['subject']; ?>
|
||||
</mj-raw>
|
||||
</mj-text>
|
||||
</mj-column>
|
||||
<mj-column width="15%">
|
||||
<mj-text align="center">
|
||||
<mj-raw>
|
||||
<?php echo $item['message_date']; ?>
|
||||
</mj-raw>
|
||||
</mj-text>
|
||||
</mj-column>
|
||||
<mj-column width="13%">
|
||||
<mj-text align="center">
|
||||
<?php echo $item['reported']; ?>
|
||||
</mj-text>
|
||||
</mj-column>
|
||||
<mj-raw>
|
||||
<?php endforeach ?>
|
||||
<?php endif ?>
|
||||
</mj-raw>
|
||||
</mj-section>
|
||||
|
||||
</mj-wrapper>
|
||||
|
||||
</mj-body>
|
||||
</mjml>
|
||||
@@ -0,0 +1,695 @@
|
||||
<!doctype html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
||||
|
||||
<head>
|
||||
<title> </title>
|
||||
<!--[if !mso]><!-- -->
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<!--<![endif]-->
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style type="text/css">
|
||||
#outlook a {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-ms-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
table,
|
||||
td {
|
||||
border-collapse: collapse;
|
||||
mso-table-lspace: 0pt;
|
||||
mso-table-rspace: 0pt;
|
||||
}
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
height: auto;
|
||||
line-height: 100%;
|
||||
outline: none;
|
||||
text-decoration: none;
|
||||
-ms-interpolation-mode: bicubic;
|
||||
}
|
||||
|
||||
p {
|
||||
display: block;
|
||||
margin: 13px 0;
|
||||
}
|
||||
</style>
|
||||
<!--[if mso]>
|
||||
<xml>
|
||||
<o:OfficeDocumentSettings>
|
||||
<o:AllowPNG/>
|
||||
<o:PixelsPerInch>96</o:PixelsPerInch>
|
||||
</o:OfficeDocumentSettings>
|
||||
</xml>
|
||||
<![endif]-->
|
||||
<!--[if lte mso 11]>
|
||||
<style type="text/css">
|
||||
.mj-outlook-group-fix { width:100% !important; }
|
||||
</style>
|
||||
<![endif]-->
|
||||
<!--[if !mso]><!-->
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,800" rel="stylesheet" type="text/css">
|
||||
<style type="text/css">
|
||||
@import url(https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,800);
|
||||
</style>
|
||||
<!--<![endif]-->
|
||||
<style type="text/css">
|
||||
@media only screen and (min-width:480px) {
|
||||
.mj-column-per-20 {
|
||||
width: 20% !important;
|
||||
max-width: 20%;
|
||||
}
|
||||
.mj-column-per-17 {
|
||||
width: 17% !important;
|
||||
max-width: 17%;
|
||||
}
|
||||
.mj-column-per-15 {
|
||||
width: 15% !important;
|
||||
max-width: 15%;
|
||||
}
|
||||
.mj-column-per-13 {
|
||||
width: 13% !important;
|
||||
max-width: 13%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style type="text/css">
|
||||
</style>
|
||||
<style type="text/css"></style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="">
|
||||
<!--[if mso | IE]>
|
||||
<table
|
||||
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:1000px;" width="1000"
|
||||
>
|
||||
<tr>
|
||||
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
|
||||
<![endif]-->
|
||||
<div style="margin:0px auto;max-width:1000px;">
|
||||
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="direction:ltr;font-size:0px;padding:0;text-align:center;">
|
||||
<!--[if mso | IE]>
|
||||
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
|
||||
|
||||
<tr>
|
||||
<td
|
||||
class="" width="1000px"
|
||||
>
|
||||
|
||||
<table
|
||||
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:1000px;" width="1000"
|
||||
>
|
||||
<tr>
|
||||
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
|
||||
<![endif]-->
|
||||
<div style="background:#6da3cd;background-color:#6da3cd;margin:0px auto;max-width:1000px;">
|
||||
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#6da3cd;background-color:#6da3cd;width:100%;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="direction:ltr;font-size:0px;padding:0;text-align:center;">
|
||||
<!--[if mso | IE]>
|
||||
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
|
||||
|
||||
<tr>
|
||||
|
||||
<td
|
||||
class="" style="vertical-align:top;width:200px;"
|
||||
>
|
||||
<![endif]-->
|
||||
<div class="mj-column-per-20 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
|
||||
<tr>
|
||||
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Open Sans, sans-serif;font-size:13px;font-weight:bold;line-height:1;text-align:center;color:#ffffff;">Merchant Name</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="" style="vertical-align:top;width:200px;"
|
||||
>
|
||||
<![endif]-->
|
||||
<div class="mj-column-per-20 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
|
||||
<tr>
|
||||
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Open Sans, sans-serif;font-size:13px;font-weight:bold;line-height:1;text-align:center;color:#ffffff;">Transport</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="" style="vertical-align:top;width:200px;"
|
||||
>
|
||||
<![endif]-->
|
||||
<div class="mj-column-per-20 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
|
||||
<tr>
|
||||
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Open Sans, sans-serif;font-size:13px;font-weight:bold;line-height:1;text-align:center;color:#ffffff;">Total Emails</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="" style="vertical-align:top;width:200px;"
|
||||
>
|
||||
<![endif]-->
|
||||
<div class="mj-column-per-20 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
|
||||
<tr>
|
||||
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Open Sans, sans-serif;font-size:13px;font-weight:bold;line-height:1;text-align:center;color:#ffffff;">Success</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="" style="vertical-align:top;width:200px;"
|
||||
>
|
||||
<![endif]-->
|
||||
<div class="mj-column-per-20 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
|
||||
<tr>
|
||||
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Open Sans, sans-serif;font-size:13px;font-weight:bold;line-height:1;text-align:center;color:#ffffff;">Fail</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td
|
||||
class="" width="1000px"
|
||||
>
|
||||
|
||||
<table
|
||||
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:1000px;" width="1000"
|
||||
>
|
||||
<tr>
|
||||
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
|
||||
<![endif]-->
|
||||
<div style="background:#5c98c7;background-color:#5c98c7;margin:0px auto;max-width:1000px;">
|
||||
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#5c98c7;background-color:#5c98c7;width:100%;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="border-bottom:1px solid #6da3cd;direction:ltr;font-size:0px;padding:0;text-align:center;">
|
||||
<!--[if mso | IE]>
|
||||
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
|
||||
|
||||
<tr>
|
||||
<![endif]-->
|
||||
<?php if ( isset( $data['summary'] ) and ! empty( $data['summary'] ) ): ?>
|
||||
<?php foreach ( $data['summary'] as $key => $item ): ?>
|
||||
<!--[if mso | IE]>
|
||||
<td
|
||||
class="" style="vertical-align:top;width:200px;"
|
||||
>
|
||||
<![endif]-->
|
||||
<div class="mj-column-per-20 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
|
||||
<tr>
|
||||
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Open Sans, sans-serif;font-size:13px;line-height:1;text-align:center;color:#ffffff;">
|
||||
<mj-raw>
|
||||
<?php echo $item['name']; ?> </mj-raw>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="" style="vertical-align:top;width:200px;"
|
||||
>
|
||||
<![endif]-->
|
||||
<div class="mj-column-per-20 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
|
||||
<tr>
|
||||
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Open Sans, sans-serif;font-size:13px;line-height:1;text-align:center;color:#ffffff;">
|
||||
<mj-raw>
|
||||
<?php echo $item['transport']; ?> </mj-raw>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="" style="vertical-align:top;width:200px;"
|
||||
>
|
||||
<![endif]-->
|
||||
<div class="mj-column-per-20 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
|
||||
<tr>
|
||||
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Open Sans, sans-serif;font-size:13px;line-height:1;text-align:center;color:#ffffff;">
|
||||
<mj-raw>
|
||||
<?php echo $item['total']; ?> </mj-raw>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="" style="vertical-align:top;width:200px;"
|
||||
>
|
||||
<![endif]-->
|
||||
<div class="mj-column-per-20 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
|
||||
<tr>
|
||||
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Open Sans, sans-serif;font-size:13px;line-height:1;text-align:center;color:#ffffff;">
|
||||
<mj-raw>
|
||||
<?php echo $item['success']; ?> </mj-raw>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="" style="vertical-align:top;width:200px;"
|
||||
>
|
||||
<![endif]-->
|
||||
<div class="mj-column-per-20 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
|
||||
<tr>
|
||||
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Open Sans, sans-serif;font-size:13px;line-height:1;text-align:center;color:#ffffff;">
|
||||
<mj-raw>
|
||||
<?php echo $item['fail']; ?> </mj-raw>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
<![endif]-->
|
||||
<?php endforeach ?>
|
||||
<?php endif ?>
|
||||
<!--[if mso | IE]>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table
|
||||
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:1000px;" width="1000"
|
||||
>
|
||||
<tr>
|
||||
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
|
||||
<![endif]-->
|
||||
<div style="margin:0px auto;max-width:1000px;">
|
||||
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="direction:ltr;font-size:0px;padding:20px 0;padding-top:30px;text-align:center;">
|
||||
<!--[if mso | IE]>
|
||||
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
|
||||
|
||||
<tr>
|
||||
<td
|
||||
class="" width="1000px"
|
||||
>
|
||||
|
||||
<table
|
||||
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:1000px;" width="1000"
|
||||
>
|
||||
<tr>
|
||||
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
|
||||
<![endif]-->
|
||||
<div style="background:#6da3cd;background-color:#6da3cd;margin:0px auto;max-width:1000px;">
|
||||
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#6da3cd;background-color:#6da3cd;width:100%;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="direction:ltr;font-size:0px;padding:0;text-align:center;">
|
||||
<!--[if mso | IE]>
|
||||
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
|
||||
|
||||
<tr>
|
||||
|
||||
<td
|
||||
class="" style="vertical-align:top;width:170px;"
|
||||
>
|
||||
<![endif]-->
|
||||
<div class="mj-column-per-17 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
|
||||
<tr>
|
||||
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Open Sans, sans-serif;font-size:13px;font-weight:bold;line-height:1;text-align:center;color:#ffffff;">Merchant Name</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="" style="vertical-align:top;width:150px;"
|
||||
>
|
||||
<![endif]-->
|
||||
<div class="mj-column-per-15 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
|
||||
<tr>
|
||||
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Open Sans, sans-serif;font-size:13px;font-weight:bold;line-height:1;text-align:center;color:#ffffff;">Email ID</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="" style="vertical-align:top;width:200px;"
|
||||
>
|
||||
<![endif]-->
|
||||
<div class="mj-column-per-20 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
|
||||
<tr>
|
||||
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Open Sans, sans-serif;font-size:13px;font-weight:bold;line-height:1;text-align:center;color:#ffffff;">User</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="" style="vertical-align:top;width:200px;"
|
||||
>
|
||||
<![endif]-->
|
||||
<div class="mj-column-per-20 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
|
||||
<tr>
|
||||
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Open Sans, sans-serif;font-size:13px;font-weight:bold;line-height:1;text-align:center;color:#ffffff;">Subject</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="" style="vertical-align:top;width:150px;"
|
||||
>
|
||||
<![endif]-->
|
||||
<div class="mj-column-per-15 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
|
||||
<tr>
|
||||
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Open Sans, sans-serif;font-size:13px;font-weight:bold;line-height:1;text-align:center;color:#ffffff;">Send Date</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="" style="vertical-align:top;width:130px;"
|
||||
>
|
||||
<![endif]-->
|
||||
<div class="mj-column-per-13 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
|
||||
<tr>
|
||||
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Open Sans, sans-serif;font-size:13px;font-weight:bold;line-height:1;text-align:center;color:#ffffff;">Reported</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td
|
||||
class="" width="1000px"
|
||||
>
|
||||
|
||||
<table
|
||||
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:1000px;" width="1000"
|
||||
>
|
||||
<tr>
|
||||
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
|
||||
<![endif]-->
|
||||
<div style="background:#5c98c7;background-color:#5c98c7;margin:0px auto;max-width:1000px;">
|
||||
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#5c98c7;background-color:#5c98c7;width:100%;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="border-bottom:1px solid #6da3cd;direction:ltr;font-size:0px;padding:0;text-align:center;">
|
||||
<!--[if mso | IE]>
|
||||
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
|
||||
|
||||
<tr>
|
||||
<![endif]-->
|
||||
<?php if ( isset( $data['emails'] ) and ! empty( $data['emails'] ) ): ?>
|
||||
<?php foreach ( $data['emails'] as $key => $item ): ?>
|
||||
<!--[if mso | IE]>
|
||||
<td
|
||||
class="" style="vertical-align:top;width:170px;"
|
||||
>
|
||||
<![endif]-->
|
||||
<div class="mj-column-per-17 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
|
||||
<tr>
|
||||
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Open Sans, sans-serif;font-size:13px;line-height:1;text-align:center;color:#ffffff;">
|
||||
<mj-raw>
|
||||
<?php echo $item['merchant_name']; ?> </mj-raw>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="" style="vertical-align:top;width:150px;"
|
||||
>
|
||||
<![endif]-->
|
||||
<div class="mj-column-per-15 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
|
||||
<tr>
|
||||
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Open Sans, sans-serif;font-size:13px;line-height:1;text-align:center;color:#ffffff;">
|
||||
<mj-raw>
|
||||
<?php echo $item['trackedemail_item_id']; ?> </mj-raw>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="" style="vertical-align:top;width:200px;"
|
||||
>
|
||||
<![endif]-->
|
||||
<div class="mj-column-per-20 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
|
||||
<tr>
|
||||
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Open Sans, sans-serif;font-size:13px;line-height:1;text-align:center;color:#ffffff;">
|
||||
<mj-raw>
|
||||
<?php echo $item['email']; ?> (ID:
|
||||
<?php echo $item['user_id']; ?>) </mj-raw>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="" style="vertical-align:top;width:200px;"
|
||||
>
|
||||
<![endif]-->
|
||||
<div class="mj-column-per-20 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
|
||||
<tr>
|
||||
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Open Sans, sans-serif;font-size:13px;line-height:1;text-align:center;color:#ffffff;">
|
||||
<mj-raw>
|
||||
<?php echo $item['subject']; ?> </mj-raw>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="" style="vertical-align:top;width:150px;"
|
||||
>
|
||||
<![endif]-->
|
||||
<div class="mj-column-per-15 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
|
||||
<tr>
|
||||
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Open Sans, sans-serif;font-size:13px;line-height:1;text-align:center;color:#ffffff;">
|
||||
<mj-raw>
|
||||
<?php echo $item['message_date']; ?> </mj-raw>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="" style="vertical-align:top;width:130px;"
|
||||
>
|
||||
<![endif]-->
|
||||
<div class="mj-column-per-13 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
|
||||
<tr>
|
||||
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Open Sans, sans-serif;font-size:13px;line-height:1;text-align:center;color:#ffffff;">
|
||||
<?php echo $item['reported']; ?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
<![endif]-->
|
||||
<?php endforeach ?>
|
||||
<?php endif ?>
|
||||
<!--[if mso | IE]>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<![endif]-->
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,395 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width"/>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<title>Simple Transactional Email</title>
|
||||
<style>
|
||||
/* -------------------------------------
|
||||
GLOBAL RESETS
|
||||
------------------------------------- */
|
||||
|
||||
/*All the styling goes here*/
|
||||
|
||||
img {
|
||||
border: none;
|
||||
-ms-interpolation-mode: bicubic;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #f6f6f6;
|
||||
font-family: sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
-ms-text-size-adjust: 100%;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: separate;
|
||||
mso-table-lspace: 0pt;
|
||||
mso-table-rspace: 0pt;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table td {
|
||||
font-family: sans-serif;
|
||||
font-size: 14px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
BODY & CONTAINER
|
||||
------------------------------------- */
|
||||
|
||||
.body {
|
||||
background-color: #f6f6f6;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */
|
||||
.container {
|
||||
display: block;
|
||||
margin: 0 auto !important;
|
||||
/* makes it centered */
|
||||
max-width: 580px;
|
||||
padding: 10px;
|
||||
width: 580px;
|
||||
}
|
||||
|
||||
/* This should also be a block element, so that it will fill 100% of the .container */
|
||||
.content {
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
max-width: 580px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
HEADER, FOOTER, MAIN
|
||||
------------------------------------- */
|
||||
.main {
|
||||
background: #ffffff;
|
||||
border-radius: 3px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
box-sizing: border-box;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.content-block {
|
||||
padding-bottom: 10px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
clear: both;
|
||||
margin-top: 10px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.footer td,
|
||||
.footer p,
|
||||
.footer span,
|
||||
.footer a {
|
||||
color: #999999;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
TYPOGRAPHY
|
||||
------------------------------------- */
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4 {
|
||||
color: #000000;
|
||||
font-family: sans-serif;
|
||||
font-weight: 400;
|
||||
line-height: 1.4;
|
||||
margin: 0;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 35px;
|
||||
font-weight: 300;
|
||||
text-align: center;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
p,
|
||||
ul,
|
||||
ol {
|
||||
font-family: sans-serif;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
p li,
|
||||
ul li,
|
||||
ol li {
|
||||
list-style-position: inside;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #3498db;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
BUTTONS
|
||||
------------------------------------- */
|
||||
.btn {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.btn > tbody > tr > td {
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
|
||||
.btn table {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.btn table td {
|
||||
background-color: #ffffff;
|
||||
border-radius: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btn a {
|
||||
background-color: #ffffff;
|
||||
border: solid 1px #3498db;
|
||||
border-radius: 5px;
|
||||
box-sizing: border-box;
|
||||
color: #3498db;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
padding: 12px 25px;
|
||||
text-decoration: none;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.btn-primary table td {
|
||||
background-color: #3498db;
|
||||
}
|
||||
|
||||
.btn-primary a {
|
||||
background-color: #3498db;
|
||||
border-color: #3498db;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
OTHER STYLES THAT MIGHT BE USEFUL
|
||||
------------------------------------- */
|
||||
.last {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.first {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.align-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.align-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.clear {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.mt0 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.mb0 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.preheader {
|
||||
color: transparent;
|
||||
display: none;
|
||||
height: 0;
|
||||
max-height: 0;
|
||||
max-width: 0;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
mso-hide: all;
|
||||
visibility: hidden;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.powered-by a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 0;
|
||||
border-bottom: 1px solid #f6f6f6;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
RESPONSIVE AND MOBILE FRIENDLY STYLES
|
||||
------------------------------------- */
|
||||
@media only screen and (max-width: 620px) {
|
||||
table[class=body] h1 {
|
||||
font-size: 28px !important;
|
||||
margin-bottom: 10px !important;
|
||||
}
|
||||
|
||||
table[class=body] p,
|
||||
table[class=body] ul,
|
||||
table[class=body] ol,
|
||||
table[class=body] td,
|
||||
table[class=body] span,
|
||||
table[class=body] a {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
|
||||
table[class=body] .wrapper,
|
||||
table[class=body] .article {
|
||||
padding: 10px !important;
|
||||
}
|
||||
|
||||
table[class=body] .content {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
table[class=body] .container {
|
||||
padding: 0 !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
table[class=body] .main {
|
||||
border-left-width: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
border-right-width: 0 !important;
|
||||
}
|
||||
|
||||
table[class=body] .btn table {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
table[class=body] .btn a {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
table[class=body] .img-responsive {
|
||||
height: auto !important;
|
||||
max-width: 100% !important;
|
||||
width: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
PRESERVE THESE STYLES IN THE HEAD
|
||||
------------------------------------- */
|
||||
@media all {
|
||||
.ExternalClass {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ExternalClass,
|
||||
.ExternalClass p,
|
||||
.ExternalClass span,
|
||||
.ExternalClass font,
|
||||
.ExternalClass td,
|
||||
.ExternalClass div {
|
||||
line-height: 100%;
|
||||
}
|
||||
|
||||
.apple-link a {
|
||||
color: inherit !important;
|
||||
font-family: inherit !important;
|
||||
font-size: inherit !important;
|
||||
font-weight: inherit !important;
|
||||
line-height: inherit !important;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
#MessageViewBody a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
font-weight: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.btn-primary table td:hover {
|
||||
background-color: #34495e !important;
|
||||
}
|
||||
|
||||
.btn-primary a:hover {
|
||||
background-color: #34495e !important;
|
||||
border-color: #34495e !important;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body class="">
|
||||
<span class="preheader">Email lists for customer journey emails weekly report <?= $short_date ?? '' ?></span>
|
||||
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="body">
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td class="container">
|
||||
<div class="content">
|
||||
|
||||
<!-- START CENTERED WHITE CONTAINER -->
|
||||
<table role="presentation" class="main">
|
||||
|
||||
<!-- START MAIN CONTENT AREA -->
|
||||
<tr>
|
||||
<td class="wrapper">
|
||||
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td>
|
||||
<p><?= $short_date ?? '' ?></p>
|
||||
<p>Hi there,</p>
|
||||
<p>Here is the weekly report of Email lists for customer journey emails</p>
|
||||
<p>Please, find the report attached.</p>
|
||||
<p>Good luck!</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- END MAIN CONTENT AREA -->
|
||||
</table>
|
||||
<!-- END CENTERED WHITE CONTAINER -->
|
||||
</div>
|
||||
</td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,395 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width"/>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<title>Simple Transactional Email</title>
|
||||
<style>
|
||||
/* -------------------------------------
|
||||
GLOBAL RESETS
|
||||
------------------------------------- */
|
||||
|
||||
/*All the styling goes here*/
|
||||
|
||||
img {
|
||||
border: none;
|
||||
-ms-interpolation-mode: bicubic;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #f6f6f6;
|
||||
font-family: sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
-ms-text-size-adjust: 100%;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: separate;
|
||||
mso-table-lspace: 0pt;
|
||||
mso-table-rspace: 0pt;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table td {
|
||||
font-family: sans-serif;
|
||||
font-size: 14px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
BODY & CONTAINER
|
||||
------------------------------------- */
|
||||
|
||||
.body {
|
||||
background-color: #f6f6f6;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */
|
||||
.container {
|
||||
display: block;
|
||||
margin: 0 auto !important;
|
||||
/* makes it centered */
|
||||
max-width: 580px;
|
||||
padding: 10px;
|
||||
width: 580px;
|
||||
}
|
||||
|
||||
/* This should also be a block element, so that it will fill 100% of the .container */
|
||||
.content {
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
max-width: 580px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
HEADER, FOOTER, MAIN
|
||||
------------------------------------- */
|
||||
.main {
|
||||
background: #ffffff;
|
||||
border-radius: 3px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
box-sizing: border-box;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.content-block {
|
||||
padding-bottom: 10px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
clear: both;
|
||||
margin-top: 10px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.footer td,
|
||||
.footer p,
|
||||
.footer span,
|
||||
.footer a {
|
||||
color: #999999;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
TYPOGRAPHY
|
||||
------------------------------------- */
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4 {
|
||||
color: #000000;
|
||||
font-family: sans-serif;
|
||||
font-weight: 400;
|
||||
line-height: 1.4;
|
||||
margin: 0;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 35px;
|
||||
font-weight: 300;
|
||||
text-align: center;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
p,
|
||||
ul,
|
||||
ol {
|
||||
font-family: sans-serif;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
p li,
|
||||
ul li,
|
||||
ol li {
|
||||
list-style-position: inside;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #3498db;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
BUTTONS
|
||||
------------------------------------- */
|
||||
.btn {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.btn > tbody > tr > td {
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
|
||||
.btn table {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.btn table td {
|
||||
background-color: #ffffff;
|
||||
border-radius: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btn a {
|
||||
background-color: #ffffff;
|
||||
border: solid 1px #3498db;
|
||||
border-radius: 5px;
|
||||
box-sizing: border-box;
|
||||
color: #3498db;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
padding: 12px 25px;
|
||||
text-decoration: none;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.btn-primary table td {
|
||||
background-color: #3498db;
|
||||
}
|
||||
|
||||
.btn-primary a {
|
||||
background-color: #3498db;
|
||||
border-color: #3498db;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
OTHER STYLES THAT MIGHT BE USEFUL
|
||||
------------------------------------- */
|
||||
.last {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.first {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.align-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.align-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.clear {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.mt0 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.mb0 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.preheader {
|
||||
color: transparent;
|
||||
display: none;
|
||||
height: 0;
|
||||
max-height: 0;
|
||||
max-width: 0;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
mso-hide: all;
|
||||
visibility: hidden;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.powered-by a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 0;
|
||||
border-bottom: 1px solid #f6f6f6;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
RESPONSIVE AND MOBILE FRIENDLY STYLES
|
||||
------------------------------------- */
|
||||
@media only screen and (max-width: 620px) {
|
||||
table[class=body] h1 {
|
||||
font-size: 28px !important;
|
||||
margin-bottom: 10px !important;
|
||||
}
|
||||
|
||||
table[class=body] p,
|
||||
table[class=body] ul,
|
||||
table[class=body] ol,
|
||||
table[class=body] td,
|
||||
table[class=body] span,
|
||||
table[class=body] a {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
|
||||
table[class=body] .wrapper,
|
||||
table[class=body] .article {
|
||||
padding: 10px !important;
|
||||
}
|
||||
|
||||
table[class=body] .content {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
table[class=body] .container {
|
||||
padding: 0 !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
table[class=body] .main {
|
||||
border-left-width: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
border-right-width: 0 !important;
|
||||
}
|
||||
|
||||
table[class=body] .btn table {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
table[class=body] .btn a {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
table[class=body] .img-responsive {
|
||||
height: auto !important;
|
||||
max-width: 100% !important;
|
||||
width: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
PRESERVE THESE STYLES IN THE HEAD
|
||||
------------------------------------- */
|
||||
@media all {
|
||||
.ExternalClass {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ExternalClass,
|
||||
.ExternalClass p,
|
||||
.ExternalClass span,
|
||||
.ExternalClass font,
|
||||
.ExternalClass td,
|
||||
.ExternalClass div {
|
||||
line-height: 100%;
|
||||
}
|
||||
|
||||
.apple-link a {
|
||||
color: inherit !important;
|
||||
font-family: inherit !important;
|
||||
font-size: inherit !important;
|
||||
font-weight: inherit !important;
|
||||
line-height: inherit !important;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
#MessageViewBody a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
font-weight: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.btn-primary table td:hover {
|
||||
background-color: #34495e !important;
|
||||
}
|
||||
|
||||
.btn-primary a:hover {
|
||||
background-color: #34495e !important;
|
||||
border-color: #34495e !important;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body class="">
|
||||
<span class="preheader">Float App sign up emails last 24 hours daily report <?= $short_date ?? '' ?></span>
|
||||
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="body">
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td class="container">
|
||||
<div class="content">
|
||||
|
||||
<!-- START CENTERED WHITE CONTAINER -->
|
||||
<table role="presentation" class="main">
|
||||
|
||||
<!-- START MAIN CONTENT AREA -->
|
||||
<tr>
|
||||
<td class="wrapper">
|
||||
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td>
|
||||
<p><?= $short_date ?? '' ?></p>
|
||||
<p>Hi there,</p>
|
||||
<p>Here is the report of Float App Sign up emails last 24 hours</p>
|
||||
<p>Please, find the report attached.</p>
|
||||
<p>Good luck!</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- END MAIN CONTENT AREA -->
|
||||
</table>
|
||||
<!-- END CENTERED WHITE CONTAINER -->
|
||||
</div>
|
||||
</td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
|
||||
// require_once( '/Users/osx/Sites/Float/adminsavvy/backend.php' );
|
||||
include '../backend.php';
|
||||
require_once('../vendor/autoload.php');
|
||||
require_once('common/Logger.php');
|
||||
|
||||
use \SendGrid\Mail\Mail;
|
||||
|
||||
/**
|
||||
* Send email Float App sign up emails last 24 hours daily report
|
||||
*/
|
||||
class EmailLast24hrsReport
|
||||
{
|
||||
|
||||
public $conn;
|
||||
public $repConn;
|
||||
|
||||
public $sendgrid_api;
|
||||
public $sender;
|
||||
public $sender_name;
|
||||
public $receivers;
|
||||
|
||||
protected $hard_limit = 550;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
global $savvyext;
|
||||
$this->conn = self::__cnn($savvyext);
|
||||
$this->repConn = self::__repCnn($savvyext);
|
||||
|
||||
$this->sendgrid_api = $savvyext->cfgReadChar('mailsend.api_key');
|
||||
$this->sender = $savvyext->cfgReadChar('mailsend.from');
|
||||
$this->sender_name = $savvyext->cfgReadChar('mailsend.name');
|
||||
$this->receivers = array(
|
||||
'jervis@float.sg' => 'Jervis',
|
||||
'tnguyen@float.sg' => 'Tri Nguyen',
|
||||
);
|
||||
}
|
||||
|
||||
private static function __cnn($savvyext)
|
||||
{
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = sprintf('host=%s port=%s dbname=%s user=%s password=%s', $db_host, $db_port, $db_name, $db_user, $db_pass);
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
return $conn;
|
||||
}
|
||||
|
||||
private static function __repCnn($savvyext)
|
||||
{
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$connstr = sprintf('host=%s port=%s dbname=%s user=%s password=%s', $db_host, $db_port, $db_name, $db_user, $db_pass);
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
return $conn;
|
||||
}
|
||||
|
||||
private function array2csv($data, $delimiter = ',', $enclosure = '"', $escape_char = "\\")
|
||||
{
|
||||
$f = fopen('php://memory', 'r+');
|
||||
foreach ($data as $item) {
|
||||
fputcsv($f, $item, $delimiter, $enclosure, $escape_char);
|
||||
}
|
||||
rewind($f);
|
||||
return stream_get_contents($f);
|
||||
}
|
||||
/**
|
||||
* Send email report via SendGrid
|
||||
* @param array $data list email fail
|
||||
* @return mixed
|
||||
*/
|
||||
protected function send($data)
|
||||
{
|
||||
$short_date = (new \DateTime())->format('Y-M-d');
|
||||
// create email layout
|
||||
ob_start();
|
||||
require_once(__DIR__ . '/email/email_lists_for_customer_journey_emails.php');
|
||||
$layout = ob_get_clean();
|
||||
// create sendgrid instance
|
||||
$sendgrid = new \SendGrid\Mail\Mail;
|
||||
$sendgrid->setFrom($this->sender, $this->sender_name);
|
||||
$sendgrid->setSubject('Email lists for customer journey emails weekly report');
|
||||
$sendgrid->addTos($this->receivers);
|
||||
$sendgrid->addContent('text/html', $layout);
|
||||
|
||||
//HEADER of csv files
|
||||
array_unshift($data,[
|
||||
'First name', 'Last name', 'Email address', 'Sync email', 'Latest account activity', 'Made trip', 'Latest trip made', 'Sync bank account', 'Latest bank activity'
|
||||
]);
|
||||
$att1 = new \SendGrid\Mail\Attachment();
|
||||
//$att1->setContent( file_get_contents("test_files/1/1.txt") );
|
||||
$att1->setContent( $this->array2csv($data) );
|
||||
$att1->setType("text/csv");
|
||||
|
||||
$att1->setFilename("email_lists_for_customer_journey_emails-weekly-report-".$short_date.".csv");
|
||||
$att1->setDisposition("attachment");
|
||||
$sendgrid->addAttachment( $att1 );
|
||||
|
||||
// send
|
||||
$send = new \SendGrid($this->sendgrid_api);
|
||||
$response = $send->send($sendgrid);
|
||||
if ($response->statusCode() !== 202) {
|
||||
throw new Exception('Send email via Sendgrid get errors!');
|
||||
}
|
||||
}
|
||||
public function getemails()
|
||||
{
|
||||
try {
|
||||
$sql = "
|
||||
SELECT id, firstname, lastname, email,
|
||||
CASE WHEN email_connected = 1 THEN 'TRUE' ELSE 'FALSE' END AS email_connected,
|
||||
updated as latest_account_activity
|
||||
FROM members
|
||||
WHERE id > 0
|
||||
ORDER BY id ASC
|
||||
LIMIT 5000 OFFSET 0";
|
||||
|
||||
$query = pg_query($this->repConn, $sql);
|
||||
|
||||
$users = pg_fetch_all($query);
|
||||
|
||||
$sql = "
|
||||
SELECT member_id, MAX(added) as latest_trip_made
|
||||
FROM members_trips
|
||||
GROUP BY member_id
|
||||
ORDER BY member_id ASC";
|
||||
|
||||
$query = pg_query($this->repConn, $sql);
|
||||
|
||||
$usersMadeTrip = pg_fetch_all($query);
|
||||
|
||||
$sql = "
|
||||
SELECT member_id, MAX(added) as latest_bank_activity
|
||||
FROM members_bank_accounts
|
||||
WHERE bank_login_status = 'active'
|
||||
GROUP BY member_id
|
||||
ORDER BY member_id ASC";
|
||||
|
||||
$query = pg_query($this->repConn, $sql);
|
||||
|
||||
$usersSyncBank = pg_fetch_all($query);
|
||||
|
||||
if ($error = pg_last_error($this->repConn)) {
|
||||
throw new Exception($error);
|
||||
}
|
||||
|
||||
foreach ($users as &$user) {
|
||||
foreach ($usersMadeTrip as $tempUser) {
|
||||
if ($tempUser['member_id'] == $user['id']) {
|
||||
$user['made_trip'] = 'TRUE';
|
||||
$user['latest_trip_made'] = $tempUser['latest_trip_made'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($usersSyncBank as $tempUser) {
|
||||
if ($tempUser['member_id'] == $user['id']) {
|
||||
$user['sync_bank'] = 'TRUE';
|
||||
$user['latest_bank_activity'] = $tempUser['latest_bank_activity'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($user['made_trip'])) {
|
||||
$user['made_trip'] = 'FALSE';
|
||||
$user['latest_trip_made'] = '';
|
||||
}
|
||||
|
||||
if (!isset($user['sync_bank'])) {
|
||||
$user['sync_bank'] = 'FALSE';
|
||||
$user['latest_bank_activity'] = '';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
foreach ($users as &$user) {
|
||||
array_shift($user);
|
||||
}
|
||||
|
||||
return $users;
|
||||
|
||||
} catch (Exception $e) {
|
||||
Logger::debug($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Excute jobs
|
||||
* @return mixed
|
||||
*/
|
||||
public function excute()
|
||||
{
|
||||
try {
|
||||
$data = $this->getemails();
|
||||
$send = $this->send($data);
|
||||
} catch (Exception $e) {
|
||||
Logger::debug($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$instace = new EmailLast24hrsReport;
|
||||
$instace->excute();
|
||||
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] GPS geocode_address job is starting.\n";
|
||||
exit();
|
||||
require('../backend.php');
|
||||
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
|
||||
|
||||
$q = "SELECT * FROM address WHERE geocoding_date IS NULL OR country IS NULL";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
if ($f["address"]=="") continue;
|
||||
$q0 = "SELECT * FROM address WHERE lower(address)=lower('".pg_escape_string($f["address"])."') AND id<>".$f["id"];
|
||||
$q0.= " AND latitude!=0 AND longitude!=0 AND geocoding_date IS NOT NULL ORDER BY geocoding_date DESC LIMIT 1";
|
||||
$r0 = pg_query($readOnlyReplicaConn, $q0);
|
||||
if ($r0 && pg_num_rows($r0) && $f0=pg_fetch_assoc($r0) && $f0["country"]!="") {
|
||||
echo "[".date("Y-m-d H:i:s")."] Already geocoded: ".$f["id"]." => ".$f0["id"].".\n";
|
||||
unset($f0["id"]);
|
||||
list($res,$err) = updateAddress($f["id"], $f0);
|
||||
if ($err && $err!="") {
|
||||
echo "[".date("Y-m-d H:i:s")."] Failure: ${err} (".$f["id"].")\n";
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Complete: ".$f["id"]."\n";
|
||||
}
|
||||
} else {
|
||||
// Geocode
|
||||
list($res,$err) = geocodeAddress($f["address"]);
|
||||
if ($res && $err==NULL) {
|
||||
if (array_key_exists("lat",$res) && array_key_exists("lng",$res)) {
|
||||
$tz = $res["timeZoneId"];
|
||||
if ($tz=="" || !is_int($tz)) {
|
||||
$q1 = "SELECT id FROM address_timezone WHERE lower(timezone)=lower('".pg_escape_string($tz)."')";
|
||||
$r1 = pg_query($readOnlyReplicaConn, $q1);
|
||||
if ($r1 && pg_num_rows($r1) && $f1=pg_fetch_row($r1)) {
|
||||
$tz = $f1[0];
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Invalid timezone: '${tz}' (".$f["id"].")\n";
|
||||
$tz = 1;
|
||||
}
|
||||
}
|
||||
$data = [
|
||||
"latitude" => $res["lat"],
|
||||
"longitude" => $res["lng"],
|
||||
/*"address" => $res["address"],*/
|
||||
"postal" => $res["postal"],
|
||||
"country" => $res["country"],
|
||||
"timezone" => $tz,
|
||||
"geocoding_date" => date("Y-m-d"),
|
||||
"geometry" => "ST_SetSRID(ST_MakePoint(".$res["lng"].",".$res["lat"]."), 4326)"
|
||||
];
|
||||
list($res,$err) = updateAddress($f["id"], $data);
|
||||
if ($err && $err!="") {
|
||||
echo "[".date("Y-m-d H:i:s")."] Failure: ${err} (".$f["id"].")\n";
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Complete: ".$f["id"]."\n";
|
||||
}
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Invalid result: ".json_encode($res)." (".$f["id"].")\n";
|
||||
}
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Failure: ${err} (".$f["id"].")\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateAddress($id, $data) {
|
||||
global $conn, $readOnlyReplicaConn;
|
||||
$columns = [];
|
||||
$q = "select column_name, data_type, character_maximum_length from INFORMATION_SCHEMA.COLUMNS where table_name = 'address'";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
$columns[$f['column_name']] = $f['data_type'];
|
||||
}
|
||||
$q = "UPDATE address SET id=${id}";
|
||||
foreach ($data as $key=>$val) {
|
||||
if ($key=="id") continue;
|
||||
if (array_key_exists($key,$columns) && $columns[$key]!='character varying' && $columns[$key]!='date') {
|
||||
$q.= ", ${key} = ".($val==""?"NULL":$val);
|
||||
} else {
|
||||
$q.= ", ${key} = '".pg_escape_string($val)."'";
|
||||
}
|
||||
}
|
||||
$q.= " WHERE id=${id} RETURNING *";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) {
|
||||
return [$f, NULL];
|
||||
}
|
||||
return [NULL, pg_last_error($conn)];
|
||||
}
|
||||
|
||||
function geocodeAddress($address) {
|
||||
global $httpAuthToken;
|
||||
// Call geocoding service
|
||||
$data = http_build_query(
|
||||
array(
|
||||
'address' => $address,
|
||||
)
|
||||
);
|
||||
$url = "http://oauth2.service/api/v1/geocode?" . $data;
|
||||
$opts = array(
|
||||
'http' => array(
|
||||
'method' => "GET",
|
||||
'timeout' => 60, /* 1 minute */
|
||||
'header' =>
|
||||
"Content-Type: application/x-www-form-urlencoded\r\n" .
|
||||
"Accept: application/json\r\n" .
|
||||
"Authorization: Server-Token ${httpAuthToken}\r\n",
|
||||
)
|
||||
);
|
||||
$context = stream_context_create($opts);
|
||||
$body = file_get_contents($url, false, $context);
|
||||
$geocoded = json_decode($body,true);
|
||||
if (is_array($geocoded) && is_array($geocoded["data"]) && !isset($geocoded["error"])) {
|
||||
// Cache the result in DB
|
||||
return array($geocoded["data"], NULL);
|
||||
} else if (is_array($geocoded) && isset($geocoded["error"])) {
|
||||
$body = $geocoded["error"];
|
||||
}
|
||||
return array(NULL, "Geocoding service call error: ".$body);
|
||||
}
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] GPS geocode_address job complete.\n";
|
||||
@@ -0,0 +1,179 @@
|
||||
<?php
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] GPS geocode_fix_address job is starting.\n";
|
||||
|
||||
require 'common/utils.php';
|
||||
require 'common/config.php';
|
||||
require 'common/address_city.php';
|
||||
require 'common/Geocode.php';
|
||||
|
||||
$tables = getForeignTables('address');
|
||||
|
||||
$address_conditions = [
|
||||
"POSITION('Your driver' in address)>0",
|
||||
];
|
||||
foreach ($address_conditions as $condition) {
|
||||
$r = getAddressesByCondition($condition);
|
||||
while ($fa = pg_fetch_assoc($r)) {
|
||||
$address_id = $fa['id'];
|
||||
$address = $fa['address'];
|
||||
echo $address;
|
||||
$pos_driver = strpos(strtolower($address),'your driver');
|
||||
if($pos_driver!=false){
|
||||
$address = substr($address,0, $pos_driver);
|
||||
}
|
||||
$update_address = [
|
||||
'address' => $address
|
||||
];
|
||||
updateDataTable('address', 'id=' . $address_id, $update_address);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$duplicates = getDuplicatedAddresses();
|
||||
|
||||
|
||||
while ($f = pg_fetch_assoc($duplicates)) {
|
||||
$latitude = $f['latitude'];
|
||||
$longitude = $f['longitude'];
|
||||
$condition = 'latitude = ' . $latitude . ' AND longitude=' . $longitude;
|
||||
$addresses = getAddressesByCondition($condition);
|
||||
$ids = [];
|
||||
while ($fa = pg_fetch_assoc($addresses)) {
|
||||
$ids[] = $fa['id'];
|
||||
}
|
||||
$id_keep = array_shift($ids);
|
||||
if (count($ids) > 0) {
|
||||
$sql = '';
|
||||
foreach($ids as $foreign_id){
|
||||
foreach ($tables as $ft) {
|
||||
$table_name = $ft['table_name'];
|
||||
$field = $ft['column_name'];
|
||||
if ($table_name == 'tourist_attraction') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data_update = [
|
||||
$field => $id_keep,
|
||||
];
|
||||
$condition_update_foreigns = "{$field} = " . $foreign_id;
|
||||
updateDataTable($table_name, $condition_update_foreigns, $data_update);
|
||||
}
|
||||
deleteDataTable('tourist_attraction', ' address_id =' . $foreign_id);
|
||||
deleteDataTable('address', ' id =' . $foreign_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
$empty_time_zones = getAddressEmptyTimezone();
|
||||
while ($fe = pg_fetch_assoc($empty_time_zones)) {
|
||||
$address_id = $fe['id'];
|
||||
$address = $fe['address'];
|
||||
$timezone_id = $fe['timezone_id'];
|
||||
$geoinfo = Geocode::geocodeAddress($address);
|
||||
if (isset($geoinfo) && is_array($geoinfo)) {
|
||||
$postal = $geoinfo['postal'];
|
||||
$timezoneID = getTimeZoneID($geoinfo['timeZoneId']);
|
||||
$update_address = [
|
||||
'timezone' => $timezoneID
|
||||
];
|
||||
updateDataTable('address', 'id=' . $address_id, $update_address);
|
||||
if ($timezoneID == $timezone_id) {
|
||||
$timezoneName = $geoinfo['timeZoneId'];
|
||||
$update_address_timezone = [
|
||||
'timezone' => $timezoneName,
|
||||
];
|
||||
updateDataTable('address_timezone', 'id=' . $timezone_id, $update_address_timezone);
|
||||
}
|
||||
}
|
||||
}
|
||||
//get invalid address by condition
|
||||
$address_conditions = [
|
||||
#"address NOT ILIKE '%singap%' and country='SG'",
|
||||
];
|
||||
foreach ($address_conditions as $condition) {
|
||||
$r = getAddressesByCondition($condition);
|
||||
while ($fa = pg_fetch_assoc($r)) {
|
||||
$address_id = $fa['id'];
|
||||
$address = $fa['address'];
|
||||
$latitude = $fa['latitude'];
|
||||
$longitude = $fa['longitude'];
|
||||
$geoinfo = Geocode::reverseGPS($latitude,$longitude);
|
||||
|
||||
if (isset($geoinfo) && is_array($geoinfo)) {
|
||||
$postal = $geoinfo['postal'];
|
||||
$timezone = getTimeZoneID($geoinfo['timeZoneId']);
|
||||
$country = $geoinfo['country'];
|
||||
$update_address = [
|
||||
'postal' => $postal,
|
||||
'timezone' => $timezone,
|
||||
'country' => $country
|
||||
];
|
||||
updateDataTable('address', 'id=' . $address_id, $update_address);
|
||||
}
|
||||
}
|
||||
}
|
||||
//invalid postal
|
||||
$address_conditions = [
|
||||
#"postal<>'Singapore' and left(postal,1)<>'0' and left(postal,1)<>'1' and left(postal,1)<>'2' and left(postal,1)<>'3' and left(postal,1)<>'4' and left(postal,1)<>'5' and left(postal,1)<>'6' and left(postal,1)<>'7' and left(postal,1)<>'8' and left(postal,1)<>'9' and country<>'GB' and country<>'CA' and country<>'IE'",
|
||||
#"postal is NULL or postal=''"
|
||||
];
|
||||
foreach ($address_conditions as $condition) {
|
||||
$r = getAddressesByCondition($condition);
|
||||
while ($fa = pg_fetch_assoc($r)) {
|
||||
$address_id = $fa['id'];
|
||||
$address = $fa['address'];
|
||||
$latitude = $fa['latitude'];
|
||||
$longitude = $fa['longitude'];
|
||||
$geoinfo = Geocode::reverseGPS($latitude,$longitude);
|
||||
|
||||
if (isset($geoinfo) && is_array($geoinfo)) {
|
||||
$postal = $geoinfo['postal'];
|
||||
$country = isset($geoinfo['country'])?$geoinfo['country']:$fa['country'];
|
||||
if(empty($postal)){
|
||||
$postal = getPostalCode($latitude,$longitude,$country);
|
||||
}
|
||||
$timezone = getTimeZoneID($geoinfo['timeZoneId']);
|
||||
$update_address = [
|
||||
'postal' => $postal,
|
||||
'timezone' => $timezone,
|
||||
'country' => $country
|
||||
];
|
||||
updateDataTable('address', 'id=' . $address_id, $update_address);
|
||||
}
|
||||
}
|
||||
}
|
||||
echo "[" . date("Y-m-d H:i:s") . "] GPS geocode_fix_address job complete.\n";
|
||||
|
||||
function getDuplicatedAddresses()
|
||||
{
|
||||
global $readOnlyReplicaConn;
|
||||
$q = "SELECT latitude, longitude, count(*)
|
||||
FROM address
|
||||
GROUP BY latitude, longitude
|
||||
HAVING count(*) >1
|
||||
ORDER BY count(*) DESC";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
return $r;
|
||||
}
|
||||
|
||||
function getAddressEmptyTimezone()
|
||||
{
|
||||
global $readOnlyReplicaConn;
|
||||
$q = "SELECT a.id, a.address, a.latitude, a.longitude, b.id as timezone_id
|
||||
FROM address a
|
||||
LEFT JOIN address_timezone b ON a.timezone=b.id
|
||||
WHERE b.timezone ='' OR b.timezone IS NULL";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
return $r;
|
||||
}
|
||||
|
||||
function getAddressesByCondition($condition)
|
||||
{
|
||||
global $readOnlyReplicaConn;
|
||||
$q = "SELECT *
|
||||
FROM address
|
||||
WHERE " . $condition;
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
return $r;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] GPS geocode_fix_address job is starting.\n";
|
||||
|
||||
require 'common/utils.php';
|
||||
require 'common/config.php';
|
||||
require 'common/address_city.php';
|
||||
require 'common/Geocode.php';
|
||||
|
||||
$conditions = [
|
||||
"address ilike '%123 Yishun Street 11, Singapore%'",
|
||||
];
|
||||
$tables = getForeignTables('address');
|
||||
foreach ($conditions as $condition) {
|
||||
|
||||
$addresses = getAddressesByCondition($condition);
|
||||
$ids = [];
|
||||
while ($fa = pg_fetch_assoc($addresses)) {
|
||||
$ids[] = $fa['id'];
|
||||
}
|
||||
$id_keep = array_shift($ids);
|
||||
if (count($ids) > 0) {
|
||||
$sql = '';
|
||||
foreach ($tables as $ft) {
|
||||
$table_name = $ft['table_name'];
|
||||
$field = $ft['column_name'];
|
||||
if ($table_name == 'tourist_attraction') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data_update = [
|
||||
$field => $id_keep,
|
||||
];
|
||||
$condition_update_foreigns = "{$field} IN (" . implode(",", $ids) . ")";
|
||||
updateDataTable($table_name, $condition_update_foreigns, $data_update);
|
||||
}
|
||||
deleteDataTable('tourist_attraction', ' address_id IN(' . implode(",", $ids) . ')');
|
||||
deleteDataTable('address', ' id IN(' . implode(",", $ids) . ')');
|
||||
}
|
||||
}
|
||||
echo "[" . date("Y-m-d H:i:s") . "] GPS geocode_fix_address job complete.\n";
|
||||
|
||||
function getAddressesByCondition($condition)
|
||||
{
|
||||
global $readOnlyReplicaConn;
|
||||
$q = "SELECT *
|
||||
FROM address
|
||||
WHERE " . $condition."
|
||||
ORDER BY id desc";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
return $r;
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
<?php
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] GPS geocode_address job is starting.\n";
|
||||
|
||||
require('../backend.php');
|
||||
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
|
||||
$q = "SELECT * FROM address WHERE country='SG' AND (LOWER(postal)='singapore' ";
|
||||
$q.= " OR (postal='' AND address ILIKE '%singapore'))";
|
||||
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
if ($f["address"]=="") continue;
|
||||
$q0 = "SELECT * FROM address WHERE lower(address)=lower('".pg_escape_string($f["address"])."') AND id<>".$f["id"];
|
||||
$q0.= " AND postal<>'' AND LOWER(postal)<>'singapore' ORDER BY geocoding_date DESC LIMIT 1";
|
||||
$r0 = pg_query($readOnlyReplicaConn, $q0);
|
||||
if ($r0 && pg_num_rows($r0) && $f0=pg_fetch_assoc($r0) && $f0["country"]!="") {
|
||||
echo "[".date("Y-m-d H:i:s")."] Already geocoded: ".$f["id"]." => ".$f0["id"].".\n";
|
||||
unset($f0["id"]);
|
||||
list($res,$err) = updateAddress($f["id"], $f0);
|
||||
if ($err && $err!="") {
|
||||
echo "[".date("Y-m-d H:i:s")."] Failure: ${err} (".$f["id"].")\n";
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Complete: ".$f["id"]."\n";
|
||||
}
|
||||
} else {
|
||||
// Geocode
|
||||
list($res,$err) = geocodeAddress($f["address"]);
|
||||
if ($res && $err==NULL) {
|
||||
if (array_key_exists("lat",$res) && array_key_exists("lng",$res)) {
|
||||
$tz = $res["timeZoneId"];
|
||||
if ($tz=="" || !is_int($tz)) {
|
||||
$q1 = "SELECT id FROM address_timezone WHERE lower(timezone)=lower('".pg_escape_string($tz)."')";
|
||||
$r1 = pg_query($readOnlyReplicaConn, $q1);
|
||||
if ($r1 && pg_num_rows($r1) && $f1=pg_fetch_row($r1)) {
|
||||
$tz = $f1[0];
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Invalid timezone: '${tz}' (".$f["id"].")\n";
|
||||
$tz = 1;
|
||||
}
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Timezone is OK: tz=${tz}\n";
|
||||
}
|
||||
if ($res["postal"]==="" || $res["postal"]=='Singapore') {
|
||||
list($res1,$err1) = geocodeReverse($res["lat"],$res["lng"]);
|
||||
$res["postal"] = $res1["postal"];
|
||||
}
|
||||
echo "[".date("Y-m-d H:i:s")."] postal=".$res["postal"]."\n";
|
||||
$data = [
|
||||
"latitude" => $res["lat"],
|
||||
"longitude" => $res["lng"],
|
||||
/*"address" => $res["address"],*/
|
||||
"postal" => $res["postal"],
|
||||
"country" => $res["country"],
|
||||
"timezone" => $tz,
|
||||
"geocoding_date" => date("Y-m-d"),
|
||||
"geometry" => "ST_SetSRID(ST_MakePoint(".$res["lng"].",".$res["lat"]."), 4326)"
|
||||
];
|
||||
//var_dump($data);
|
||||
list($res,$err) = updateAddress($f["id"], $data);
|
||||
if ($err && $err!="") {
|
||||
echo "[".date("Y-m-d H:i:s")."] Failure: ${err} (".$f["id"].")\n";
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Complete: ".$f["id"]."\n";
|
||||
}
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Invalid result: ".json_encode($res)." (".$f["id"].")\n";
|
||||
}
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Failure: ${err} (".$f["id"].")\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateAddress($id, $data) {
|
||||
global $conn, $readOnlyReplicaConn;
|
||||
$columns = [];
|
||||
$q = "select column_name, data_type, character_maximum_length from INFORMATION_SCHEMA.COLUMNS where table_name = 'address'";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
$columns[$f['column_name']] = $f['data_type'];
|
||||
}
|
||||
$q = "UPDATE address SET id=${id}";
|
||||
foreach ($data as $key=>$val) {
|
||||
if ($key!="postal") continue;
|
||||
if (array_key_exists($key,$columns) && $columns[$key]!='character varying' && $columns[$key]!='date') {
|
||||
$q.= ", ${key} = ".($val==""?"NULL":$val);
|
||||
} else {
|
||||
$q.= ", ${key} = '".pg_escape_string($val)."'";
|
||||
}
|
||||
}
|
||||
$q.= " WHERE id=${id} RETURNING *";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) {
|
||||
return [$f, NULL];
|
||||
}
|
||||
return [NULL, pg_last_error($conn)];
|
||||
}
|
||||
|
||||
function geocodeAddress($address) {
|
||||
global $httpAuthToken;
|
||||
// Call geocoding service
|
||||
$data = http_build_query(
|
||||
array(
|
||||
'address' => $address,
|
||||
)
|
||||
);
|
||||
$url = "http://oauth2.service/api/v1/geocode?" . $data;
|
||||
$opts = array(
|
||||
'http' => array(
|
||||
'method' => "GET",
|
||||
'timeout' => 60, /* 1 minute */
|
||||
'header' =>
|
||||
"Content-Type: application/x-www-form-urlencoded\r\n" .
|
||||
"Accept: application/json\r\n" .
|
||||
"Authorization: Server-Token ${httpAuthToken}\r\n",
|
||||
)
|
||||
);
|
||||
$context = stream_context_create($opts);
|
||||
$body = file_get_contents($url, false, $context);
|
||||
$geocoded = json_decode($body,true);
|
||||
if (is_array($geocoded) && is_array($geocoded["data"]) && !isset($geocoded["error"])) {
|
||||
// Cache the result in DB
|
||||
return array($geocoded["data"], NULL);
|
||||
} else if (is_array($geocoded) && isset($geocoded["error"])) {
|
||||
$body = $geocoded["error"];
|
||||
}
|
||||
return array(NULL, "Geocoding service call error: ".$body);
|
||||
}
|
||||
|
||||
function geocodeReverse($latitude,$longitude) {
|
||||
global $httpAuthToken;
|
||||
// Call geocoding service
|
||||
$url = "http://oauth2.service/api/v1/reverse/" . $latitude . ',' . $longitude;
|
||||
$opts = array(
|
||||
'http' => array(
|
||||
'method' => "GET",
|
||||
'timeout' => 60, /* 1 minute */
|
||||
'header' =>
|
||||
"Content-Type: application/x-www-form-urlencoded\r\n" .
|
||||
"Accept: application/json\r\n" .
|
||||
"Authorization: Server-Token ${httpAuthToken}\r\n",
|
||||
)
|
||||
);
|
||||
$context = stream_context_create($opts);
|
||||
$body = file_get_contents($url, false, $context);
|
||||
$geocoded = json_decode($body,true);
|
||||
if (is_array($geocoded) && is_array($geocoded["data"]) && !isset($geocoded["error"])) {
|
||||
// Cache the result in DB
|
||||
return array($geocoded["data"], NULL);
|
||||
} else if (is_array($geocoded) && isset($geocoded["error"])) {
|
||||
$body = $geocoded["error"];
|
||||
}
|
||||
return array(NULL, "Geocoding service call error: ".$body);
|
||||
}
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] GPS geocode_address job complete.\n";
|
||||
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] GPS geocode_address job is starting.\n";
|
||||
|
||||
require('../backend.php');
|
||||
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
|
||||
|
||||
$q = "SELECT * FROM address WHERE timezone IS NULL OR timezone<1";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
if ($f["address"]=="") continue;
|
||||
$q0 = "SELECT * FROM address WHERE lower(address)=lower('".pg_escape_string($f["address"])."') AND id<>".$f["id"];
|
||||
$q0.= " AND timezone>0 ORDER BY geocoding_date DESC LIMIT 1";
|
||||
$r0 = pg_query($readOnlyReplicaConn, $q0);
|
||||
if ($r0 && pg_num_rows($r0) && $f0=pg_fetch_assoc($r0) && $f0["country"]!="") {
|
||||
echo "[".date("Y-m-d H:i:s")."] Already geocoded: ".$f["id"]." => ".$f0["id"].".\n";
|
||||
unset($f0["id"]);
|
||||
list($res,$err) = updateAddress($f["id"], $f0);
|
||||
if ($err && $err!="") {
|
||||
echo "[".date("Y-m-d H:i:s")."] Failure: ${err} (".$f["id"].")\n";
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Complete: ".$f["id"]."\n";
|
||||
}
|
||||
} else {
|
||||
// Geocode
|
||||
list($res,$err) = geocodeAddress($f["address"]);
|
||||
if ($res && $err==NULL) {
|
||||
if (array_key_exists("lat",$res) && array_key_exists("lng",$res)) {
|
||||
$tz = $res["timeZoneId"];
|
||||
if ($tz=="" || !is_int($tz)) {
|
||||
$q1 = "SELECT id FROM address_timezone WHERE lower(timezone)=lower('".pg_escape_string($tz)."')";
|
||||
$r1 = pg_query($readOnlyReplicaConn, $q1);
|
||||
if ($r1 && pg_num_rows($r1) && $f1=pg_fetch_row($r1)) {
|
||||
$tz = $f1[0];
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Invalid timezone: '${tz}' (".$f["id"].")\n";
|
||||
$tz = 1;
|
||||
}
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Timezone is OK: tz=${tz}\n";
|
||||
}
|
||||
echo "[".date("Y-m-d H:i:s")."] tz=${tz}\n";
|
||||
$data = [
|
||||
"latitude" => $res["lat"],
|
||||
"longitude" => $res["lng"],
|
||||
/*"address" => $res["address"],*/
|
||||
"postal" => $res["postal"],
|
||||
"country" => $res["country"],
|
||||
"timezone" => $tz,
|
||||
"geocoding_date" => date("Y-m-d"),
|
||||
"geometry" => "ST_SetSRID(ST_MakePoint(".$res["lng"].",".$res["lat"]."), 4326)"
|
||||
];
|
||||
list($res,$err) = updateAddress($f["id"], $data);
|
||||
if ($err && $err!="") {
|
||||
echo "[".date("Y-m-d H:i:s")."] Failure: ${err} (".$f["id"].")\n";
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Complete: ".$f["id"]."\n";
|
||||
}
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Invalid result: ".json_encode($res)." (".$f["id"].")\n";
|
||||
}
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Failure: ${err} (".$f["id"].")\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateAddress($id, $data) {
|
||||
global $conn, $readOnlyReplicaConn;
|
||||
$columns = [];
|
||||
$q = "select column_name, data_type, character_maximum_length from INFORMATION_SCHEMA.COLUMNS where table_name = 'address'";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
$columns[$f['column_name']] = $f['data_type'];
|
||||
}
|
||||
$q = "UPDATE address SET id=${id}";
|
||||
foreach ($data as $key=>$val) {
|
||||
if ($key!="timezone") continue;
|
||||
if (array_key_exists($key,$columns) && $columns[$key]!='character varying' && $columns[$key]!='date') {
|
||||
$q.= ", ${key} = ".($val==""?"NULL":$val);
|
||||
} else {
|
||||
$q.= ", ${key} = '".pg_escape_string($val)."'";
|
||||
}
|
||||
}
|
||||
$q.= " WHERE id=${id} RETURNING *";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) {
|
||||
return [$f, NULL];
|
||||
}
|
||||
return [NULL, pg_last_error($conn)];
|
||||
}
|
||||
|
||||
function geocodeAddress($address) {
|
||||
global $httpAuthToken;
|
||||
// Call geocoding service
|
||||
$data = http_build_query(
|
||||
array(
|
||||
'address' => $address,
|
||||
)
|
||||
);
|
||||
$url = "http://oauth2.service/api/v1/geocode?" . $data;
|
||||
$opts = array(
|
||||
'http' => array(
|
||||
'method' => "GET",
|
||||
'timeout' => 60, /* 1 minute */
|
||||
'header' =>
|
||||
"Content-Type: application/x-www-form-urlencoded\r\n" .
|
||||
"Accept: application/json\r\n" .
|
||||
"Authorization: Server-Token ${httpAuthToken}\r\n",
|
||||
)
|
||||
);
|
||||
$context = stream_context_create($opts);
|
||||
$body = file_get_contents($url, false, $context);
|
||||
$geocoded = json_decode($body,true);
|
||||
if (is_array($geocoded) && is_array($geocoded["data"]) && !isset($geocoded["error"])) {
|
||||
// Cache the result in DB
|
||||
return array($geocoded["data"], NULL);
|
||||
} else if (is_array($geocoded) && isset($geocoded["error"])) {
|
||||
$body = $geocoded["error"];
|
||||
}
|
||||
return array(NULL, "Geocoding service call error: ".$body);
|
||||
}
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] GPS geocode_address job complete.\n";
|
||||
@@ -0,0 +1,17 @@
|
||||
-- common
|
||||
UPDATE address SET timezone=8 WHERE timezone IS NULL AND country='FR';
|
||||
UPDATE address SET timezone=21 WHERE timezone IS NULL AND country='TH';
|
||||
UPDATE address SET timezone=24 WHERE timezone IS NULL AND country='UA';
|
||||
UPDATE address SET timezone=28 WHERE timezone IS NULL AND country='PL';
|
||||
UPDATE address SET timezone=29 WHERE timezone IS NULL AND country='RO';
|
||||
UPDATE address SET timezone=34 WHERE timezone IS NULL AND country='DE';
|
||||
UPDATE address SET timezone=39 WHERE timezone IS NULL AND country='TW';
|
||||
-- development
|
||||
UPDATE address SET timezone=289 WHERE timezone IS NULL AND country='VN';
|
||||
UPDATE address SET timezone=301 WHERE timezone IS NULL AND country='IN';
|
||||
UPDATE address SET timezone=476 WHERE timezone IS NULL AND country='TR';
|
||||
-- production
|
||||
UPDATE address SET timezone=300 WHERE timezone IS NULL AND country='VN';
|
||||
UPDATE address SET timezone=312 WHERE timezone IS NULL AND country='IN';
|
||||
UPDATE address SET timezone=487 WHERE timezone IS NULL AND country='TR';
|
||||
|
||||
@@ -0,0 +1,341 @@
|
||||
<?php
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] geofence_area_average_quotes job is starting.\n";
|
||||
|
||||
require('./lock.php');
|
||||
$lock_file = lock_pid_file();
|
||||
|
||||
require('../backend.php');
|
||||
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$con = pg_connect($connstr);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
|
||||
|
||||
if ($con===FALSE || $readOnlyReplicaConn===FALSE) {
|
||||
unlock_pid_file($lock_file);
|
||||
die ("Could not connect to server\n");
|
||||
}
|
||||
$rate = 1.1;
|
||||
$numberOfDays = 365; // This is handled by update cheapest data job now...
|
||||
|
||||
$city_id = 1;
|
||||
$tz = 'Asia/Singapore';
|
||||
$transport_providers = [3, 4, 5];
|
||||
$min_distance = 0.1; //0.1km
|
||||
$min_rate = 0.2; //20 cents
|
||||
|
||||
// Load max IDs
|
||||
$q = "SELECT max(id) FROM parsedemail_item WHERE base_cost>0 AND dup_id IS NULL AND private='f' AND booking='f' AND transport_provider_id IS NOT NULL";
|
||||
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) {
|
||||
$max_parsedemail_item_id = $f[0];
|
||||
}
|
||||
|
||||
$q = "SELECT max(id) FROM quotes WHERE cost>0";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) {
|
||||
$max_quote_id = $f[0];
|
||||
}
|
||||
|
||||
// Load areas
|
||||
$areas = [];
|
||||
$q = "SELECT * FROM geofence_area WHERE city_id=${city_id}";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
$areas[$f["id"]] = $f;
|
||||
}
|
||||
}
|
||||
|
||||
// Load previous data
|
||||
$average_quotes = [];
|
||||
foreach ($areas as $f) {
|
||||
$average_quotes[$f["id"]] = load_average_quotes_for_area($f,$areas,$transport_providers);
|
||||
}
|
||||
|
||||
// Start processing
|
||||
foreach ($average_quotes as $area_id=>$average_quote) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Processing area ID #${area_id}\n";
|
||||
process_area_average_quotes($average_quote,$areas,$area_id, $min_distance,$min_rate);
|
||||
}
|
||||
|
||||
/*********************************** Function ***********************************/
|
||||
|
||||
function load_average_quotes_for_area($area,$areas,$transport_providers) {
|
||||
global $con, $readOnlyReplicaConn;
|
||||
$average_quotes = [];
|
||||
// Pre-fill the initial data
|
||||
for ($i=0;$i<24;$i++) {
|
||||
foreach ($areas as $item) {
|
||||
foreach ($transport_providers as $transport_provider_id) {
|
||||
// unique(area_start_id,area_end_id,transport_provider_id,hour)
|
||||
$key = $area["id"]."_".$item["id"];
|
||||
if (!array_key_exists($key,$average_quotes)) {
|
||||
$average_quotes[$key] = []; // initialize
|
||||
}
|
||||
if (!array_key_exists($transport_provider_id,$average_quotes[$key])) {
|
||||
$average_quotes[$key][$transport_provider_id] = [];
|
||||
}
|
||||
$average_quotes[$key][$transport_provider_id][$i] = [
|
||||
"id" => 0,
|
||||
"area_start_id" => $area["id"],
|
||||
"area_end_id" => $item["id"],
|
||||
"transport_provider_id" => $transport_provider_id,
|
||||
"average_cost" => 0,
|
||||
"average_total" => 0,
|
||||
"average_count" => 0,
|
||||
"hour" => $i,
|
||||
/* "last_updated" => NULL, */
|
||||
"last_quotes_id" => 0,
|
||||
"last_parsedemail_item_id" => 0
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
// Load the existing data from the DB
|
||||
$q = "SELECT * FROM geofence_area_average_quotes WHERE area_start_id=".$area["id"];
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
// unique(area_start_id,area_end_id,transport_provider_id,hour)
|
||||
$key = $f["area_start_id"]."_".$f["area_end_id"];
|
||||
if (!array_key_exists($key,$average_quotes)) {
|
||||
$average_quotes[$key] = [];
|
||||
}
|
||||
if (!array_key_exists($f["transport_provider_id"],$average_quotes[$key])) {
|
||||
$average_quotes[$key][$f["transport_provider_id"]] = [];
|
||||
}
|
||||
$average_quotes[$key][$f["transport_provider_id"]][$f["hour"]] = $f;
|
||||
}
|
||||
}
|
||||
return $average_quotes;
|
||||
}
|
||||
|
||||
function process_area_average_quotes($average_quote,$areas,$area_id,$min_distance=0.1,$min_rate=0.2) {
|
||||
global $con, $readOnlyReplicaConn, $max_parsedemail_item_id, $max_quote_id, $numberOfDays, $tz, $transport_providers;
|
||||
// $average_quote[$key][$transport_provider_id][$hour]
|
||||
foreach ($average_quote as $key=>$vals) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Processing key{from,to}=${key}\n";
|
||||
// Get the first item
|
||||
foreach ($vals as $val) {
|
||||
break; // no matter which...
|
||||
}
|
||||
$item = $val[0]; // first entry
|
||||
if ($max_parsedemail_item_id<=$item["last_parsedemail_item_id"] && $max_quote_id<=$item["last_quotes_id"]) {
|
||||
echo "[".date("Y-m-d H:i:s")."] No new records to compare for the key=${key}\n";
|
||||
continue;
|
||||
}
|
||||
$from_area = $areas[$item["area_start_id"]];
|
||||
$to_area = $areas[$item["area_end_id"]];
|
||||
try {
|
||||
// We assume quotes has UTC timestamp without timezone
|
||||
$q = "(SELECT a.cost, a.transport_provider_id, ";
|
||||
$q.= " date_part('hour',(a.travel_date at time zone 'utc' at time zone '${tz}')) AS hour FROM quotes a ";
|
||||
$q.= " JOIN address AS b ON (b.id = a.location_start_id) ";
|
||||
$q.= " JOIN address AS c ON (c.id = a.location_end_id) ";
|
||||
$q.= " WHERE a.cost>0 AND a.travel_date BETWEEN NOW() - INTERVAL '" . $numberOfDays . " days' AND NOW()";
|
||||
$q.= " AND (b.country='".$from_area["country"]."' OR c.country='".$to_area["country"]."') ";
|
||||
$q.= " AND a.transport_provider_id IN (".implode(",",$transport_providers).")";
|
||||
//echo $q; unlock_pid_file($lock_file); exit();
|
||||
$q.= " AND a.id>".$item["last_quotes_id"]." AND a.id<=".$max_quote_id;
|
||||
$q.= process_area_filter($from_area,$to_area);
|
||||
$q.= ") UNION ALL (";
|
||||
// We assume parsedemail_item has local timestamp without timezone
|
||||
$q.= "SELECT a.base_cost, a.transport_provider_id, date_part('hour', a.travel_date) AS hour FROM parsedemail_item a ";
|
||||
$q.= " JOIN address AS b ON (b.id = a.location_start_id) ";
|
||||
$q.= " JOIN address AS c ON (c.id = a.location_end_id) ";
|
||||
$q.= " WHERE a.base_cost>0 AND a.travel_date BETWEEN NOW() - INTERVAL '" . $numberOfDays . " days' AND NOW()";
|
||||
$q.= " AND a.dup_id IS NULL AND a.private='f' AND a.booking='f' AND a.transport_provider_id IS NOT NULL ";
|
||||
$q.= " AND (b.country='".$from_area["country"]."' OR c.country='".$to_area["country"]."') ";
|
||||
$q.= " AND a.transport_provider_id IN (".implode(",",$transport_providers).")";
|
||||
$q.= " AND a.id>".$item["last_parsedemail_item_id"]." AND a.id<=".$max_parsedemail_item_id;
|
||||
$q.= " AND (distance IS NULL OR distance<".$min_distance." OR base_cost/distance>".$min_rate.")";
|
||||
$q.= process_area_filter($from_area,$to_area);
|
||||
$q.= ")";
|
||||
// Master query
|
||||
$mq = "SELECT ROUND(AVG(a.cost), 2) as average_cost, ROUND(SUM(a.cost),2) AS average_total, COUNT(*) AS average_count, a.transport_provider_id, a.hour ";
|
||||
$mq.= " FROM (${q}) AS a GROUP BY a.transport_provider_id,a.hour";
|
||||
|
||||
if ( ($item["area_start_id"]==23 and $item["area_end_id"]==9)
|
||||
|| ($item["area_start_id"]==12 and $item["area_end_id"]==4)
|
||||
|| ($item["area_start_id"]==14 and $item["area_end_id"]==16)
|
||||
|| ($item["area_start_id"]== 9 and $item["area_end_id"]==14)
|
||||
|| ($item["area_start_id"]==23 and $item["area_end_id"]==22)
|
||||
|| ($item["area_start_id"]==17 and $item["area_end_id"]==7)
|
||||
|| ($item["area_start_id"]==22 and $item["area_end_id"]==22)) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Area '".$item["area_start_id"]."' to area '".$item["area_end_id"]."' \n";
|
||||
echo $mq.";\n\n";
|
||||
}
|
||||
$r = pg_query($readOnlyReplicaConn, $mq);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
// unique(area_start_id,area_end_id,transport_provider_id,hour)
|
||||
$average_cost = $average_quote[$key][$f["transport_provider_id"]][$f["hour"]]["average_cost"];
|
||||
$average_total = $average_quote[$key][$f["transport_provider_id"]][$f["hour"]]["average_total"];
|
||||
$average_count = $average_quote[$key][$f["transport_provider_id"]][$f["hour"]]["average_count"];
|
||||
|
||||
$new_average_cost = $f["average_cost"];
|
||||
$new_average_count = $average_count + $f["average_count"];
|
||||
$new_average_total = $average_total + $f["average_total"];
|
||||
if ($new_average_count>0) {
|
||||
$new_average_cost = sprintf("%0.02f",$new_average_total/$new_average_count);
|
||||
}
|
||||
|
||||
$average_quote[$key][$f["transport_provider_id"]][$f["hour"]]["average_cost"] = $new_average_cost;
|
||||
$average_quote[$key][$f["transport_provider_id"]][$f["hour"]]["average_total"] = $new_average_total;
|
||||
$average_quote[$key][$f["transport_provider_id"]][$f["hour"]]["average_count"] = $new_average_count;
|
||||
$average_quote[$key][$f["transport_provider_id"]][$f["hour"]]["last_quotes_id"] = $max_quote_id;
|
||||
$average_quote[$key][$f["transport_provider_id"]][$f["hour"]]["last_parsedemail_item_id"] = $max_parsedemail_item_id;
|
||||
$average_quote[$key][$f["transport_provider_id"]][$f["hour"]]["id"] = save_or_update($average_quote[$key][$f["transport_provider_id"]][$f["hour"]]);
|
||||
}
|
||||
} else {
|
||||
$err = pg_last_error();
|
||||
if ($err === "") {
|
||||
echo "[".date("Y-m-d H:i:s")."] WARNING(${key}): No trips found between areas?\n";
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] ERROR(${key}): ${err}\n";
|
||||
echo "[".date("Y-m-d H:i:s")."] ${q}\n";
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
echo "[".date("Y-m-d H:i:s")."] ERROR(${key}): ".$e->getMessage()."\n";
|
||||
}
|
||||
//unlock_pid_file($lock_file); exit(); // DEBUG
|
||||
}
|
||||
}
|
||||
|
||||
function save_or_update($data) {
|
||||
global $con;
|
||||
$qb = "average_cost=".sprintf("%0.02f",$data["average_cost"]);
|
||||
$qb.= ",average_total=".sprintf("%0.02f",$data["average_total"]);
|
||||
$qb.= ",average_count=".((int)$data["average_count"]);
|
||||
$qb.= ",last_updated=NOW()";
|
||||
$qb.= ",last_quotes_id=".((int)$data["last_quotes_id"]);
|
||||
$qb.= ",last_parsedemail_item_id=".((int)$data["last_parsedemail_item_id"]);
|
||||
|
||||
if ($data["id"]>0) {
|
||||
// Update
|
||||
$q = "UPDATE geofence_area_average_quotes SET";
|
||||
$q.= " ".$qb." ";
|
||||
$q.= " WHERE id=".$data["id"]." RETURNING id";
|
||||
} else {
|
||||
// Save
|
||||
$fields = ['area_start_id','area_end_id','transport_provider_id','average_cost','average_total','average_count','hour','last_quotes_id','last_parsedemail_item_id'];
|
||||
$values = [];
|
||||
foreach ($fields as $field) {
|
||||
$values[] = $data[$field];
|
||||
}
|
||||
$q = "INSERT INTO geofence_area_average_quotes (".implode(",",$fields).") VALUES(".implode(",",$values).") ";
|
||||
$q.= " ON CONFLICT (area_start_id, area_end_id, transport_provider_id, hour) DO UPDATE SET ${qb} RETURNING id";
|
||||
}
|
||||
//echo $q . "\n";
|
||||
//*
|
||||
$r = pg_query($con, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) {
|
||||
return $f[0]; // ID
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] ERROR: ${q}\n";
|
||||
}//*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
CREATE TABLE geofence_area_average_quotes (
|
||||
id bigserial,
|
||||
area_start_id int references geofence_area(id),
|
||||
area_end_id int references geofence_area(id),
|
||||
transport_provider_id int references transport_providers(id),
|
||||
average_cost numeric,
|
||||
average_total numeric,
|
||||
average_count int,
|
||||
hour smallint not null,
|
||||
last_updated timestamp default now(),
|
||||
last_quotes_id bigint,
|
||||
last_parsedemail_item_id bigint,
|
||||
primary key(id),
|
||||
unique(area_start_id,area_end_id,transport_provider_id,hour)
|
||||
);
|
||||
*/
|
||||
|
||||
function process_area_filter($from_area,$to_area) {
|
||||
$from_boundaries = json_decode($from_area["boundaries"],true);
|
||||
$to_boundaries = json_decode($to_area["boundaries"],true);
|
||||
$q = "";
|
||||
if ($from_area['type'] === 'radius') {
|
||||
$q.= process_area_filter_radius('b',$from_area,$from_boundaries);
|
||||
}
|
||||
if ($to_area['type'] === 'radius') {
|
||||
$q.= process_area_filter_radius('c',$to_area,$to_boundaries);
|
||||
}
|
||||
if ($from_area['type'] === 'postal') {
|
||||
$q.= process_area_filter_postal('b',$from_area,$from_boundaries);
|
||||
//$q.= process_area_filter_polygon('b',$from_area,$from_boundaries);
|
||||
}
|
||||
if ($to_area['type'] === 'postal') {
|
||||
$q.= process_area_filter_postal('c',$to_area,$to_boundaries);
|
||||
//$q.= process_area_filter_polygon('c',$to_area,$to_boundaries);
|
||||
}
|
||||
if ($from_area['type'] === 'polygon') {
|
||||
$q.= process_area_filter_polygon('b',$from_area,$from_boundaries);
|
||||
}
|
||||
if ($to_area['type'] === 'polygon') {
|
||||
$q.= process_area_filter_polygon('c',$to_area,$to_boundaries);
|
||||
}
|
||||
return $q;
|
||||
}
|
||||
|
||||
function process_area_filter_radius($ref,$area,$boundaries) {
|
||||
if (is_array($boundaries) && array_key_exists("radius",$boundaries) && $boundaries["radius"]>0) {
|
||||
return " AND ST_DWithin('" . $area['location'] . "', ${ref}.geometry, " . $boundaries["radius"] . ")";
|
||||
}
|
||||
throw new Exception("Missing radius in boundaries field");
|
||||
}
|
||||
|
||||
function process_area_filter_postal($ref,$area,$boundaries) {
|
||||
if (is_array($boundaries) && array_key_exists("postal_code",$boundaries) && is_array($boundaries["postal_code"]) && count($boundaries["postal_code"])>0) {
|
||||
$q = "";
|
||||
foreach ($boundaries["postal_code"] as $code) {
|
||||
if ($q!="") $q.= " OR ";
|
||||
$q.= " LEFT(${ref}.postal,".strlen($code).")='${code}' ";
|
||||
}
|
||||
return " AND (".$q.")";
|
||||
}
|
||||
throw new Exception("Missing postal_code in boundaries field");
|
||||
}
|
||||
|
||||
function process_area_filter_polygon($ref,$area,$boundaries) {
|
||||
if (is_array($boundaries) && array_key_exists("polygon",$boundaries) && is_array($boundaries["polygon"]) and count($boundaries["polygon"])>0) {
|
||||
$polygonCoords = [];
|
||||
foreach ($boundaries["polygon"] as $coord) {
|
||||
$polygonCoords[] = "$coord[0] $coord[1]";
|
||||
}
|
||||
$polygonCoordsString = implode(",", $polygonCoords);
|
||||
return " AND ST_Contains(ST_GeomFromText('POLYGON((${polygonCoordsString}))', 4326), ${ref}.geometry::geometry) ";
|
||||
}
|
||||
throw new Exception("Missing radius in boundaries field");
|
||||
}
|
||||
|
||||
pg_close($con);
|
||||
pg_close($readOnlyReplicaConn);
|
||||
|
||||
unlock_pid_file($lock_file);
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] geofence_area_average_quotes job complete.\n";
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,337 @@
|
||||
<?php
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] geofence_area_average_quotes job is starting.\n";
|
||||
|
||||
require('./lock.php');
|
||||
$lock_file = lock_pid_file();
|
||||
|
||||
|
||||
$profile = getenv("SAVVY_PROFILE");
|
||||
if ($profile) {
|
||||
require_once("../backend.${profile}.php");
|
||||
} else {
|
||||
require_once('../backend.php');
|
||||
}
|
||||
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$con = pg_connect($connstr);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
|
||||
|
||||
if ($con===FALSE || $readOnlyReplicaConn===FALSE) {
|
||||
unlock_pid_file($lock_file);
|
||||
die ("Could not connect to server\n");
|
||||
}
|
||||
$rate = 1.1;
|
||||
$numberOfDays = 365; // This is handled by update cheapest data job now...
|
||||
|
||||
$city_id = 257;
|
||||
$tz = 'America/Los_Angeles';
|
||||
$transport_providers = [1, 2, 8];
|
||||
$min_distance = 0.1; //0.1km
|
||||
$min_rate = 0.2; //20 cents
|
||||
|
||||
// Load max IDs
|
||||
$q = "SELECT max(id) FROM parsedemail_item WHERE base_cost>0 AND dup_id IS NULL AND private='f' AND booking='f' AND transport_provider_id IS NOT NULL";
|
||||
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) {
|
||||
$max_parsedemail_item_id = $f[0];
|
||||
}
|
||||
|
||||
$q = "SELECT max(id) FROM quotes WHERE cost>0";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) {
|
||||
$max_quote_id = $f[0];
|
||||
}
|
||||
|
||||
// Load areas
|
||||
$areas = [];
|
||||
$q = "SELECT * FROM geofence_area WHERE city_id=${city_id} AND id in (30,51)";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
$areas[$f["id"]] = $f;
|
||||
}
|
||||
}
|
||||
|
||||
// Load previous data
|
||||
$average_quotes = [];
|
||||
foreach ($areas as $f) {
|
||||
$average_quotes[$f["id"]] = load_average_quotes_for_area($f,$areas,$transport_providers);
|
||||
}
|
||||
|
||||
// Start processing
|
||||
foreach ($average_quotes as $area_id=>$average_quote) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Processing area ID #${area_id}\n";
|
||||
process_area_average_quotes($average_quote,$areas,$area_id, $min_distance,$min_rate);
|
||||
}
|
||||
|
||||
/*********************************** Function ***********************************/
|
||||
|
||||
function load_average_quotes_for_area($area,$areas,$transport_providers) {
|
||||
global $con, $readOnlyReplicaConn;
|
||||
$average_quotes = [];
|
||||
// Pre-fill the initial data
|
||||
for ($i=0;$i<24;$i++) {
|
||||
foreach ($areas as $item) {
|
||||
foreach ($transport_providers as $transport_provider_id) {
|
||||
// unique(area_start_id,area_end_id,transport_provider_id,hour)
|
||||
$key = $area["id"]."_".$item["id"];
|
||||
if (!array_key_exists($key,$average_quotes)) {
|
||||
$average_quotes[$key] = []; // initialize
|
||||
}
|
||||
if (!array_key_exists($transport_provider_id,$average_quotes[$key])) {
|
||||
$average_quotes[$key][$transport_provider_id] = [];
|
||||
}
|
||||
$average_quotes[$key][$transport_provider_id][$i] = [
|
||||
"id" => 0,
|
||||
"area_start_id" => $area["id"],
|
||||
"area_end_id" => $item["id"],
|
||||
"transport_provider_id" => $transport_provider_id,
|
||||
"average_cost" => 0,
|
||||
"average_total" => 0,
|
||||
"average_count" => 0,
|
||||
"hour" => $i,
|
||||
/* "last_updated" => NULL, */
|
||||
"last_quotes_id" => 0,
|
||||
"last_parsedemail_item_id" => 0
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
// Load the existing data from the DB
|
||||
$q = "SELECT * FROM geofence_area_average_quotes WHERE area_start_id=".$area["id"];
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
// unique(area_start_id,area_end_id,transport_provider_id,hour)
|
||||
$key = $f["area_start_id"]."_".$f["area_end_id"];
|
||||
if (!array_key_exists($key,$average_quotes)) {
|
||||
$average_quotes[$key] = [];
|
||||
}
|
||||
if (!array_key_exists($f["transport_provider_id"],$average_quotes[$key])) {
|
||||
$average_quotes[$key][$f["transport_provider_id"]] = [];
|
||||
}
|
||||
$average_quotes[$key][$f["transport_provider_id"]][$f["hour"]] = $f;
|
||||
}
|
||||
}
|
||||
return $average_quotes;
|
||||
}
|
||||
|
||||
function process_area_average_quotes($average_quote,$areas,$area_id,$min_distance=0.1,$min_rate=0.2) {
|
||||
global $con, $readOnlyReplicaConn, $max_parsedemail_item_id, $max_quote_id, $numberOfDays, $tz, $transport_providers;
|
||||
// $average_quote[$key][$transport_provider_id][$hour]
|
||||
foreach ($average_quote as $key=>$vals) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Processing key{from,to}=${key}\n";
|
||||
// Get the first item
|
||||
foreach ($vals as $val) {
|
||||
break; // no matter which...
|
||||
}
|
||||
$item = $val[0]; // first entry
|
||||
if ($max_parsedemail_item_id<=$item["last_parsedemail_item_id"] && $max_quote_id<=$item["last_quotes_id"]) {
|
||||
echo "[".date("Y-m-d H:i:s")."] No new records to compare for the key=${key}\n";
|
||||
continue;
|
||||
}
|
||||
$from_area = $areas[$item["area_start_id"]];
|
||||
$to_area = $areas[$item["area_end_id"]];
|
||||
try {
|
||||
// We assume quotes has UTC timestamp without timezone
|
||||
$q = "(SELECT a.cost, a.transport_provider_id, ";
|
||||
$q.= " date_part('hour',(a.travel_date at time zone 'utc' at time zone '${tz}')) AS hour FROM quotes a ";
|
||||
$q.= " JOIN address AS b ON (b.id = a.location_start_id) ";
|
||||
$q.= " JOIN address AS c ON (c.id = a.location_end_id) ";
|
||||
$q.= " WHERE a.cost>0 AND a.travel_date BETWEEN NOW() - INTERVAL '" . $numberOfDays . " days' AND NOW()";
|
||||
$q.= " AND (b.country='".$from_area["country"]."' OR c.country='".$to_area["country"]."') ";
|
||||
$q.= " AND a.transport_provider_id IN (".implode(",",$transport_providers).")";
|
||||
//echo $q; unlock_pid_file($lock_file); exit();
|
||||
$q.= " AND a.id>".$item["last_quotes_id"]." AND a.id<=".$max_quote_id;
|
||||
$q.= process_area_filter($from_area,$to_area);
|
||||
$q.= ") UNION ALL (";
|
||||
// We assume parsedemail_item has local timestamp without timezone
|
||||
$q.= "SELECT a.base_cost, a.transport_provider_id, date_part('hour', a.travel_date) AS hour FROM parsedemail_item a ";
|
||||
$q.= " JOIN address AS b ON (b.id = a.location_start_id) ";
|
||||
$q.= " JOIN address AS c ON (c.id = a.location_end_id) ";
|
||||
$q.= " WHERE a.base_cost>0 AND a.travel_date BETWEEN NOW() - INTERVAL '" . $numberOfDays . " days' AND NOW()";
|
||||
$q.= " AND a.dup_id IS NULL AND a.private='f' AND a.booking='f' AND a.transport_provider_id IS NOT NULL ";
|
||||
$q.= " AND (b.country='".$from_area["country"]."' OR c.country='".$to_area["country"]."') ";
|
||||
$q.= " AND a.transport_provider_id IN (".implode(",",$transport_providers).")";
|
||||
$q.= " AND a.id>".$item["last_parsedemail_item_id"]." AND a.id<=".$max_parsedemail_item_id;
|
||||
$q.= " AND (distance IS NULL OR distance<".$min_distance." OR base_cost/distance>".$min_rate.")";
|
||||
$q.= process_area_filter($from_area,$to_area);
|
||||
$q.= ")";
|
||||
// Master query
|
||||
$mq = "SELECT ROUND(AVG(a.cost), 2) as average_cost, ROUND(SUM(a.cost),2) AS average_total, COUNT(*) AS average_count, a.transport_provider_id, a.hour ";
|
||||
$mq.= " FROM (${q}) AS a GROUP BY a.transport_provider_id,a.hour";
|
||||
|
||||
$r = pg_query($readOnlyReplicaConn, $mq);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
// unique(area_start_id,area_end_id,transport_provider_id,hour)
|
||||
$average_cost = $average_quote[$key][$f["transport_provider_id"]][$f["hour"]]["average_cost"];
|
||||
$average_total = $average_quote[$key][$f["transport_provider_id"]][$f["hour"]]["average_total"];
|
||||
$average_count = $average_quote[$key][$f["transport_provider_id"]][$f["hour"]]["average_count"];
|
||||
|
||||
$new_average_cost = $f["average_cost"];
|
||||
$new_average_count = $average_count + $f["average_count"];
|
||||
$new_average_total = $average_total + $f["average_total"];
|
||||
if ($new_average_count>0) {
|
||||
$new_average_cost = sprintf("%0.02f",$new_average_total/$new_average_count);
|
||||
}
|
||||
|
||||
$average_quote[$key][$f["transport_provider_id"]][$f["hour"]]["average_cost"] = $new_average_cost;
|
||||
$average_quote[$key][$f["transport_provider_id"]][$f["hour"]]["average_total"] = $new_average_total;
|
||||
$average_quote[$key][$f["transport_provider_id"]][$f["hour"]]["average_count"] = $new_average_count;
|
||||
$average_quote[$key][$f["transport_provider_id"]][$f["hour"]]["last_quotes_id"] = $max_quote_id;
|
||||
$average_quote[$key][$f["transport_provider_id"]][$f["hour"]]["last_parsedemail_item_id"] = $max_parsedemail_item_id;
|
||||
$average_quote[$key][$f["transport_provider_id"]][$f["hour"]]["id"] = save_or_update($average_quote[$key][$f["transport_provider_id"]][$f["hour"]]);
|
||||
}
|
||||
} else {
|
||||
$err = pg_last_error();
|
||||
if ($err === "") {
|
||||
echo "[".date("Y-m-d H:i:s")."] WARNING(${key}): No trips found between areas?\n";
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] ERROR(${key}): ${err}\n";
|
||||
echo "[".date("Y-m-d H:i:s")."] ${q}\n";
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
echo "[".date("Y-m-d H:i:s")."] ERROR(${key}): ".$e->getMessage()."\n";
|
||||
}
|
||||
//unlock_pid_file($lock_file); exit(); // DEBUG
|
||||
}
|
||||
}
|
||||
|
||||
function save_or_update($data) {
|
||||
global $con;
|
||||
$qb = "average_cost=".sprintf("%0.02f",$data["average_cost"]);
|
||||
$qb.= ",average_total=".sprintf("%0.02f",$data["average_total"]);
|
||||
$qb.= ",average_count=".((int)$data["average_count"]);
|
||||
$qb.= ",last_updated=NOW()";
|
||||
$qb.= ",last_quotes_id=".((int)$data["last_quotes_id"]);
|
||||
$qb.= ",last_parsedemail_item_id=".((int)$data["last_parsedemail_item_id"]);
|
||||
|
||||
if ($data["id"]>0) {
|
||||
// Update
|
||||
$q = "UPDATE geofence_area_average_quotes SET";
|
||||
$q.= " ".$qb." ";
|
||||
$q.= " WHERE id=".$data["id"]." RETURNING id";
|
||||
} else {
|
||||
// Save
|
||||
$fields = ['area_start_id','area_end_id','transport_provider_id','average_cost','average_total','average_count','hour','last_quotes_id','last_parsedemail_item_id'];
|
||||
$values = [];
|
||||
foreach ($fields as $field) {
|
||||
$values[] = $data[$field];
|
||||
}
|
||||
$q = "INSERT INTO geofence_area_average_quotes (".implode(",",$fields).") VALUES(".implode(",",$values).") ";
|
||||
$q.= " ON CONFLICT (area_start_id, area_end_id, transport_provider_id, hour) DO UPDATE SET ${qb} RETURNING id";
|
||||
}
|
||||
//echo $q . "\n";
|
||||
//*
|
||||
$r = pg_query($con, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) {
|
||||
return $f[0]; // ID
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] ERROR: ${q}\n";
|
||||
}//*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
CREATE TABLE geofence_area_average_quotes (
|
||||
id bigserial,
|
||||
area_start_id int references geofence_area(id),
|
||||
area_end_id int references geofence_area(id),
|
||||
transport_provider_id int references transport_providers(id),
|
||||
average_cost numeric,
|
||||
average_total numeric,
|
||||
average_count int,
|
||||
hour smallint not null,
|
||||
last_updated timestamp default now(),
|
||||
last_quotes_id bigint,
|
||||
last_parsedemail_item_id bigint,
|
||||
primary key(id),
|
||||
unique(area_start_id,area_end_id,transport_provider_id,hour)
|
||||
);
|
||||
*/
|
||||
|
||||
function process_area_filter($from_area,$to_area) {
|
||||
$from_boundaries = json_decode($from_area["boundaries"],true);
|
||||
$to_boundaries = json_decode($to_area["boundaries"],true);
|
||||
$q = "";
|
||||
if ($from_area['type'] === 'radius') {
|
||||
$q.= process_area_filter_radius('b',$from_area,$from_boundaries);
|
||||
}
|
||||
if ($to_area['type'] === 'radius') {
|
||||
$q.= process_area_filter_radius('c',$to_area,$to_boundaries);
|
||||
}
|
||||
if ($from_area['type'] === 'postal') {
|
||||
$q.= process_area_filter_postal('b',$from_area,$from_boundaries);
|
||||
//$q.= process_area_filter_polygon('b',$from_area,$from_boundaries);
|
||||
}
|
||||
if ($to_area['type'] === 'postal') {
|
||||
$q.= process_area_filter_postal('c',$to_area,$to_boundaries);
|
||||
//$q.= process_area_filter_polygon('c',$to_area,$to_boundaries);
|
||||
}
|
||||
if ($from_area['type'] === 'polygon') {
|
||||
$q.= process_area_filter_polygon('b',$from_area,$from_boundaries);
|
||||
}
|
||||
if ($to_area['type'] === 'polygon') {
|
||||
$q.= process_area_filter_polygon('c',$to_area,$to_boundaries);
|
||||
}
|
||||
return $q;
|
||||
}
|
||||
|
||||
function process_area_filter_radius($ref,$area,$boundaries) {
|
||||
if (is_array($boundaries) && array_key_exists("radius",$boundaries) && $boundaries["radius"]>0) {
|
||||
return " AND ST_DWithin('" . $area['location'] . "', ${ref}.geometry, " . $boundaries["radius"] . ")";
|
||||
}
|
||||
throw new Exception("Missing radius in boundaries field");
|
||||
}
|
||||
|
||||
function process_area_filter_postal($ref,$area,$boundaries) {
|
||||
if (is_array($boundaries) && array_key_exists("postal_code",$boundaries) && is_array($boundaries["postal_code"]) && count($boundaries["postal_code"])>0) {
|
||||
$q = "";
|
||||
foreach ($boundaries["postal_code"] as $code) {
|
||||
if ($q!="") $q.= " OR ";
|
||||
$q.= " LEFT(${ref}.postal,".strlen($code).")='${code}' ";
|
||||
}
|
||||
return " AND (".$q.")";
|
||||
}
|
||||
throw new Exception("Missing postal_code in boundaries field");
|
||||
}
|
||||
|
||||
function process_area_filter_polygon($ref,$area,$boundaries) {
|
||||
if (is_array($boundaries) && array_key_exists("polygon",$boundaries) && is_array($boundaries["polygon"]) and count($boundaries["polygon"])>0) {
|
||||
$polygonCoords = [];
|
||||
foreach ($boundaries["polygon"] as $coord) {
|
||||
$polygonCoords[] = "$coord[0] $coord[1]";
|
||||
}
|
||||
$polygonCoordsString = implode(",", $polygonCoords);
|
||||
return " AND ST_Contains(ST_GeomFromText('POLYGON((${polygonCoordsString}))', 4326), ${ref}.geometry::geometry) ";
|
||||
}
|
||||
throw new Exception("Missing polygon in boundaries field");
|
||||
}
|
||||
|
||||
pg_close($con);
|
||||
pg_close($readOnlyReplicaConn);
|
||||
|
||||
unlock_pid_file($lock_file);
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] geofence_area_average_quotes job complete.\n";
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,191 @@
|
||||
<?php
|
||||
$job_name = 'geofence_area_city_cleanup';
|
||||
echo "[" . date("Y-m-d H:i:s") . "] {$job_name} job is starting.\n";
|
||||
|
||||
require 'common/config.php';
|
||||
require 'common/address_city.php';
|
||||
require 'common/Geocode.php';
|
||||
$total = $success = $failed = 0;
|
||||
/*
|
||||
* 1. Get duplicated cities
|
||||
* 2. Update one city in #1, and remove others
|
||||
* 3. Update incorrect name
|
||||
*/
|
||||
|
||||
$conditions = [
|
||||
"city='' OR city IS NULL",
|
||||
"country in ('TR','UA')",
|
||||
"LENGTH(city)=2",
|
||||
"city ~ '[0-9]+'"
|
||||
//"city LIKE 'San F%' or city LIKE 'SFO%'"
|
||||
];
|
||||
foreach ($conditions as $condition) {
|
||||
$r=getCitiesByCondition($condition);
|
||||
while ($f = pg_fetch_assoc($r)) { //d($f,1);
|
||||
$ok = false;
|
||||
$total++;
|
||||
$city_id = $f['id'];
|
||||
$latitude = $f['latitude'];
|
||||
$longitude = $f['longitude'];
|
||||
|
||||
$city_new_name="";
|
||||
$data_reverse = Geocode::reverseGPS($latitude, $longitude);
|
||||
if (!empty($data_reverse['city'])) {
|
||||
$city_new_name = $data_reverse['city'];
|
||||
} else {
|
||||
$city_new_name = Geocode::getGeoInfoBigDataCloud($latitude, $longitude);
|
||||
}
|
||||
if (!empty($city_new_name)) {
|
||||
$data_update_city = [
|
||||
'city' => $city_new_name
|
||||
];
|
||||
$updated = updateDataTable('geofence_area_city', 'id=' . $city_id, $data_update_city);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$r = getAddressWithEmptyCity();
|
||||
while ($f = pg_fetch_assoc($r)) {
|
||||
$total++;
|
||||
$city_name = $f['city'];
|
||||
$country_code = $f['country'];
|
||||
$city_id = $f['city_id'];
|
||||
$address = $f['address'];
|
||||
$latitude = $f['latitude'];
|
||||
$longitude = $f['longitude'];
|
||||
|
||||
$address_info = parseAddressByCountry($address, $country_code);
|
||||
$city_new_name = "";
|
||||
if (!empty($address_info['city'])) {
|
||||
$city_new_name = $address_info['city'];
|
||||
} else {
|
||||
$city_new_name = Geocode::getGeoInfoBigDataCloud($latitude, $longitude);
|
||||
if (empty($city_new_name)) {
|
||||
$data_reverse = Geocode::reverseGPS($latitude, $longitude);
|
||||
if (!empty($data_reverse['city'])) {
|
||||
$city_new_name = $data_reverse['city'];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($city_new_name)) {
|
||||
$city_new_id = getCityId($city_new_name, $country_code, $latitude, $longitude);
|
||||
$city_id = $city_new_id;
|
||||
$data_update = [
|
||||
'city_id' => $city_new_id,
|
||||
];
|
||||
|
||||
$updated = updateDataTable('address', 'id=' . $f['id'], $data_update);
|
||||
if ($updated) {
|
||||
$ok = true;
|
||||
} else {
|
||||
$ok = false;
|
||||
}
|
||||
}
|
||||
if (empty($city_name)) {
|
||||
$data_update_city = [
|
||||
'city' => $city_new_name,
|
||||
'country' => $country_code,
|
||||
];
|
||||
$updated = updateDataTable('geofence_area_city', 'id=' . $city_id, $data_update_city);
|
||||
if ($updated) {
|
||||
$ok = true;
|
||||
} else {
|
||||
$ok = false;
|
||||
}
|
||||
}
|
||||
if (!empty($ok)) {
|
||||
$success++;
|
||||
} else {
|
||||
$failed++;
|
||||
}
|
||||
|
||||
}
|
||||
//clean duplicated cities
|
||||
$r = getDuplicatedCities();
|
||||
while ($f = pg_fetch_assoc($r)) {
|
||||
$city_name = $f['city'];
|
||||
$country = $f['country'];
|
||||
$citie_ids = getCities($city_name, $country);
|
||||
$num = count($citie_ids);
|
||||
if ($num > 0) {
|
||||
$total += $num;
|
||||
foreach ($citie_ids as $country => $ids) {
|
||||
$city_id = $ids[0];
|
||||
$data_update = [
|
||||
'city_id' => $city_id,
|
||||
];
|
||||
$condition = "country='" . $country . "' AND city_id IN (" . implode(",", $ids) . ")";
|
||||
$updated = updateDataTable("address", $condition, $data_update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deleteUnusedCities();
|
||||
|
||||
echo "Total: " . $total . ".\n";
|
||||
echo "Success: : " . $success . ".\n";
|
||||
echo "Failed: : " . $failed . ".\n";
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] {$job_name} job complete.\n";
|
||||
|
||||
function getCitiesByCondition($condition)
|
||||
{
|
||||
global $conn, $readOnlyReplicaConn;
|
||||
$q = "SELECT id, latitude,longitude
|
||||
FROM geofence_area_city
|
||||
WHERE ".$condition;
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
return $r;
|
||||
}
|
||||
|
||||
|
||||
function getAddressWithEmptyCity()
|
||||
{
|
||||
global $conn, $readOnlyReplicaConn;
|
||||
$q = "SELECT a.id, address, a.latitude, a.longitude, city_id, city, a.country as country
|
||||
FROM address a
|
||||
LEFT JOIN geofence_area_city b ON a.city_id=b.id
|
||||
WHERE city_id IS NULL OR b.city='' OR a.country!=b.country;";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
return $r;
|
||||
}
|
||||
|
||||
function getDuplicatedCities()
|
||||
{
|
||||
global $conn, $readOnlyReplicaConn;
|
||||
$q = "SELECT city, country, count(*)
|
||||
FROM geofence_area_city
|
||||
GROUP BY city,
|
||||
country
|
||||
HAVING count(*)>1
|
||||
ORDER BY count(*) DESC";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
return $r;
|
||||
}
|
||||
|
||||
function deleteUnusedCities()
|
||||
{
|
||||
global $conn;
|
||||
$q = "DELETE
|
||||
FROM geofence_area_city
|
||||
WHERE id NOT IN (SELECT DISTINCT city_id FROM address);";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_affected_rows($r)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getCities($city, $country)
|
||||
{
|
||||
global $readOnlyReplicaConn;
|
||||
$q = "SELECT id FROM geofence_area_city WHERE LOWER(city) ILIKE '" . strtolower(pg_escape_string($city)) . "' AND country='" . $country . "' ORDER BY id ASC";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
$result = [];
|
||||
while ($f = pg_fetch_assoc($r)) {
|
||||
$result[$country][] = $f['id'];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] GPS geometry_address job is starting.\n";
|
||||
|
||||
require('../backend.php');
|
||||
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
|
||||
$q = "SELECT * FROM address WHERE geometry IS NULL AND latitude!=0 AND longitude!=0";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
$data = [
|
||||
"geometry" => "ST_SetSRID(ST_MakePoint(".$f["longitude"].",".$f["latitude"]."), 4326)"
|
||||
];
|
||||
list($res,$err) = updateAddress($f["id"], $data);
|
||||
if ($err && $err!="") {
|
||||
echo "[".date("Y-m-d H:i:s")."] Failure: ${err} (".$f["id"].")\n";
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Complete: ".$f["id"]."\n";
|
||||
}
|
||||
}
|
||||
|
||||
function updateAddress($id, $data) {
|
||||
global $conn, $readOnlyReplicaConn;
|
||||
$columns = [];
|
||||
$q = "select column_name, data_type, character_maximum_length from INFORMATION_SCHEMA.COLUMNS where table_name = 'address'";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
$columns[$f['column_name']] = $f['data_type'];
|
||||
}
|
||||
$q = "UPDATE address SET id=${id}";
|
||||
foreach ($data as $key=>$val) {
|
||||
if ($key=="id") continue;
|
||||
if (array_key_exists($key,$columns) && $columns[$key]!='character varying' && $columns[$key]!='date') {
|
||||
$q.= ", ${key} = ".($val==""?"NULL":$val);
|
||||
} else {
|
||||
$q.= ", ${key} = '".pg_escape_string($val)."'";
|
||||
}
|
||||
}
|
||||
$q.= " WHERE id=${id} RETURNING *";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) {
|
||||
return [$f, NULL];
|
||||
}
|
||||
return [NULL, pg_last_error($conn)];
|
||||
}
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] GPS geometry_address job complete.\n";
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
require '../backend.php';
|
||||
|
||||
global $pgconn_gps, $readOnlyReplicaConn;
|
||||
|
||||
$gps_address_insert = <<< EOS
|
||||
INSERT INTO address(id, address, latitude, longitude, location) VALUES ($1, $2, $3, $4, st_setsrid(st_point($4, $3),4326))
|
||||
EOS;
|
||||
|
||||
$gps_db_host = $savvyext->cfgReadChar('gpsdatabase.host');
|
||||
$gps_db_port = $savvyext->cfgReadLong('gpsdatabase.port');
|
||||
$gps_db_name = $savvyext->cfgReadChar('gpsdatabase.name');
|
||||
$gps_db_user = $savvyext->cfgReadChar('gpsdatabase.user');
|
||||
$gps_db_pass = $savvyext->cfgReadChar('gpsdatabase.pass');
|
||||
$conn_string_gps = "host=${gps_db_host} port=${gps_db_port} dbname=${gps_db_name} user=${gps_db_user} password=${gps_db_pass}";
|
||||
$pgconn_gps = pg_connect($conn_string_gps);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
|
||||
// Get max id from GPS DB
|
||||
$q = "SELECT max(id) FROM address";
|
||||
$r = pg_query($pgconn_gps, $q);
|
||||
$id = 0;
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) {
|
||||
$id = (int)$f[0];
|
||||
}
|
||||
$q = "SELECT a.id, a.address, a.latitude, a.longitude FROM address as a WHERE a.id > ${id}";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
pg_query_params($pgconn_gps, $gps_address_insert, [
|
||||
$f['id'],
|
||||
$f['address'],
|
||||
$f['latitude'],
|
||||
$f['longitude']
|
||||
]);
|
||||
}
|
||||
|
||||
pg_close($readOnlyReplicaConn);
|
||||
pg_close($pgconn_gps);
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
require '../backend.php';
|
||||
|
||||
global $readOnlyReplicaConn, $pgconn_gps;
|
||||
//PostgreSQL
|
||||
$gps_db_host = $savvyext->cfgReadChar('gpsdatabase.host');
|
||||
$gps_db_port = $savvyext->cfgReadLong('gpsdatabase.port');
|
||||
$gps_db_name = $savvyext->cfgReadChar('gpsdatabase.name');
|
||||
$gps_db_user = $savvyext->cfgReadChar('gpsdatabase.user');
|
||||
$gps_db_pass = $savvyext->cfgReadChar('gpsdatabase.pass');
|
||||
$conn_string_gps = "host=${gps_db_host} port=${gps_db_port} dbname=${gps_db_name} user=${gps_db_user} password=${gps_db_pass}";
|
||||
$pgconn_gps = pg_connect($conn_string_gps);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
|
||||
// Get max id from GPS DB
|
||||
$q = "SELECT max(id) FROM parsedemail_item";
|
||||
$r = pg_query($pgconn_gps, $q);
|
||||
$id = 0;
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) {
|
||||
$id = (int)$f[0];
|
||||
}
|
||||
|
||||
// Get newer records from the main DB
|
||||
$q = "SELECT a.id,b.latitude AS location_start_lat,b.longitude AS location_start_lng,c.latitude AS location_end_lat,c.longitude AS location_end_lng ";
|
||||
$q.= " FROM parsedemail_item a, address b, address c WHERE b.id=a.location_start_id AND c.id=a.location_end_id AND a.id>${id} ORDER BY a.id";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
if ($f["location_start_lat"]==0 && $f["location_start_lng"]==0 && $f["location_end_lat"]==0 && $f["location_end_lng"]==0) {
|
||||
continue; // Bad GPS coordinates - cannot work with it...
|
||||
}
|
||||
$q = "INSERT INTO parsedemail_item (id,location_start_lat,location_start_lng,location_start,location_end_lat,location_end_lng,location_end) VALUES(";
|
||||
$q.= $f["id"].",".$f["location_start_lat"].",".$f["location_start_lng"].",st_setsrid(st_point(".$f["location_start_lng"].",".$f["location_start_lat"]."),4326),";
|
||||
$q.= $f["location_end_lat"].",".$f["location_end_lng"].",st_setsrid(st_point(".$f["location_end_lng"].",".$f["location_end_lat"]."),4326)";
|
||||
$q.= ")";
|
||||
//echo "$q\n";
|
||||
pg_query($pgconn_gps,$q);
|
||||
}
|
||||
|
||||
pg_close($readOnlyReplicaConn);
|
||||
pg_close($pgconn_gps);
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
require '../backend.php';
|
||||
|
||||
global $pgconn_gps, $readOnlyReplicaConn;
|
||||
//PostgreSQL
|
||||
$gps_db_host = $savvyext->cfgReadChar('gpsdatabase.host');
|
||||
$gps_db_port = $savvyext->cfgReadLong('gpsdatabase.port');
|
||||
$gps_db_name = $savvyext->cfgReadChar('gpsdatabase.name');
|
||||
$gps_db_user = $savvyext->cfgReadChar('gpsdatabase.user');
|
||||
$gps_db_pass = $savvyext->cfgReadChar('gpsdatabase.pass');
|
||||
$conn_string_gps = "host=${gps_db_host} port=${gps_db_port} dbname=${gps_db_name} user=${gps_db_user} password=${gps_db_pass}";
|
||||
$pgconn_gps = pg_connect($conn_string_gps);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
|
||||
$id = 0;
|
||||
|
||||
// Get newer records from the main DB
|
||||
$q = "SELECT a.id,b.latitude AS location_start_lat,b.longitude AS location_start_lng,c.latitude AS location_end_lat,c.longitude AS location_end_lng ";
|
||||
$q.= " FROM parsedemail_item a, address b, address c WHERE b.id=a.location_start_id AND c.id=a.location_end_id AND a.id>${id} ORDER BY a.id";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
if ($f["location_start_lat"]==0 && $f["location_start_lng"]==0 && $f["location_end_lat"]==0 && $f["location_end_lng"]==0) {
|
||||
continue; // Bad GPS coordinates - cannot work with it...
|
||||
}
|
||||
$q = "SELECT * FROM parsedemail_item WHERE id=".$f["id"];
|
||||
$s = pg_query($pgconn_gps,$q);
|
||||
if ($s && pg_num_rows($s)) {
|
||||
continue; // We have this record already - do not update...
|
||||
}
|
||||
$q = "INSERT INTO parsedemail_item (id,location_start_lat,location_start_lng,location_start,location_end_lat,location_end_lng,location_end) VALUES(";
|
||||
$q.= $f["id"].",".$f["location_start_lat"].",".$f["location_start_lng"].",st_setsrid(st_point(".$f["location_start_lng"].",".$f["location_start_lat"]."),4326),";
|
||||
$q.= $f["location_end_lat"].",".$f["location_end_lng"].",st_setsrid(st_point(".$f["location_end_lng"].",".$f["location_end_lat"]."),4326)";
|
||||
$q.= ")";
|
||||
//echo "$q\n";
|
||||
pg_query($pgconn_gps,$q);
|
||||
}
|
||||
|
||||
// TODO: algorithm to make sure there is no "skipped" to nor comb the whole table
|
||||
// Manual solution: increase $id variable once in a while...
|
||||
|
||||
pg_close($readOnlyReplicaConn);
|
||||
pg_close($pgconn_gps);
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
require '../backend.php';
|
||||
|
||||
global $readOnlyReplicaConn, $pgconn_gps;
|
||||
|
||||
$gps_singapore_buildings_insert = <<< EOS
|
||||
INSERT INTO singapore_buildings(id, address, latitude, longitude, location) VALUES ($1, $2, $3, $4, st_setsrid(st_point($4, $3),4326))
|
||||
EOS;
|
||||
|
||||
|
||||
//PostgreSQL
|
||||
$gps_db_host = $savvyext->cfgReadChar('gpsdatabase.host');
|
||||
$gps_db_port = $savvyext->cfgReadLong('gpsdatabase.port');
|
||||
$gps_db_name = $savvyext->cfgReadChar('gpsdatabase.name');
|
||||
$gps_db_user = $savvyext->cfgReadChar('gpsdatabase.user');
|
||||
$gps_db_pass = $savvyext->cfgReadChar('gpsdatabase.pass');
|
||||
$conn_string_gps = "host=${gps_db_host} port=${gps_db_port} dbname=${gps_db_name} user=${gps_db_user} password=${gps_db_pass}";
|
||||
$pgconn_gps = pg_connect($conn_string_gps);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
|
||||
// Get max id from GPS DB
|
||||
$q = "SELECT max(id) FROM singapore_buildings";
|
||||
$r = pg_query($pgconn_gps, $q);
|
||||
$id = 0;
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) {
|
||||
$id = (int)$f[0];
|
||||
}
|
||||
$q = "SELECT a.id, a.address, a.latitude, a.longitude FROM singapore_buildings as a WHERE a.id > ${id}";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
pg_query_params($pgconn_gps, $gps_singapore_buildings_insert, [
|
||||
$f['id'],
|
||||
$f['address'],
|
||||
$f['latitude'],
|
||||
$f['longitude']
|
||||
]);
|
||||
}
|
||||
|
||||
pg_close($readOnlyReplicaConn);
|
||||
pg_close($pgconn_gps);
|
||||
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] load_past_transit_quotes job is starting.\n";
|
||||
|
||||
require('../backend.php');
|
||||
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
|
||||
$q = "SELECT a.fare_raw,a.distance_raw,a.distance,a.board,a.alight,a.service,b.distance as bdistance ";
|
||||
$q.= " FROM leg_step_quote a, google_directions_leg_steps b WHERE a.fare_raw>0 AND b.id=a.google_directions_leg_step_id AND b.travel_mode='TRANSIT' ";
|
||||
$q.= " AND (b.location_start_lat BETWEEN 1.207 AND 1.471) AND (b.location_start_lng BETWEEN 103.610 AND 104.060) ";
|
||||
$q.= " AND (b.location_end_lat BETWEEN 1.207 AND 1.471) AND (b.location_end_lng BETWEEN 103.610 AND 104.060)";
|
||||
echo $q;
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
if ($f["service"]=="MRT/LRT") {
|
||||
//process_past_transit_quote_mrtlrt($f);
|
||||
}
|
||||
if (substr($f["service"],0,8)=="Bus Svc ") {
|
||||
process_past_transit_quote_bus($f);
|
||||
}
|
||||
}
|
||||
/*
|
||||
fare_raw | distance_raw | distance | board | alight | service | bdistance
|
||||
----------+--------------+----------+-----------------------------------+------------------------------------+-------------+-----------
|
||||
113 | 560 | 5.6 km | 41049 - Opp Coronation Plaza | 09179 - Royal Thai Embassy | Bus Svc 174 | 5492
|
||||
100 | 200 | 2.0 km | 13029 - Bef Tyersall Ave | 14539 - Beach Station Bus Terminal | Bus Svc 123 | 14621
|
||||
100 | 200 | 2.0 km | 13029 - Bef Tyersall Ave | 14539 - Beach Station Bus Terminal | Bus Svc 123 | 14621
|
||||
83 | 170 | 1.7 km | 91061 - Bet Hse No. 767/767A | 92041 - Opp Parkway Parade | Bus Svc 196 | 1787
|
||||
83 | 130 | 1.3 km | 82051 - Tg Katong Rd Sth P/G | 92041 - Opp Parkway Parade | Bus Svc 48 | 1437
|
||||
83 | 240 | 2.4 km | 11209 - Opp Peirce Rd | 09179 - Royal Thai Embassy | Bus Svc 7 | 2465
|
||||
135 | 860 | 8.6 km | Buona Vista (EW21 / CC22) | Raffles Place (NS26 / EW14) | MRT/LRT | 8585
|
||||
135 | 910 | 9.1 km | Bishan (NS17 / CC15) | Raffles Place (NS26 / EW14) | MRT/LRT | 9765
|
||||
*/
|
||||
echo "[".date("Y-m-d H:i:s")."] load_past_transit_quotes complete.\n";
|
||||
|
||||
pg_close($conn);
|
||||
|
||||
/*
|
||||
boarding_id | integer |
|
||||
alight_id | integer |
|
||||
fare | integer |
|
||||
distance | integer |
|
||||
*/
|
||||
function process_past_transit_quote_mrtlrt($f) {
|
||||
global $conn;
|
||||
echo "[".date("Y-m-d H:i:s")."] process_past_transit_quote_mrtlrt()\n";
|
||||
// singapore_mrtlrt_stop_fares
|
||||
$boarding_id = get_mrtlrt_stop_id($f["board"]);
|
||||
$alight_id = get_mrtlrt_stop_id($f["board"]);
|
||||
if ($boarding_id>0 && $alight_id>0 && $f["fare_raw"]>0) {
|
||||
$q = "SELECT * FROM singapore_mrtlrt_stop_fares WHERE boarding_id=${boarding_id} AND alight_id=${alight_id}";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
if ($r && pg_num_rows($r) && $o=pg_fetch_assoc($r)) {
|
||||
// UP?
|
||||
if ($o["fare"]>0) {
|
||||
$q = "";
|
||||
} else {
|
||||
$q = "UPDATE SET singapore_mrtlrt_stop_fares SET fare=%s,distance=%s WHERE id=".$o["id"];
|
||||
}
|
||||
} else {
|
||||
$q = "INSERT INTO singapore_mrtlrt_stop_fares (boarding_id,alight_id,fare,distance) VALUES (";
|
||||
$q.= "${boarding_id},${alight_id},%d,%d)";
|
||||
}
|
||||
if ($q!="") {
|
||||
$d = $f["distance_raw"]>0?((int)(10*$f["distance_raw"])):$f["bdistance"];
|
||||
$q = sprintf($q,(int)$f["fare_raw"],$d);
|
||||
pg_query($conn,$q);
|
||||
echo "q=${q}\n";
|
||||
} else {
|
||||
echo "Update is not required? fare=".$o["fare"]."\n";
|
||||
}
|
||||
} else {
|
||||
echo "ERROR: board(${boarding_id})='".$f["board"]."', alight(${alight_id})='".$f["alight"]."'\n";
|
||||
}
|
||||
}
|
||||
|
||||
function process_past_transit_quote_bus($f) {
|
||||
echo "[".date("Y-m-d H:i:s")."] process_past_transit_quote_bus()\n";
|
||||
global $conn, $readOnlyReplicaConn;
|
||||
// singapore_bus_stop_fares
|
||||
$line = substr($f["service"],8);
|
||||
$boarding_id = get_bus_stop_id($f["board"],$f["service"]);
|
||||
$alight_id = get_bus_stop_id($f["alight"],$f["service"]);
|
||||
if ($boarding_id>0 && $alight_id>0 && $f["fare_raw"]>0) {
|
||||
if ($r && pg_num_rows($r) && $o=pg_fetch_assoc($r)) {
|
||||
// UP?
|
||||
if ($o["fare"]>0) {
|
||||
$q = "";
|
||||
} else {
|
||||
$q = "UPDATE SET singapore_bus_stop_fares SET fare=%s,distance=%s WHERE id=".$o["id"];
|
||||
}
|
||||
} else {
|
||||
$q = "INSERT INTO singapore_bus_stop_fares (boarding_id,alight_id,fare,distance) VALUES (";
|
||||
$q.= "${boarding_id},${alight_id},%d,%d)";
|
||||
}
|
||||
if ($q!="") {
|
||||
$d = $f["distance_raw"]>0?((int)(10*$f["distance_raw"])):$f["bdistance"];
|
||||
$q = sprintf($q,(int)$f["fare_raw"],$d);
|
||||
$r = pg_query($conn,$q);
|
||||
echo "q=${q}\n";
|
||||
} else {
|
||||
echo "Update is not required? fare=".$o["fare"]."\n";
|
||||
}
|
||||
} else {
|
||||
echo "ERROR: board(${boarding_id})='".$f["board"]."', alight(${alight_id})='".$f["alight"]."'\n";
|
||||
}
|
||||
}
|
||||
|
||||
function get_mrtlrt_stop_id($name) {
|
||||
global $readOnlyReplicaConn;
|
||||
$q = "select id from singapore_mrtlrt_stops_mytransport where name='${name}'";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) {
|
||||
return $f[0];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function get_bus_stop_id($str,$service) {
|
||||
global $readOnlyReplicaConn;
|
||||
echo "'${service}' => '${str}'\n";
|
||||
$line = substr($service,8);
|
||||
$pos = strpos($str,'-');
|
||||
if ($pos!==false) {
|
||||
$stop_code = trim(substr($str,0,$pos-1));
|
||||
$name = trim(substr($str,$pos+1));
|
||||
} else {
|
||||
$name = $str; // Will not work most likely...
|
||||
$stop_code = "";
|
||||
}
|
||||
$q = "select id from singapore_bus_stops where name='${name}' and stop_code='${stop_code}' and line='${line}'";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) {
|
||||
return $f[0];
|
||||
}
|
||||
$q = "select id from singapore_bus_stops where stop_code='${stop_code}' and line='${line}'";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) {
|
||||
return $f[0];
|
||||
}
|
||||
$q = "select id from singapore_bus_stops where name='${name}' and line='${line}'";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) {
|
||||
return $f[0];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
// sudo mkdir /run/php
|
||||
// sudo chmod a+rw /run/php
|
||||
|
||||
function lock_pid_file($fn=NULL) {
|
||||
if ($fn==NULL) {
|
||||
$fn = '/run/php/'.basename($_SERVER['PHP_SELF'], '.php').'.pid';
|
||||
}
|
||||
$lock_file = fopen($fn, 'c');
|
||||
$got_lock = flock($lock_file, LOCK_EX | LOCK_NB, $wouldblock);
|
||||
if ($lock_file === false || (!$got_lock && !$wouldblock)) {
|
||||
throw new Exception(
|
||||
"Unexpected error opening or locking lock file. Perhaps you " .
|
||||
"don't have permission to write to the lock file or its " .
|
||||
"containing directory?"
|
||||
);
|
||||
}
|
||||
else if (!$got_lock && $wouldblock) {
|
||||
exit("Another instance is already running; terminating.\n");
|
||||
}
|
||||
// Lock acquired; let's write our PID to the lock file for the convenience
|
||||
// of humans who may wish to terminate the script.
|
||||
ftruncate($lock_file, 0);
|
||||
fwrite($lock_file, getmypid() . "\n");
|
||||
|
||||
/*
|
||||
The main body of your script goes here.
|
||||
*/
|
||||
return $lock_file;
|
||||
}
|
||||
|
||||
function unlock_pid_file($lock_file) {
|
||||
// All done; we blank the PID file and explicitly release the lock
|
||||
// (although this should be unnecessary) before terminating.
|
||||
ftruncate($lock_file, 0);
|
||||
flock($lock_file, LOCK_UN);
|
||||
}
|
||||
|
||||
/*
|
||||
vi:ts=2
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,247 @@
|
||||
<?php
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] member_notification job is starting.\n";
|
||||
|
||||
require('../backend.php');
|
||||
|
||||
define('EMAIL_PENDING', 1);
|
||||
define('EMAIL_SENT', 5);
|
||||
|
||||
// We will not limit the SQL we will exhaust the allowed memory
|
||||
// we will process data in ${hard_limit} batches and hopefully catch up
|
||||
$hard_limit = 500000;
|
||||
// GPS coordinate precision to assume the same location
|
||||
$precision = 3;
|
||||
$tag_message = false;
|
||||
|
||||
$email_templates_dir = $savvyext->cfgReadChar('mailsend.templates_dir');
|
||||
$template_name = "DealTemplate.html"; // This is test template.
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
include 'notifications_functions.php';
|
||||
|
||||
function Fextension_call($in, &$out) {
|
||||
// logToFl("Merchant_Name count->" . $in["merchant_name"]);
|
||||
$in["pid"] = 100; // not used currenlty
|
||||
global $savvyext;
|
||||
$out = $savvyext->savvyext_api($in);
|
||||
$ret = $out["retval"];
|
||||
return $ret;
|
||||
}
|
||||
|
||||
//exit();
|
||||
|
||||
$mysql = "SELECT value FROM global_settings WHERE key='tag_notififaction' AND value='1'";
|
||||
$r = pg_query($readOnlyReplicaConn, $mysql);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
$tag_message = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
$mysql = "SELECT n.id AS notify_id,m.id AS m_id,m.email AS reciever_email, n.*, e.category, e.frequency, e.send_day, e.send_time
|
||||
FROM members_notification n LEFT JOIN members m ON m.id = n.member_id
|
||||
LEFT JOIN email_trigger e ON e.e_trigger = n.trigger_key
|
||||
WHERE n.status IN (" . EMAIL_PENDING . ")
|
||||
AND m.alert_notification = 1
|
||||
AND n.notice_type = 'INSTANT'
|
||||
ORDER BY n.ic ASC LIMIT 100";
|
||||
//AND m.id IN (SELECT member_id FROM test_accounts WHERE status=1)
|
||||
|
||||
|
||||
$r = pg_query($readOnlyReplicaConn, $mysql);
|
||||
|
||||
$acc = array();
|
||||
if ($r && pg_num_rows($r)) {
|
||||
|
||||
// Load Email template
|
||||
$htm_template = file_get_contents($email_templates_dir . "/" . $template_name);
|
||||
|
||||
while ($f = pg_fetch_assoc($r)) {
|
||||
$member_id = $f["member_id"];
|
||||
$notify_id = $f["notify_id"];
|
||||
$reciever_email = $f["reciever_email"];
|
||||
$notice_type = $f["notice_type"];
|
||||
$trigger_key = $f["trigger_key"];
|
||||
$category = $f["category"];
|
||||
$frequency_day = $f["frequency"];//num of days
|
||||
$send_day = $f["send_day"];
|
||||
$send_time = $f["send_time"];
|
||||
$current_day = strtolower(date('l', strtotime($date)));
|
||||
$current_hour = date("H:00:00");
|
||||
|
||||
$message = $f["msg"];
|
||||
|
||||
$extension_call = false;
|
||||
|
||||
$x["pid"] = 0;
|
||||
$x["member_id"] = $member_id;
|
||||
$x["notify_id"] = $notify_id;
|
||||
|
||||
$extension_call = true;
|
||||
|
||||
|
||||
$q_count = "UPDATE members_notification SET ic=ic+1 WHERE id = " . $notify_id;
|
||||
pg_query($conn, $q_count);
|
||||
|
||||
$approve_send = true;
|
||||
$send_count = 0;
|
||||
|
||||
if ( $notice_type == "INSTANT"){
|
||||
$approve_send = true; // send instant immediatley;
|
||||
}
|
||||
|
||||
if (false == $approve_send && $send_count < 4) {
|
||||
|
||||
}
|
||||
// ANY MESSAGE IN THE LAST 12 HOURS =====================MOVE TO A FUNCTION
|
||||
//
|
||||
//
|
||||
// SEND Notification if APPLICABLE
|
||||
$data = []; // reset the data
|
||||
|
||||
$q = "SELECT * FROM members_devices WHERE status =1 AND member_id=${member_id} ";
|
||||
//$r = $this->db->query($q);
|
||||
$r1 = pg_query($readOnlyReplicaConn, $q);
|
||||
while ($f1 = pg_fetch_assoc($r1)) {
|
||||
$data["devices"][] = $f1["player_id"]; //$row->player_id;
|
||||
$device_count++;
|
||||
}
|
||||
|
||||
//print_r( $data["devices"] );
|
||||
|
||||
if ( $notice_type == 'INSTANT' ) {
|
||||
$cat = $category; // "GOACTIVITY";
|
||||
generateCard($notify_id, $member_id, $cat);
|
||||
$arrayData = array("NEXTSCREEN" => $cat);
|
||||
if (true == $approve_send) {
|
||||
//upodate before sedning
|
||||
$q_sent = "UPDATE members_notification SET status = " . EMAIL_SENT . ",date_sent=now() WHERE id = " . $notify_id;
|
||||
pg_query($conn, $q_sent);
|
||||
sendmemberMessage($member_id, $data["devices"], $message, $arrayData, $tag_message);
|
||||
}
|
||||
}
|
||||
|
||||
if ($notice_type == 'EMAILALERT') {
|
||||
// sending email - IF APPLICABLE
|
||||
if ($reciever_email != '' && $htm_template) {
|
||||
$values = [
|
||||
"to_emails" => "{" . $reciever_email . "}",
|
||||
"subject" => "Float Deal",
|
||||
"html_body" => pg_escape_string($htm_template),
|
||||
"status" => "0",
|
||||
"created_at" => (new DateTime())->format('c'),
|
||||
"updated_at" => (new DateTime())->format('c')
|
||||
];
|
||||
|
||||
$values = array_filter($values, 'strlen');
|
||||
$q = "INSERT INTO emails ";
|
||||
$q .= " (" . implode(", ", array_keys($values)) . ")";
|
||||
$q .= " VALUES ('" . implode("', '", $values) . "') ";
|
||||
$rs = pg_query($conn, $q);
|
||||
if ($rs) {
|
||||
$q = "UPDATE members_notification SET status = " . EMAIL_SENT . " WHERE id = " . $notify_id;
|
||||
// $rs = pg_query($conn, $q);
|
||||
}
|
||||
}
|
||||
} // if EMAIl ALERT IS NEEDED
|
||||
// print_r($acc);
|
||||
}
|
||||
}
|
||||
|
||||
function sendmemberMessage($member_id, $player_id_array, $message, $arrayData, $tag_message = false) {
|
||||
$ic = 0;
|
||||
$player_id_string = "";
|
||||
// print_r($player_id_array);
|
||||
|
||||
if (is_array($player_id_array) && $message != "" && count($player_id_array) > 0 && is_array($arrayData)) {
|
||||
|
||||
if (true == $tag_message) {
|
||||
$message = $message . " - " . $member_id;
|
||||
}
|
||||
|
||||
$one_success = false;
|
||||
|
||||
foreach ($player_id_array as $pl) {
|
||||
$sprt = "";
|
||||
if ($pl != '') {
|
||||
$player_id_array = array($pl);
|
||||
$result = postOneSignal($player_id_array, $message, $arrayData);
|
||||
//var_dump($result);
|
||||
|
||||
// if result is true assign to one_success
|
||||
}
|
||||
}
|
||||
|
||||
// if one succeess, then call sendKochavaEvent
|
||||
|
||||
} else {
|
||||
echo "Invalid PLAYER_ID and/or MESSAGE!";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function sendKochavaEvent(){
|
||||
|
||||
// send data here
|
||||
|
||||
}
|
||||
|
||||
function postOneSignal($player_id_array, $message, $arrayData) {
|
||||
global $savvyext;
|
||||
// $url = $savvyext->cfgReadChar('onesignal.url');
|
||||
//echo $app_id = $savvyext->cfgReadChar('onesignal.app_id');
|
||||
|
||||
$url = "https://onesignal.com/api/v1/notifications";
|
||||
$app_id = "e9a7bb38-0a27-4250-9fb7-9bd7871d7b63";
|
||||
|
||||
|
||||
$data = [
|
||||
'app_id' => $app_id,
|
||||
'contents' => ['en' => $message],
|
||||
'headings' => ['en' => 'Float Activities'],
|
||||
'subtitle' => ['en' => 'Your account activities message from Float.'],
|
||||
'content_available' => true,
|
||||
'mutable_content' => true,
|
||||
'include_player_ids' => $player_id_array,
|
||||
'data' => $arrayData
|
||||
];
|
||||
$opts = array(
|
||||
'http' => array(
|
||||
'method' => "POST",
|
||||
'header' =>
|
||||
"Content-Type: application/json; charset=utf-8\r\n" .
|
||||
"Accept: application/json\r\n",
|
||||
'content' => json_encode($data)
|
||||
)
|
||||
);
|
||||
|
||||
// print_r($opts);
|
||||
// print_r($data);
|
||||
// echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n <br>";
|
||||
|
||||
$context = stream_context_create($opts);
|
||||
$body = file_get_contents($url, false, $context);
|
||||
error_log($body);
|
||||
$result = json_decode($body, true);
|
||||
return $result;
|
||||
}
|
||||
|
||||
pg_close($conn);
|
||||
pg_close($readOnlyReplicaConn);
|
||||
echo "[" . date("Y-m-d H:i:s") . "] member_notification job complete.\n";
|
||||
?>
|
||||
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] member_lifecyle_emails job is starting.\n";
|
||||
|
||||
require('../backend.php');
|
||||
|
||||
define('EMAIL_PENDING', 1);
|
||||
define('EMAIL_SENT', 5);
|
||||
|
||||
// We will not limit the SQL we will exhaust the allowed memory
|
||||
// we will process data in ${hard_limit} batches and hopefully catch up
|
||||
$hard_limit = 500000;
|
||||
// GPS coordinate precision to assume the same location
|
||||
$precision = 3;
|
||||
|
||||
echo $email_templates_dir = $savvyext->cfgReadChar('mailsend.templates_dir');
|
||||
$template_name = "How_it_works.html"; // This is test template.
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
|
||||
// send peding emsils
|
||||
$notice_type = 'EMAILALERT';
|
||||
//savvy=> SELECT l.id AS life_id,l.* FROM members_lifecycle_emails l LEFT JOIN members m ON m.id=l.member_id WHERE l.status = 1 ;
|
||||
// life_id | id | member_id | cycle_type | subject | status | added | completed
|
||||
|
||||
$mysql = "SELECT l.id AS life_id,l.*,m.email AS reciever_email FROM members_lifecycle_emails l LEFT JOIN members m ON m.id=l.member_id WHERE l.status = 1";
|
||||
$r0 = pg_query($readOnlyReplicaConn, $mysql);
|
||||
|
||||
if ($r0 && pg_num_rows($r0)) {
|
||||
|
||||
while ($f0 = pg_fetch_assoc($r0)) {
|
||||
$member_id = $f0["member_id"];
|
||||
$life_id = $f0["life_id"];
|
||||
$reciever_email = $f0["reciever_email"];
|
||||
$subject = $f0["subject"];
|
||||
|
||||
$qup = "UPDATE members_lifecycle_emails SET status = 4 WHERE id=$life_id";
|
||||
pg_query($conn, $qup);
|
||||
|
||||
|
||||
if ($notice_type == 'EMAILALERT') {
|
||||
|
||||
$htm_template = file_get_contents($email_templates_dir . "/lifecycle/" . $template_name); // note read evertime in case we need to change some parameters
|
||||
|
||||
if ($reciever_email != '' && $htm_template) {
|
||||
$values = [
|
||||
"to_emails" => "{" . $reciever_email . "}",
|
||||
"member_id" => "" . $member_id . "",
|
||||
"subject" => $subject,
|
||||
"html_body" => pg_escape_string($htm_template),
|
||||
"status" => "0",
|
||||
"created_at" => (new DateTime())->format('c'),
|
||||
"updated_at" => (new DateTime())->format('c')
|
||||
];
|
||||
|
||||
$values = array_filter($values, 'strlen');
|
||||
$q = "INSERT INTO emails ";
|
||||
$q .= " (" . implode(", ", array_keys($values)) . ")";
|
||||
$q .= " VALUES ('" . implode("', '", $values) . "') ";
|
||||
$rs = pg_query($conn, $q);
|
||||
if ($rs) {
|
||||
$q = "UPDATE members_lifecycle_emails SET status = " . EMAIL_SENT . ", completed=now() WHERE id = " . $life_id;
|
||||
$rs = pg_query($conn, $q);
|
||||
}
|
||||
}
|
||||
} // if EMAIl ALERT IS NEEDED
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//genedate new list of emails
|
||||
|
||||
$mysql = "SELECT *, id AS member_id FROM members WHERE id > 0 AND now() BETWEEN added+'1 minute' AND added+'2 day' AND id NOT IN (SELECT member_id FROM members_lifecycle_emails WHERE cycle_type ='HOWITWORKS' )";
|
||||
|
||||
// TEST echo
|
||||
//$mysql = "SELECT *, id AS member_id FROM members WHERE id < 5 AND id> 0 AND id NOT IN (SELECT member_id FROM members_lifecycle_emails WHERE cycle_type ='HOWITWORKS' ) ORDER BY id ASC";
|
||||
$r = pg_query($readOnlyReplicaConn, $mysql);
|
||||
|
||||
if ($r && pg_num_rows($r)) {
|
||||
|
||||
while ($f = pg_fetch_assoc($r)) {
|
||||
$member_id = $f["member_id"];
|
||||
|
||||
$values = [
|
||||
"member_id" => "" . $member_id . "",
|
||||
"subject" => "Float - How it Works",
|
||||
"cycle_type" => "HOWITWORKS"
|
||||
];
|
||||
|
||||
$values = array_filter($values, 'strlen');
|
||||
$q = "INSERT INTO members_lifecycle_emails ";
|
||||
$q .= " (" . implode(", ", array_keys($values)) . ")";
|
||||
echo $q .= " VALUES ('" . implode("', '", $values) . "') ";
|
||||
|
||||
|
||||
$rs = pg_query($conn, $q);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
* CREATE TABLE members_lifecycle_emails (
|
||||
id SERIAL,
|
||||
member_id INT REFERENCES members(id),
|
||||
cycle_type VARCHAR(15) NOT NULL REFERENCES email_cycle_types(cycle_type),
|
||||
subject VARCHAR(100),
|
||||
status integer DEFAULT 1,
|
||||
added timestamp without time zone DEFAULT now(),
|
||||
completed timestamp without time zone DEFAULT null
|
||||
);
|
||||
ALTER TABLE ONLY members_lifecycle_emails
|
||||
ADD CONSTRAINT members_lifecycle_emails_id_key UNIQUE (id);
|
||||
*/
|
||||
|
||||
pg_close($conn);
|
||||
pg_close($readOnlyReplicaConn);
|
||||
echo "[" . date("Y-m-d H:i:s") . "] member_lifecyle_emails job complete.\n";
|
||||
?>
|
||||
@@ -0,0 +1,292 @@
|
||||
<?php
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] member_notification job is starting.\n";
|
||||
|
||||
require('../backend.php');
|
||||
|
||||
define('EMAIL_PENDING', 1);
|
||||
define('EMAIL_SENT', 5);
|
||||
|
||||
// We will not limit the SQL we will exhaust the allowed memory
|
||||
// we will process data in ${hard_limit} batches and hopefully catch up
|
||||
$hard_limit = 500000;
|
||||
// GPS coordinate precision to assume the same location
|
||||
$precision = 3;
|
||||
$tag_message = false;
|
||||
|
||||
$email_templates_dir = $savvyext->cfgReadChar('mailsend.templates_dir');
|
||||
$template_name = "DealTemplate.html"; // This is test template.
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
include 'notifications_functions.php';
|
||||
|
||||
function Fextension_call($in, &$out) {
|
||||
// logToFl("Merchant_Name count->" . $in["merchant_name"]);
|
||||
$in["pid"] = 100; // not used currenlty
|
||||
global $savvyext;
|
||||
$out = $savvyext->savvyext_api($in);
|
||||
$ret = $out["retval"];
|
||||
return $ret;
|
||||
}
|
||||
|
||||
//exit();
|
||||
|
||||
$mysql = "SELECT value FROM global_settings WHERE key='tag_notififaction' AND value='1'";
|
||||
$r = pg_query($readOnlyReplicaConn, $mysql);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
$tag_message = true;
|
||||
}
|
||||
|
||||
//===================================================================================================================
|
||||
/*
|
||||
* DEACTIVATE 24 hours expired cards
|
||||
*/
|
||||
$mysql_expired_cards = "SELECT mc.id FROM members_card_assign mc "
|
||||
. "LEFT JOIN email_trigger et ON et.e_trigger=mc.trigger_key "
|
||||
. "WHERE mc.trigger_key IS NOT NULL "
|
||||
. "AND mc.status = 1 "
|
||||
. "AND et.expiration = 'EXP00002' "
|
||||
. "AND now() > mc.updated + '12 hours' LIMIT 500";
|
||||
|
||||
$mysql_del_list = "UPDATE members_card_assign SET status = 0 WHERE id IN ( $mysql_expired_cards ) AND trigger_key IS NOT NULL";
|
||||
pg_query($conn, $mysql_del_list); // REAL UPDATE TO CARD STATUS
|
||||
//======================================================================================================================
|
||||
|
||||
|
||||
|
||||
$mysql = "SELECT n.id AS notify_id,m.id AS m_id,m.email AS reciever_email, n.*, e.category, e.frequency, e.send_day, e.send_time
|
||||
FROM members_notification n LEFT JOIN members m ON m.id = n.member_id
|
||||
LEFT JOIN email_trigger e ON e.e_trigger = n.trigger_key
|
||||
WHERE n.status IN (" . EMAIL_PENDING . ")
|
||||
AND m.alert_notification = 1
|
||||
ORDER BY n.ic ASC LIMIT 100";
|
||||
//AND m.id IN (SELECT member_id FROM test_accounts WHERE status=1)
|
||||
|
||||
$r = pg_query($readOnlyReplicaConn, $mysql);
|
||||
|
||||
$acc = array();
|
||||
if ($r && pg_num_rows($r)) {
|
||||
|
||||
// Load Email template
|
||||
$htm_template = file_get_contents($email_templates_dir . "/" . $template_name);
|
||||
|
||||
while ($f = pg_fetch_assoc($r)) {
|
||||
$member_id = $f["member_id"];
|
||||
$notify_id = $f["notify_id"];
|
||||
$reciever_email = $f["reciever_email"];
|
||||
$notice_type = $f["notice_type"];
|
||||
$category = $f["category"];
|
||||
$trigger_key = $f["trigger_key"];
|
||||
$frequency_day = $f["frequency"];//num of days
|
||||
$send_day = $f["send_day"];
|
||||
$send_time = $f["send_time"];
|
||||
$current_day = strtolower(date('l'));//current day name
|
||||
$current_hour = date("H:00:00");
|
||||
|
||||
$message = $f["msg"];
|
||||
|
||||
$extension_call = false;
|
||||
|
||||
$x["pid"] = 0;
|
||||
$x["member_id"] = $member_id;
|
||||
$x["notify_id"] = $notify_id;
|
||||
|
||||
$extension_call = true;
|
||||
|
||||
|
||||
$q_count = "UPDATE members_notification SET ic=ic+1 WHERE id = " . $notify_id;
|
||||
pg_query($conn, $q_count);
|
||||
|
||||
$approve_send = true;
|
||||
$send_count = 0;
|
||||
|
||||
//CHECK FREQUENCY
|
||||
if(!empty($frequency_day) && !empty($send_day) && !empty($send_time)){
|
||||
$day_check = strtolower(date('l', strtotime(-$frequency_day." days")));
|
||||
if($day_check != $send_day){
|
||||
$approve_send = false;
|
||||
}
|
||||
if($send_time != $current_hour){
|
||||
$approve_send = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($notice_type == "INSTANT") {
|
||||
$approve_send = true; // send instant immediatley;
|
||||
} else {
|
||||
|
||||
// ANY MESSAGE IN THE LAST 12 HOURS =====================MOVE TO A FUNCTION
|
||||
$q_test = "SELECT count(id) AS send_count from members_notification WHERE member_id = $member_id AND status=5 AND date_sent IS NOT NULL AND now() < date_sent+'12 hour' AND trigger_key='".$trigger_key."'";
|
||||
$r0 = pg_query($readOnlyReplicaConn, $q_test);
|
||||
if ($r0 && pg_num_rows($r0) > 0) {
|
||||
$f0 = pg_fetch_assoc($r0);
|
||||
$send_count = $f0["send_count"];
|
||||
if ($send_count > 0) {
|
||||
$approve_send = false;
|
||||
}
|
||||
}
|
||||
if(!empty($frequency_day)){
|
||||
$q_test = "SELECT count(id) AS send_count from members_notification WHERE member_id = $member_id AND status=5 AND date_sent IS NOT NULL AND now() < date_sent+'".$frequency_day." days' AND trigger_key='".$trigger_key."'";
|
||||
$r0 = pg_query($readOnlyReplicaConn, $q_test);
|
||||
if ($r0 && pg_num_rows($r0) > 0) {
|
||||
$f0 = pg_fetch_assoc($r0);
|
||||
$send_count = $f0["send_count"];
|
||||
if ($send_count > 0) {
|
||||
$approve_send = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (false == $approve_send && $send_count < 4) {
|
||||
|
||||
}
|
||||
// ANY MESSAGE IN THE LAST 12 HOURS =====================MOVE TO A FUNCTION
|
||||
//
|
||||
//
|
||||
// SEND Notification if APPLICABLE
|
||||
$data = []; // reset the data
|
||||
|
||||
$q = "SELECT * FROM members_devices WHERE status =1 AND member_id=${member_id} ";
|
||||
//$r = $this->db->query($q);
|
||||
$r1 = pg_query($readOnlyReplicaConn, $q);
|
||||
while ($f1 = pg_fetch_assoc($r1)) {
|
||||
$data["devices"][] = $f1["player_id"]; //$row->player_id;
|
||||
$device_count++;
|
||||
}
|
||||
|
||||
//print_r( $data["devices"] );
|
||||
// Let take a look at the last time the user get this trigger - see if we need to span the message
|
||||
|
||||
if ($notice_type == 'GENALERT' || $notice_type == 'INSTANT') {
|
||||
$cat = $category; // "GOACTIVITY";
|
||||
generateCard($notify_id, $member_id, $cat);
|
||||
$arrayData = array("NEXTSCREEN" => $cat);
|
||||
if (true == $approve_send) {
|
||||
//upodate before sedning
|
||||
$q_sent = "UPDATE members_notification SET status = " . EMAIL_SENT . ",date_sent=now() WHERE id = " . $notify_id;
|
||||
pg_query($conn, $q_sent);
|
||||
sendmemberMessage($member_id, $data["devices"], $message, $arrayData, $tag_message);
|
||||
}
|
||||
}
|
||||
|
||||
if ($notice_type == 'EMAILALERT') {
|
||||
// sending email - IF APPLICABLE
|
||||
if ($reciever_email != '' && $htm_template) {
|
||||
$values = [
|
||||
"to_emails" => "{" . $reciever_email . "}",
|
||||
"subject" => "Float Deal",
|
||||
"html_body" => pg_escape_string($htm_template),
|
||||
"status" => "0",
|
||||
"created_at" => (new DateTime())->format('c'),
|
||||
"updated_at" => (new DateTime())->format('c')
|
||||
];
|
||||
|
||||
$values = array_filter($values, 'strlen');
|
||||
$q = "INSERT INTO emails ";
|
||||
$q .= " (" . implode(", ", array_keys($values)) . ")";
|
||||
$q .= " VALUES ('" . implode("', '", $values) . "') ";
|
||||
$rs = pg_query($conn, $q);
|
||||
if ($rs) {
|
||||
$q = "UPDATE members_notification SET status = " . EMAIL_SENT . " WHERE id = " . $notify_id;
|
||||
// $rs = pg_query($conn, $q);
|
||||
}
|
||||
}
|
||||
} // if EMAIl ALERT IS NEEDED
|
||||
// print_r($acc);
|
||||
}
|
||||
}
|
||||
|
||||
function sendmemberMessage($member_id, $player_id_array, $message, $arrayData, $tag_message = false) {
|
||||
$ic = 0;
|
||||
$player_id_string = "";
|
||||
// print_r($player_id_array);
|
||||
|
||||
if (is_array($player_id_array) && $message != "" && count($player_id_array) > 0 && is_array($arrayData)) {
|
||||
|
||||
if (true == $tag_message) {
|
||||
$message = $message . " - " . $member_id;
|
||||
}
|
||||
|
||||
$one_success = false;
|
||||
|
||||
foreach ($player_id_array as $pl) {
|
||||
$sprt = "";
|
||||
if ($pl != '') {
|
||||
$player_id_array = array($pl);
|
||||
$result = postOneSignal($player_id_array, $message, $arrayData);
|
||||
//var_dump($result);
|
||||
// if result is true assign to one_success
|
||||
}
|
||||
}
|
||||
|
||||
// if one succeess, then call sendKochavaEvent
|
||||
} else {
|
||||
echo "Invalid PLAYER_ID and/or MESSAGE!";
|
||||
}
|
||||
}
|
||||
|
||||
function sendKochavaEvent() {
|
||||
|
||||
// send data here
|
||||
}
|
||||
|
||||
function postOneSignal($player_id_array, $message, $arrayData) {
|
||||
global $savvyext;
|
||||
// $url = $savvyext->cfgReadChar('onesignal.url');
|
||||
//echo $app_id = $savvyext->cfgReadChar('onesignal.app_id');
|
||||
|
||||
$url = "https://onesignal.com/api/v1/notifications";
|
||||
$app_id = "e9a7bb38-0a27-4250-9fb7-9bd7871d7b63";
|
||||
|
||||
|
||||
$data = [
|
||||
'app_id' => $app_id,
|
||||
'contents' => ['en' => $message],
|
||||
'headings' => ['en' => 'Float Activities'],
|
||||
'subtitle' => ['en' => 'Your account activities message from Float.'],
|
||||
'content_available' => true,
|
||||
'mutable_content' => true,
|
||||
'include_player_ids' => $player_id_array,
|
||||
'data' => $arrayData
|
||||
];
|
||||
$opts = array(
|
||||
'http' => array(
|
||||
'method' => "POST",
|
||||
'header' =>
|
||||
"Content-Type: application/json; charset=utf-8\r\n" .
|
||||
"Accept: application/json\r\n",
|
||||
'content' => json_encode($data)
|
||||
)
|
||||
);
|
||||
|
||||
// print_r($opts);
|
||||
// print_r($data);
|
||||
// echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n <br>";
|
||||
|
||||
$context = stream_context_create($opts);
|
||||
$body = file_get_contents($url, false, $context);
|
||||
error_log($body);
|
||||
$result = json_decode($body, true);
|
||||
return $result;
|
||||
}
|
||||
|
||||
pg_close($conn);
|
||||
pg_close($readOnlyReplicaConn);
|
||||
echo "[" . date("Y-m-d H:i:s") . "] member_notification job complete.\n";
|
||||
?>
|
||||
@@ -0,0 +1,510 @@
|
||||
<?php
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] member_prepare_notification job is starting.\n";
|
||||
|
||||
require('../backend.php');
|
||||
|
||||
|
||||
// We will not limit the SQL we will exhaust the allowed memory
|
||||
// we will process data in ${hard_limit} batches and hopefully catch up
|
||||
$hard_limit = 500000;
|
||||
// GPS coordinate precision to assume the same location
|
||||
$precision = 3;
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
include 'notifications_functions.php';
|
||||
|
||||
/*
|
||||
LEFT us refesh the triggertable
|
||||
*/
|
||||
|
||||
foreach ($trigger_query AS $key => $lrow) {
|
||||
$system_id = $key;
|
||||
$mysql = $lrow["query"];
|
||||
$message = $lrow["message"];
|
||||
$active = $lrow["active"];
|
||||
$category = $lrow["cat"];
|
||||
$dynamic_key = $lrow["dynamic_key"];
|
||||
|
||||
$send_mail = $lrow["send_mail"];
|
||||
$send_notification = $lrow["send_notification"];
|
||||
$icon = $lrow["icon"];
|
||||
|
||||
|
||||
|
||||
$sq2 = "SELECT * FROM email_trigger WHERE e_trigger='$system_id'";
|
||||
$r2 = pg_query($readOnlyReplicaConn, $sq2);
|
||||
if ($r2 && pg_num_rows($r2) == 0) {
|
||||
|
||||
$template_name = trim(strtolower($system_id . ".html"));
|
||||
$values = [
|
||||
"e_trigger" => "" . $system_id . "",
|
||||
"category" => "" . $category . "",
|
||||
"message" => pg_escape_string($message),
|
||||
"action_detail" => pg_escape_string($message),
|
||||
"template_name" => $template_name,
|
||||
"dynamic_key" => $dynamic_key,
|
||||
"status" => $active,
|
||||
"override_text" => "1",
|
||||
"expiration" => "EXP00000",
|
||||
"icon" => $icon,
|
||||
];
|
||||
|
||||
$values = array_filter($values, 'strlen');
|
||||
$q = "INSERT INTO email_trigger ";
|
||||
$q .= " (" . implode(", ", array_keys($values)) . ")";
|
||||
$q .= " VALUES ('" . implode("', '", $values) . "') ";
|
||||
// echo $q;
|
||||
$rs = pg_query($conn, $q);
|
||||
} else {
|
||||
$template_name = trim(strtolower($system_id . ".html"));
|
||||
/* $values = [
|
||||
"category" => "" . $category . "",
|
||||
"message" => pg_escape_string($message),
|
||||
"template_name" => $template_name,
|
||||
"dynamic_key" => $dynamic_key,
|
||||
"send_mail" => $send_mail,
|
||||
"send_notification" => $send_notification,
|
||||
"status" => $active
|
||||
];
|
||||
*/
|
||||
$values = [
|
||||
"message" => pg_escape_string($message),
|
||||
"template_name" => $template_name,
|
||||
"dynamic_key" => $dynamic_key
|
||||
];
|
||||
|
||||
//echo "jcjcjcjcjjcc";
|
||||
$msqUpdt = "";
|
||||
$ick = 0;
|
||||
foreach ($values as $key => $val) {
|
||||
if ($ick > 0) {
|
||||
$msqUpdt .= ",";
|
||||
}
|
||||
$msqUpdt .= " $key = '" . $val . "'";
|
||||
$ick++;
|
||||
}
|
||||
|
||||
if ($ick > 0) {
|
||||
|
||||
$q = "UPDATE email_trigger SET " . $msqUpdt;
|
||||
$q .= " WHERE e_trigger ='$system_id' ";
|
||||
|
||||
// do not update all
|
||||
// echo $q;
|
||||
// $rs = pg_query($conn, $q);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------ATTEND TO THE CAR POOL NOTIFIFICATION ETRG0020 ----------------------------------------
|
||||
/* savvy=> SELECT * FROM members_trips WHERE member_id =1 LIMIT 1;
|
||||
id | member_id | trip_name | trip_from | trip_to | country | trip_date | status | added | color
|
||||
----+-----------+------------+---------------------------------------------+-------------------------------------+---------+---------------------+--------+----------------------------+--------
|
||||
1 | 1 | Trip 62236 | 4201 Defoors Fram Trail, Powder Springs, GA | 3500 Riverwood parkway, Atlanta, GA | US | 2019-12-12 11:30:00 | 1 | 2019-12-16 00:10:33.354752 | 6464e2
|
||||
(1 row)
|
||||
*/
|
||||
|
||||
$mysql_trip = "SELECT id AS trip_id, * FROM members_trips WHERE member_id > 0 AND now()+'15 minutes' < trip_date AND trip_date > now()+ '-30 minutes' AND notify = 0 LIMIT 10";
|
||||
|
||||
$r = pg_query($conn, $mysql_trip);
|
||||
|
||||
$acc = array();
|
||||
if ($r && pg_num_rows($r)) {
|
||||
|
||||
while ($f = pg_fetch_assoc($r)) {
|
||||
$member_id = $f["member_id"];
|
||||
$trip_id = $f["trip_id"];
|
||||
|
||||
$trip_from = $f["trip_from"];
|
||||
$trip_to = $f["trip_to"];
|
||||
$trip_date = $f["trip_date"];
|
||||
$trip_name = $f["trip_name"];
|
||||
|
||||
$sql_up = "UPDATE members_trips SET notify =notify + 1 WHERE id = $trip_id AND member_id = $member_id ";
|
||||
pg_query($conn, $sql_up);
|
||||
|
||||
$extension_call = true;
|
||||
if ($extension_call == true) {
|
||||
$outX = array();
|
||||
$x = array();
|
||||
//$member_id = 1;
|
||||
$x["pid"] = 0;
|
||||
$x["member_id"] = $member_id;
|
||||
$x["notice_type"] = "INSTANT";
|
||||
$x["mmode"] = "AUTO";
|
||||
$x["trigger_key"] = "ETRG0020";
|
||||
$x["msg"] = "You have an upcoming trip $trip_name today at $trip_date to $trip_to";
|
||||
$x["action"] = FLOAT_SYSTEM_CREATE_NOTIFICATION;
|
||||
//print_r($x);
|
||||
Fextension_call($x, $outX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------- ----------------------------------------
|
||||
/*
|
||||
*
|
||||
* "ETRG0007" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget,(ma.spend_14 - 2*ma.spend_7) AS week_increase from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE m.decision_group IN('A1NUS25','USSF001') AND m.id NOT IN (SELECT member_id FROM members_carpool) ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "Deal Carpool Try carpooling and save $X and Y emissions this month",
|
||||
* "html_body" => pg_escape_string($htm_template),
|
||||
|
||||
savvy=> select * from email_trigger;
|
||||
id | e_trigger | category | action_detail | template_name | status | added | updated
|
||||
----+-----------+------------+------------------------------------------+-----------------+--------+----------------------------+----------------------------
|
||||
2 | ETRG0002 | GOACTIVITY | Put Details Here | dealtmp022.html | 1 | 2020-02-18 15:06:46.721542 | 2020-02-18 15:06:46.721542
|
||||
3 | ETRG0003 | GOACTIVITY | Put Details Here | dealtmp033.html | 1 | 2020-02-18 15:06:46.725502 | 2020-02-18 15:06:46.725502
|
||||
4 | ETRG0004 | GOACTIVITY | Put Details Here | dealtmp044.html | 1 | 2020-02-18 15:06:46.729315 | 2020-02-18 15:06:46.729315
|
||||
5 | ETRG0005 | GOACTIVITY | Put Details Here | dealtmp055.html | 1 | 2020-02-18 15:06:46.733011 | 2020-02-18 15:06:46.733011
|
||||
1 | ETRG0001 | GOACTIVITY | <p><strong>Put Details Here</strong></p>+| dealtmp011.html | 1 | 2020-02-18 15:06:46.716103 | 2020-02-18 15:06:46.716103
|
||||
| | | | | | |
|
||||
(5 rows)
|
||||
|
||||
|
||||
$trigger_query = array(
|
||||
"SURGESAVE" => array(
|
||||
"query" => $mysql,
|
||||
"message" => "You are spending too much. Let's save money",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "",
|
||||
"start_save" => false
|
||||
),
|
||||
*/
|
||||
|
||||
function Fextension_call($in, &$out) {
|
||||
// logToFl("Merchant_Name count->" . $in["merchant_name"]);
|
||||
global $savvyext;
|
||||
$out = $savvyext->savvyext_api($in);
|
||||
$ret = $out["retval"];
|
||||
return $ret;
|
||||
}
|
||||
|
||||
// clear out the expired list first
|
||||
$sq2 = "UPDATE members_notification SET status =2 WHERE status = 1 AND expire < now() AND notice_type!='INSTANT'";
|
||||
$r2 = pg_query($conn, $sq2);
|
||||
|
||||
|
||||
|
||||
foreach ($trigger_query AS $key => $lrow) {
|
||||
$system_id = $key;
|
||||
$mysql = $lrow["query"];
|
||||
$message = $lrow["message"];
|
||||
$active = $lrow["active"];
|
||||
$extension_call = $lrow["start_save"];
|
||||
|
||||
if (1 == $active && $system_id != '') {
|
||||
// echo $system_id. " - <hr> - ".$mysql;
|
||||
$mysql_up = "UPDATE email_trigger SET last_run = now() WHERE e_trigger = '$system_id'";
|
||||
pg_query($conn, $mysql_up);
|
||||
|
||||
$r = pg_query($conn, $mysql);
|
||||
|
||||
$acc = array();
|
||||
if ($r && pg_num_rows($r)) {
|
||||
// echo $system_id. " - <hr> - ".$mysql;
|
||||
// echo 'ddhdhdhd';
|
||||
while ($f = pg_fetch_assoc($r)) {
|
||||
$member_id = $f["member_id"];
|
||||
|
||||
$extension_call = false; // does not matter - dontset to send by =default.
|
||||
if (array_key_exists($member_id, $acc)) {
|
||||
// echo "here " . $member_id;
|
||||
// nothing - we dont want duplicate
|
||||
} else {
|
||||
|
||||
$sq2 = "SELECT * FROM members_notification WHERE member_id=$member_id AND trigger_key ='$system_id' AND status IN (1)";
|
||||
$r2 = pg_query($readOnlyReplicaConn, $sq2);
|
||||
$x["pid"] = 0;
|
||||
$x["member_id"] = $member_id;
|
||||
$x["notice_type"] = "GENALERT";
|
||||
$acc[$member_id] = $member_id;
|
||||
if ($r2 && pg_num_rows($r2) == 0) {
|
||||
$x["msg"] = $message;
|
||||
$extension_call = true;
|
||||
// modify the message here
|
||||
|
||||
|
||||
if ($system_id == "SURGESAVE") {
|
||||
$extension_call = false; // turn message off
|
||||
// print_r($x);
|
||||
if ($f["surge_price"] > 0 && $f["cheaper_alternative"] > 0) {
|
||||
$x["msg"] = "We have found a way to save time and money for you";
|
||||
}
|
||||
|
||||
if ($f["surge_price"] > 0 && $f["cheaper_alternative"] == 0) {
|
||||
$x["msg"] = "We have found a way to save time for you";
|
||||
}
|
||||
$extension_call = true;
|
||||
}
|
||||
|
||||
if ($system_id == "ETRG0002") {
|
||||
$percent_less = 100 - ($f["spend_7"] / $f["min_budget"]) * 100;
|
||||
$x["msg"] = "Good Job, you're " . round($percent_less, 2) . "% below your budget. Let's save more.";
|
||||
}
|
||||
|
||||
if ($system_id == "ETRG0004") {
|
||||
$rideshare_30 = $f["rideshare_30"] * 0.01;
|
||||
$extension_call = false; // turn message off
|
||||
if ($rideshare_30 > 0) {
|
||||
$x["msg"] = "We can see you spent $ $rideshare_30 on rideshare this month. Here's how Float can save you money";
|
||||
$extension_call = true; // turn message off
|
||||
}
|
||||
}
|
||||
|
||||
if ($system_id == "ETRG0005") {
|
||||
$extension_call = false;
|
||||
$x["msg"] = getAccountBenefit($readOnlyReplicaConn, $member_id, $extension_confirm_call);
|
||||
if ($x["msg"] != '' && $extension_confirm_call == true) {
|
||||
$extension_call = $extension_confirm_call;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($system_id == "ETRG0006") {
|
||||
$percent_increase = round($f["week_increase"] / $f["spend_7"]) * 100;
|
||||
$extension_call = false;
|
||||
if ($percent_increase > 0) {
|
||||
$x["msg"] = "Your spending is up $percent_increase% this week. Would you like to create a budget?";
|
||||
$extension_call = true; // turn message off
|
||||
}
|
||||
}
|
||||
|
||||
if ($system_id == "ETRG0007") {
|
||||
//$percent_increase = round($f["week_increase"] / $f["spend_7"], 2) * 100;
|
||||
$extension_call = false; // turn message off
|
||||
$emmission_save = rand(100, 200);
|
||||
$emmission_value = rand(100, 200);
|
||||
$country = $f["country"];
|
||||
|
||||
$week_increase = $f["week_increase"] * 0.01;
|
||||
if ($week_increase > 0) {
|
||||
|
||||
$emmission_save = round($week_increase, 2);
|
||||
$emisson = getEmissionModel($week_increase, 1, $country);
|
||||
$emmission_value = round($emisson[0], 2);
|
||||
|
||||
$x["msg"] = "Try carpooling and save $$emmission_save and $emmission_value grams of emissions this month";
|
||||
$extension_call = true;
|
||||
}
|
||||
|
||||
//"Your spending is up $percent_increase% this week. Let's create a budget together";
|
||||
}
|
||||
|
||||
if ($system_id == "ETRG0014") {
|
||||
$extension_call = false; // turn message off
|
||||
/*
|
||||
id | member_id | updated | spend_7 | rideshare_30 | spend_14 | gas_7 | gas_30 | gas_14 | min_budget | week_increase
|
||||
-----+-----------+----------------------------+---------+--------------+----------+-------+--------+--------+------------+---------------
|
||||
191 | 202 | 2020-05-06 11:20:04.339684 | 92989 | 75433 | 162604 | 42949 | 174047 | 77361 | 27500 | 23374
|
||||
117 | 76 | 2020-05-06 11:05:05.830233 | 1995 | 0 | 1995 | 0 | 0 | 0 | 0 | 1995
|
||||
*/
|
||||
$week_increase = $f["week_increase"] * 0.01;
|
||||
|
||||
if ($week_increase >= 20) {
|
||||
$emmission_inc = emissonIncrease($member_id, 7);
|
||||
if ($emmission_inc > 0) {
|
||||
$x["msg"] = "Your emissions output is $emmission_inc% higher this week, lets see how we can lower it";
|
||||
$extension_call = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($system_id == "ETRG0015") {
|
||||
$extension_call = false; // turn message off
|
||||
/*
|
||||
id | member_id | updated | spend_7 | rideshare_30 | spend_14 | gas_7 | gas_30 | gas_14 | min_budget | week_decrease
|
||||
-----+-----------+----------------------------+---------+--------------+----------+-------+--------+--------+------------+---------------
|
||||
194 | 186 | 2020-04-28 17:45:03.507661 | 172933 | 116230 | 315990 | 66650 | 215045 | 128172 | 0 | 29876
|
||||
*/
|
||||
$week_decrease = $f["week_decrease"] * 0.01;
|
||||
|
||||
if ($week_decrease >= 20) {
|
||||
$less_minutes = getTripMinutes($member_id, 7);
|
||||
if ($less_minutes > 0) {
|
||||
$x["msg"] = "Hurray, you have spent $less_minutes minutes less on the road this week.";
|
||||
$extension_call = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($system_id == "ETRG0019") {
|
||||
$extension_call = false; // this is managed by another automation
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pg_query($conn, "UPDATE members SET notification_test = now()+'1 day' WHERE id = $member_id");
|
||||
|
||||
if ($extension_call == true) {
|
||||
$outX = array();
|
||||
$x["mmode"] = "AUTO";
|
||||
$x["trigger_key"] = $system_id;
|
||||
$x["action"] = FLOAT_SYSTEM_CREATE_NOTIFICATION;
|
||||
print_r($x);
|
||||
Fextension_call($x, $outX);
|
||||
}
|
||||
// print_r($acc);
|
||||
}
|
||||
}
|
||||
} // end if active
|
||||
}
|
||||
exit();
|
||||
|
||||
function emissonIncrease($member_id, $days_gap) {
|
||||
|
||||
$emmission_inc = rand(0, 28);
|
||||
return $emmission_inc;
|
||||
}
|
||||
|
||||
function getTripMinutes($member_id, $days_gap) {
|
||||
|
||||
$less_minutes = rand(12, 99);
|
||||
return $less_minutes;
|
||||
}
|
||||
|
||||
function getEmissionModel($gas_amount, $gas_number, $gas_country = 'US') {
|
||||
|
||||
// GAS MODEL ASSUMPTIONS
|
||||
|
||||
$average_car_CO2_emissions = 168;
|
||||
$average_distance_travelled_pre_litre_of_petrol_km = 13;
|
||||
$average_price_per_litre_USD = 1.07;
|
||||
if ('SG' == $gas_country) {
|
||||
$average_price_per_litre_USD = 1.39;
|
||||
}
|
||||
|
||||
|
||||
$estimated_litres_of_fuel_purchased_litres = $gas_amount / $average_price_per_litre_USD;
|
||||
$estimated_distance_travelled_per_re_fuel_km = $estimated_litres_of_fuel_purchased_litres * $average_distance_travelled_pre_litre_of_petrol_km;
|
||||
|
||||
$estimated_total_CO2_emissions_per_refuel = $estimated_distance_travelled_per_re_fuel_km * $average_car_CO2_emissions;
|
||||
$estimated_CO2_emissions_per_month = $estimated_total_CO2_emissions_per_refuel * $gas_number;
|
||||
$estimated_CO2_emissions_per_week = $estimated_CO2_emissions_per_month * 12 / 52;
|
||||
|
||||
|
||||
$data = [];
|
||||
|
||||
$data[0] = $estimated_total_CO2_emissions_per_refuel;
|
||||
$data[1] = $estimated_CO2_emissions_per_month;
|
||||
$data[2] = $estimated_CO2_emissions_per_week;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
function getAccountBenefit($conn, $member_id, &$extension_confirm_call) {
|
||||
$msg_text = "";
|
||||
$extension_confirm_call = false;
|
||||
// $msql = "SELECT b.id AS bank_id,ccb.benefit from members_bank_accounts mb LEFT JOIN banks b ON b.bank_name = mb.bank_name LEFT JOIN credit_card_benefits ccb ON ccb.credit_card_id = b.id WHERE mb.member_id = $member_id AND ccb.benefit IS NOT NULL LIMIT 1";
|
||||
$myqsl = "SELECT b.id AS bank_id,ccb.benefit from members_bank_accounts mb "
|
||||
. " LEFT JOIN credit_cards b ON b.card_name= mb.description "
|
||||
. " LEFT JOIN credit_card_benefits ccb ON ccb.credit_card_id = b.id "
|
||||
. " WHERE mb.member_id = $member_id AND ccb.benefit IS NOT NULL "
|
||||
. " ORDER BY random() LIMIT 1";
|
||||
$r2 = pg_query($conn, $myqsl);
|
||||
if ($r2 && pg_num_rows($r2) > 0) {
|
||||
|
||||
while ($row = pg_fetch_row($r2)) {
|
||||
$msg_text = $row[1];
|
||||
// echo 'HERE 22222->' . $msg_text;
|
||||
$extension_confirm_call = true;
|
||||
}
|
||||
}
|
||||
return $msg_text;
|
||||
}
|
||||
|
||||
$r = pg_query($conn, $mysql);
|
||||
$acc = array();
|
||||
if ($r && pg_num_rows($r)) {
|
||||
// echo 'ddhdhdhd';
|
||||
while ($f = pg_fetch_assoc($r)) {
|
||||
$member_id = $f["member_id"];
|
||||
|
||||
$extension_call = false;
|
||||
if (array_key_exists($member_id, $acc)) {
|
||||
// echo "here " . $member_id;
|
||||
// nothing - we dont want duplicate
|
||||
} else {
|
||||
|
||||
$sq2 = "SELECT * FROM members_notification WHERE member_id=$member_id AND status IN (1)";
|
||||
$r2 = pg_query($readOnlyReplicaConn, $sq2);
|
||||
$x["pid"] = 0;
|
||||
$x["member_id"] = $member_id;
|
||||
$x["notice_type"] = "GENALERT";
|
||||
$acc[$member_id] = $member_id;
|
||||
if ($r2 && pg_num_rows($r2) == 0) {
|
||||
$x["msg"] = "We have found a way to save time for you";
|
||||
|
||||
|
||||
// print_r($x);
|
||||
if ($f["surge_price"] > 0 && $f["cheaper_alternative"] > 0) {
|
||||
$x["msg"] = "We have found a way to save time and money for you";
|
||||
}
|
||||
|
||||
if ($f["surge_price"] > 0 && $f["cheaper_alternative"] == 0) {
|
||||
$x["msg"] = "We have found a way to save time for you";
|
||||
}
|
||||
|
||||
$extension_call = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($extension_call == true) {
|
||||
$outX = array();
|
||||
$x["mmode"] = "AUTO";
|
||||
$x["action"] = FLOAT_SYSTEM_CREATE_NOTIFICATION;
|
||||
// Fextension_call($x, $outX);
|
||||
}
|
||||
print_r($acc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
$q = "SELECT * FROM members_notification WHERE status = 1 LIMIT 5";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
while ($f = pg_fetch_row($r)) {
|
||||
$member_id = $f[0];
|
||||
echo "[" . date("Y-m-d H:i:s") . "] Processing member_id=" . $member_id . " (total member records: " . $f[1] . ")\n";
|
||||
//if ($f[0]==22) continue; // Crash!
|
||||
// $p = processMemberGPSDataPartition($member_id);
|
||||
echo "[" . date("Y-m-d H:i:s") . "] Processed member_id=" . $member_id . " (processed records: " . $p . ")\n";
|
||||
}
|
||||
}
|
||||
|
||||
function processMemberGPSDataPartition($member_id) {
|
||||
global $conn, $precision, $hard_limit;
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
pg_close($conn);
|
||||
pg_close($readOnlyReplicaConn);
|
||||
echo "[" . date("Y-m-d H:i:s") . "] member_prepare_notification job complete.\n";
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] GPS member_tracking_duration job is starting.\n";
|
||||
|
||||
require('../backend.php');
|
||||
|
||||
// We will not limit the SQL we will exhaust the allowed memory
|
||||
// we will process data in ${hard_limit} batches and hopefully catch up
|
||||
$hard_limit = 500000;
|
||||
// GPS coordinate precision to assume the same location
|
||||
$precision = 3;
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('gpsdatabase.host');
|
||||
$db_name = $savvyext->cfgReadChar('gpsdatabase.name');
|
||||
$db_user = $savvyext->cfgReadChar('gpsdatabase.user');
|
||||
$db_pass = $savvyext->cfgReadChar('gpsdatabase.pass');
|
||||
$db_port = $savvyext->cfgReadLong('gpsdatabase.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
|
||||
$q = "select member_id,count(*) from members_tracking group by member_id";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
while ($f=pg_fetch_row($r)) {
|
||||
$member_id = $f[0];
|
||||
echo "[".date("Y-m-d H:i:s")."] Processing member_id=".$member_id." (total member records: ".$f[1].")\n";
|
||||
//if ($f[0]==22) continue; // Crash!
|
||||
$p = processMemberGPSDataPartition($member_id);
|
||||
echo "[".date("Y-m-d H:i:s")."] Processed member_id=".$member_id." (processed records: ".$p.")\n";
|
||||
}
|
||||
}
|
||||
|
||||
function processMemberGPSDataPartition($member_id) {
|
||||
global $conn,$precision,$hard_limit,$readOnlyReplicaConn;
|
||||
echo "[".date("Y-m-d H:i:s")."] processMemberGPSDataPartition($member_id)\n";
|
||||
$id = 0;
|
||||
$q = 'select max(last_id) from members_tracking_duration where member_id=' . $member_id;
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) {
|
||||
$id = (int)$f[0];
|
||||
}
|
||||
echo "[".date("Y-m-d H:i:s")."] Last processed ID is ${id}\n";
|
||||
/*
|
||||
0 - id
|
||||
1 - lat
|
||||
2 - lng
|
||||
3 - ttime
|
||||
4 - member_id
|
||||
5 - device_id
|
||||
6 - gps
|
||||
*/
|
||||
$q = "select id,round(lat,${precision}) as lat,round(lng,${precision}) as lng,ttime,member_id,device_id,gps ";
|
||||
$q.= " from members_tracking where id>${id} ";
|
||||
$q.= " and member_id=".$member_id;
|
||||
$q.= " order by member_id,device_id,ttime limit ${hard_limit}";
|
||||
echo "\n$q\n";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
|
||||
if ($r && pg_num_rows($r)) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Records to process: ".pg_num_rows($r)."\n";
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] No new records to process. Stop.\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] Processing";
|
||||
$first_data = NULL;
|
||||
$last_data = NULL;
|
||||
$pool_data = [];
|
||||
$processed = 0;
|
||||
while ($f=pg_fetch_row($r)) {
|
||||
//echo ".";
|
||||
if ($last_data!=NULL) {
|
||||
// member id
|
||||
if ($last_data[4]!=$f[4] || $last_data[5]!=$f[5] || // device_id
|
||||
$last_data[1]!=$f[1] || $last_data[2]!=$f[2]) { // gps coordinates
|
||||
// Process
|
||||
$clear_data = [];
|
||||
foreach ($pool_data as $id) {
|
||||
if ($id!=$first_data[0] && $id!=$last_data[0]) {
|
||||
$clear_data[] = $id;
|
||||
}
|
||||
}
|
||||
$first = $clear_data[0] ?? $first_data;
|
||||
$n = count($pool_data);
|
||||
$last = array_pop($pool_data) ?? $last_data;
|
||||
$q = "INSERT INTO members_tracking_duration (member_id,lat,lng,gps,first_id,last_id,first_time,last_time,duration,device_id,inner_duration,total) VALUES(";
|
||||
$q.= $last_data[4].",".$last_data[1].",".$last_data[2].","; // member_id,lat,lng
|
||||
$q.= "ST_SetSRID(ST_MakePoint(".$last_data[1].",".$last_data[2]."), 4326)::geography"; // GPS
|
||||
$q.= ",".$first_data[0].",".$last_data[0].",'".$first_data[3]."','".$last_data[3]."',"; // fist_id,last_id,first_time,last_time,duration
|
||||
$q.= "'".$last_data[3]."'::timestamp - '".$first_data[3]."'::timestamp,".($f[5]>0?$f[5]:"NULL"); // duration, device_id
|
||||
$q.= "EXTRACT(epoch FROM '".$last[3]."':timestamp-'".$first[3]."'::timestamp),".$n.")"; // inner_duration, total
|
||||
pg_query($conn, $q);
|
||||
//echo pg_last_error()."\n";
|
||||
|
||||
if (count($clear_data)>0) {
|
||||
$q1 = "DELETE FROM members_tracking WHERE id IN (".implode(",",$clear_data).")";
|
||||
$r1 = pg_query($conn, $q1);
|
||||
if ($r1 && pg_affected_rows($r1)) {
|
||||
$q2 = "UPDATE members_tracking SET previous_id=".$first_data[0].",";
|
||||
$q2.= "distance=ST_Distance(gps,'".$first_data[6]."'::geometry),";
|
||||
$q2.= "duration=EXTRACT(epoch FROM ttime-'".$first_data[3]."'::timestamp)";
|
||||
$q2.= " WHERE previous_id IN (".implode(",",$clear_data).",".$last_data[0].")";
|
||||
$r2 = pg_query($conn, $q2);
|
||||
echo "\n${q2}\n";
|
||||
//echo pg_last_error()."\n";
|
||||
} else {
|
||||
echo "\n";
|
||||
echo "[".date("Y-m-d H:i:s")."] Failed - ".pg_last_error()."\n";
|
||||
echo "${q1}\n";
|
||||
}
|
||||
}
|
||||
$first_data = NULL;
|
||||
}
|
||||
}
|
||||
if ($first_data==NULL) {
|
||||
$first_data = $f;
|
||||
unset($pool_data);
|
||||
$pool_data = [];
|
||||
}
|
||||
$pool_data[] = $f[0]; // id
|
||||
$last_data = $f;
|
||||
$processed++;
|
||||
}
|
||||
pg_free_result($r);
|
||||
echo "\n";
|
||||
return $processed;
|
||||
}
|
||||
|
||||
pg_close($conn);
|
||||
pg_close($readOnlyReplicaConn);
|
||||
echo "[".date("Y-m-d H:i:s")."] GPS member_tracking_duration job complete.\n";
|
||||
@@ -0,0 +1,317 @@
|
||||
<?php
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] GPS members_tracking_trips job is starting.\n";
|
||||
|
||||
require('../backend.php');
|
||||
|
||||
// We will not limit the SQL we will exhaust the allowed memory
|
||||
// we will process data in ${hard_limit} batches and hopefully catch up
|
||||
$hard_limit = 500000;
|
||||
// GPS coordinate precision to assume the same location
|
||||
$precision = 3;
|
||||
// How many seconds is a stop?
|
||||
$stop_limit = 120;
|
||||
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('gpsdatabase.host');
|
||||
$db_name = $savvyext->cfgReadChar('gpsdatabase.name');
|
||||
$db_user = $savvyext->cfgReadChar('gpsdatabase.user');
|
||||
$db_pass = $savvyext->cfgReadChar('gpsdatabase.pass');
|
||||
$db_port = $savvyext->cfgReadLong('gpsdatabase.port');
|
||||
$gpsconnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$gpsconn = pg_connect($gpsconnstr);
|
||||
|
||||
$q = "select member_id,count(*) from members_tracking ";
|
||||
//$q.= "where member_id=55 "; // DEBUG
|
||||
$q.= "group by member_id";
|
||||
$r = pg_query($gpsconn, $q);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
while ($f=pg_fetch_row($r)) {
|
||||
$member_id = $f[0];
|
||||
echo "[".date("Y-m-d H:i:s")."] Processing member_id=".$member_id." (total member records: ".$f[1].")\n";
|
||||
$p = processMemberGPSTrackingTrips($member_id);
|
||||
echo "[".date("Y-m-d H:i:s")."] Processed member_id=".$member_id." (processed records: ".$p.")\n";
|
||||
}
|
||||
}
|
||||
|
||||
function processMemberGPSTrackingTrips($member_id) {
|
||||
global $gpsconn,$precision,$hard_limit,$stop_limit;
|
||||
echo "[".date("Y-m-d H:i:s")."] processMemberGPSDataPartition($member_id)\n";
|
||||
$id = 0;
|
||||
$q = 'select max(location_start),max(location_end) from members_tracking_trips where member_id=' . $member_id;
|
||||
$r = pg_query($gpsconn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) {
|
||||
$id = max((int)$f[0],(int)$f[1]);
|
||||
}
|
||||
echo "[".date("Y-m-d H:i:s")."] Last processed ID is ${id}\n";
|
||||
|
||||
$q = "select a.first_id,a.last_id,a.device_id,extract(milliseconds from a.duration) as ms, ";
|
||||
$q.= "extract(epoch from a.duration) as seconds, c.speed, a.inner_duration, a.total, ";
|
||||
$q.= "ST_Distance(c.gps,b.gps) AS distance, b.gps AS gps_start, c.gps AS gps_end,";
|
||||
$q.= "EXTRACT(epoch FROM c.ttime-b.ttime) AS travel_time ";
|
||||
$q.= "from members_tracking_duration a ";
|
||||
$q.= "left join members_tracking b on (b.id=a.first_id) ";
|
||||
$q.= "left join members_tracking c on (c.id=a.last_id) ";
|
||||
$q.= "where a.member_id=${member_id} ";
|
||||
$q.= "and a.first_id>${id} AND a.last_id>${id} "; // Limit ?
|
||||
$q.= "order by a.device_id, a.first_time limit ${hard_limit}";
|
||||
//echo "\n$q\n";
|
||||
$r = pg_query($gpsconn, $q);
|
||||
|
||||
if ($r && pg_num_rows($r)) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Records to process: ".pg_num_rows($r)."\n";
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] No new records to process. Stop.\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] Processing";
|
||||
|
||||
$trip = [];
|
||||
$trips = [];
|
||||
$trip_data = ['distance'=>0,'duration'=>0,'total'=>0,'speed'=>0];
|
||||
$trips_data = [];
|
||||
$processed = 0;
|
||||
$last_device_id = -1;
|
||||
$r = pg_query($gpsconn, $q);
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
//$res[] = $f;
|
||||
//if ($f["seconds"]>=$stop_limit || ($last_device_id!=$f["device_id"] && count($trip)>0)) {
|
||||
if ($f["inner_duration"]>=$stop_limit || ($last_device_id!=$f["device_id"] && count($trip)>0)) {
|
||||
$trips[] = $trip;
|
||||
$trips_data[] = $trip_data;
|
||||
$n = count($trip)-1;
|
||||
list ($res, $err) = processMemberGPSTrackingTripsSave(
|
||||
$member_id,
|
||||
$trip[0],
|
||||
array_pop($trip),
|
||||
$trip_data);
|
||||
if ($res && $res["id"]>0) {
|
||||
echo "[".date("Y-m-d H:i:s")."] New trip processed: ".$res["id"]." (member_id=${member_id})\n";
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Failed to process trip: ${err} (member_id=${member_id})\n";
|
||||
var_dump($trip_data); // DEBUG
|
||||
}
|
||||
unset($trip);
|
||||
unset($trip_data);
|
||||
$trip = [];
|
||||
$trip_data = ['distance'=>0,'duration'=>0,'total'=>0,'speed'=>0];
|
||||
} else {
|
||||
$trip[] = $f;
|
||||
$trip_data['distance'] += $f["distance"];
|
||||
$trip_data['duration'] += $f["ms"];
|
||||
$trip_data['speed'] += $f["ms"]>0 ? (3600 * $f["distance"] / $f["ms"]) : 0; // km/h
|
||||
$trip_data['total'] += 1;
|
||||
}
|
||||
$last_device_id = $f["device_id"];
|
||||
$processed++;
|
||||
}
|
||||
pg_free_result($r);
|
||||
return $processed;
|
||||
}
|
||||
|
||||
function processMemberGPSTrackingTripsSave($member_id,$first,$last,$trip_data) {
|
||||
global $gpsconn;
|
||||
|
||||
$distance = $trip_data['distance'];
|
||||
$duration = $trip_data['duration']/1000;
|
||||
|
||||
if ($distance>0 && $duration>0) {
|
||||
// OK
|
||||
} else {
|
||||
return [NULL, "Distance and/or duration are invalid!"];
|
||||
}
|
||||
|
||||
$speed = 3600 * $trip_data['distance'] / $trip_data['duration'];
|
||||
$avg_speed = $trip_data['speed'] / $trip_data['total'];
|
||||
$device_id = ($first['device_id']>0 ? $first['device_id'] : "NULL");
|
||||
|
||||
$location_start = $first['last_id'];
|
||||
$location_end = $last['last_id'];
|
||||
$gps_start = $first['gps_end'];
|
||||
$gps_end = $last['gps_end'];
|
||||
|
||||
$address_start = processMemberGPSTrackingTripsReverseGeocode($gps_start);
|
||||
$address_end = processMemberGPSTrackingTripsReverseGeocode($gps_end);
|
||||
|
||||
$q = "SELECT * FROM members_tracking_trips WHERE member_id=${member_id} ";
|
||||
$q.= "AND location_start=${location_start} AND location_end=${location_end} ";
|
||||
$q.= "AND ".($device_id=="NULL"?"device_id IS NULL":"device_id=${device_id}");
|
||||
$r = pg_query($gpsconn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) {
|
||||
$q = "UPDATE members_tracking_trips SET distance=${distance},duration=${duration},";
|
||||
$q.= "speed=${speed},avg_speed=${avg_speed},gps_start='${gps_start}',gps_end='${gps_end}',";
|
||||
$q.= "address_start='${address_start}',address_end='${address_end}' WHERE member_id=${member_id} ";
|
||||
$q.= "AND location_start=${location_start} AND location_end=${location_end} ";
|
||||
$q.= "AND ".($device_id=="NULL"?"device_id IS NULL":"device_id=${device_id}");
|
||||
$q.=" RETURNING *";
|
||||
} else {
|
||||
$q = "INSERT INTO members_tracking_trips (member_id,distance,duration,speed,avg_speed,location_start,location_end,device_id,gps_start,gps_end,address_start,address_end) VALUES(";
|
||||
$q.= "${member_id},${distance},${duration},${speed},${avg_speed},${location_start},${location_end},${device_id},'${gps_start}','${gps_end}',${address_start},${address_end}";
|
||||
$q.= ") RETURNING *";
|
||||
}
|
||||
$r = pg_query($gpsconn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) {
|
||||
pg_free_result($r);
|
||||
return [$f, NULL];
|
||||
}
|
||||
echo "\n$q\n";
|
||||
return [NULL, pg_last_error($gpsconn)];
|
||||
}
|
||||
|
||||
function processMemberGPSTrackingTripsReverseGeocode($gps) {
|
||||
global $gpsconn, $readOnlyReplicaConn;
|
||||
if ($gps==NULL || $gps=="") {
|
||||
echo "[".date("Y-m-d H:i:s")."] Empty GPS string\n";
|
||||
return "NULL";
|
||||
}
|
||||
$q = "SELECT ST_Y('${gps}') AS lat, ST_X('${gps}') AS lng";
|
||||
$r = pg_query($gpsconn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) {
|
||||
$lat = $f[0];
|
||||
$lng = $f[1];
|
||||
} else {
|
||||
echo "[".date("Y-m-d H:i:s")."] Failed to decode GPS: '${gps}'\n";
|
||||
return "NULL";
|
||||
}
|
||||
list ($address,$err) = reverseGeocode($readOnlyReplicaConn, $lat, $lng);
|
||||
if (!$address && $err) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Failed to reverse geocode GPS: ${lat},${lng}\n";
|
||||
return "NULL";
|
||||
}
|
||||
$q = "SELECT id FROM address WHERE lower(address)=lower('".pg_escape_string($address)."') ORDER BY geocoding_date DESC LIMIT 1";
|
||||
//echo "\n\n${q}\n\n";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) {
|
||||
return $f[0];
|
||||
}
|
||||
echo "[".date("Y-m-d H:i:s")."] Failed to load address: '${address}'\n";
|
||||
return "NULL";
|
||||
}
|
||||
|
||||
function reverseGeocode($db, $lat, $lng) {
|
||||
// Reverse geocode using local DB
|
||||
list($res,$err) = GeocodeReverseGeocode($db, $lat, $lng);
|
||||
if (is_array($res) && isset($res["address"])) {
|
||||
return [$res["address"],NULL];
|
||||
}
|
||||
// Reverse geocode service using Google Maps API
|
||||
list($res,$err) = reverseGeocodeService($db, $lat, $lng);
|
||||
if (is_array($res) && isset($res["address"]) && $res["address"]!="") {
|
||||
reverseGeocodeServiceSave($db, $res);
|
||||
return [$res["address"],NULL];
|
||||
}
|
||||
return [NULL, $err];
|
||||
}
|
||||
|
||||
function GeocodeReverseGeocode($db, $lat, $lng) {
|
||||
$db_lat = ((float)$lat);
|
||||
$db_lng = ((float)$lng);
|
||||
// Check our local address table with precisions 5 to 3
|
||||
for ($i=5;$i>2;$i--) {
|
||||
$q = "SELECT * FROM address WHERE round(latitude,${i})=round(${db_lat},${i}) AND round(longitude,${i})=round(${db_lng},${i})";
|
||||
$r = pg_query($db, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) {
|
||||
return [$f, NULL];
|
||||
}
|
||||
}
|
||||
// Check our local Singapore table with precisions 5 to 3
|
||||
/* for ($i=5;$i>2;$i--) {
|
||||
$q = "SELECT * FROM singapore_buildings WHERE round(latitude,${i})=round(${db_lat},${i}) AND round(longitude,${i})=round(${db_lng},${i})";
|
||||
$r = pg_query($q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) {
|
||||
return [$f, NULL];
|
||||
}
|
||||
} //*/
|
||||
return [NULL, pg_last_error($db)];
|
||||
}
|
||||
|
||||
function reverseGeocodeServiceSave($db, $result) {
|
||||
$db_lat = floatval($result["lat"]);
|
||||
$db_lng = floatval($result["lng"]);
|
||||
$db_address = pg_escape_string($result["address"]);
|
||||
$db_postal = pg_escape_string($result["postal"]);
|
||||
$db_tz = GeocodeGetTimezone($db, $result["timeZoneId"]);
|
||||
// Check the address exists
|
||||
$q = "SELECT id FROM address WHERE lower(address)=lower('${db_address}') ";
|
||||
$q.= "AND latitude<>0 AND longitude<>0 AND geocoding_date IS NOT NULL ";
|
||||
$q.= "ORDER BY geocoding_date DESC LIMIT 1";
|
||||
//error_log($q);
|
||||
$r = pg_query($db, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) {
|
||||
return $f[0];
|
||||
}
|
||||
$q = "INSERT INTO address (address,latitude,longitude,timezone,geocoding_date,postal) VALUES (";
|
||||
$q.= "'${db_address}',${db_lat},${db_lng},".($db_tz==NULL?"NULL":$db_tz).",now(),'${db_postal}')";
|
||||
$q.= " RETURNING id";
|
||||
$r = pg_query($db, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) {
|
||||
return $f[0];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
function GeocodeGetTimezone($db, $timezone) {
|
||||
$db_timezone = pg_escape_string($timezone);
|
||||
$q = "SELECT id FROM address_timezone WHERE timezone='${db_timezone}'";
|
||||
$r = pg_query($db, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) {
|
||||
return $f[0];
|
||||
}
|
||||
$q = "INSERT INTO address_timezone (timezone) VALUES('${db_timezone}') RETURNING id";
|
||||
$r = pg_query($db, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) {
|
||||
return $f[0];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
function reverseGeocodeService($db, $lat, $lng) {
|
||||
global $httpAuthToken;
|
||||
$data = http_build_query(
|
||||
array(
|
||||
'lat' => $lat,
|
||||
'lng' => $lng
|
||||
)
|
||||
);
|
||||
$url = "http://oauth2.service/api/v1/reverse?" . $data;
|
||||
//echo "\n\n${url}\n\n";
|
||||
$opts = array(
|
||||
'http' => array(
|
||||
'method' => "GET",
|
||||
'timeout' => 60, /* 1 minute */
|
||||
'header' =>
|
||||
"Content-Type: application/x-www-form-urlencoded\r\n" .
|
||||
"Accept: application/json\r\n" .
|
||||
"Authorization: Server-Token ${httpAuthToken}\r\n",
|
||||
)
|
||||
);
|
||||
$context = stream_context_create($opts);
|
||||
$body = file_get_contents($url, false, $context);
|
||||
//error_log("BODY: ".$body);
|
||||
$geocoded = json_decode($body,true);
|
||||
if (is_array($geocoded) && is_array($geocoded["data"]) && !isset($geocoded["error"])) {
|
||||
//error_log(json_encode($geocoded));
|
||||
// Cache the result in DB
|
||||
/*Geocode::saveDistanceCache(
|
||||
$db->getConnect(), $fromLat, $fromLng, $toLat, $toLng, $geocoded["data"]);
|
||||
*/
|
||||
return [$geocoded["data"], NULL];
|
||||
} else if (is_array($geocoded) && isset($geocoded["error"])) {
|
||||
$body = $geocoded["error"];
|
||||
}
|
||||
return [NULL, "Reverse geocoding service call error: ".$body];
|
||||
}
|
||||
|
||||
pg_close($readOnlyReplicaConn);
|
||||
pg_close($gpsconn);
|
||||
echo "[".date("Y-m-d H:i:s")."] GPS members_tracking_trips job complete.\n";
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
echo "[" . date( "Y-m-d H:i:s" ) . "] members_devices_check job is starting.\n";
|
||||
|
||||
require('lock.php');
|
||||
$lock_file = lock_pid_file();
|
||||
|
||||
set_time_limit(0); // No limit!
|
||||
|
||||
require( '../backend.php' );
|
||||
|
||||
$inactivePeriod = 14400; // 240 hours in minutes
|
||||
|
||||
$db_host = $savvyext->cfgReadChar( 'database.host' );
|
||||
$db_name = $savvyext->cfgReadChar( 'database.name' );
|
||||
$db_user = $savvyext->cfgReadChar( 'database.user' );
|
||||
$db_pass = $savvyext->cfgReadChar( 'database.pass' );
|
||||
$db_port = $savvyext->cfgReadLong( 'database.port' );
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect( $connstr );
|
||||
|
||||
$q = "UPDATE members_devices SET status = 0 WHERE status = 1 AND updated IS NOT NULL AND updated < (now() - interval '".$inactivePeriod." minutes') RETURNING *";
|
||||
|
||||
$r = pg_query( $conn, $q );
|
||||
|
||||
if ( $r && $count = pg_num_rows( $r ) ) {
|
||||
echo "[" . date( "Y-m-d H:i:s" ) . "] Updated ${count} rows\n";
|
||||
}
|
||||
|
||||
unlock_pid_file($lock_file);
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] members_devices_check job complete.\n";
|
||||
@@ -0,0 +1,335 @@
|
||||
<?php
|
||||
|
||||
define("FLOAT_SYSTEM_CREATE_NOTIFICATION", 92025);
|
||||
define("FLOAT_SYSTEM_EMAIL_NOTIFICATION", 92027);
|
||||
define('FLOAT_SYSTEM_CREATE_DYNAMICCARD', 92026);
|
||||
|
||||
|
||||
$mysql = " SELECT ";
|
||||
$mysql .= " p.id,m.id AS member_id,m.email, p.travel_date,p.duration,p.cost_raw,p.trackedemail_item_id,p.cost,p.updated,p.distance, ";
|
||||
$mysql .= " CASE WHEN e.id IS NULL THEN '0' ELSE '1' END AS surge_price, ";
|
||||
$mysql .= " CASE WHEN (f.id IS NOT NULL AND f.cost>f.average) THEN ROUND(f.average/f.cost,2) ELSE 0 END AS cheaper_alternative ";
|
||||
$mysql .= " FROM parsedemail_item p LEFT JOIN trackedemail_item t ON t.id=p.trackedemail_item_id ";
|
||||
$mysql .= " LEFT JOIN trip_surge_price e ON (e.data_source_id=p.id AND e.data_source=1) ";
|
||||
$mysql .= " LEFT JOIN trip_price_comparison f ON (f.data_source_id=p.id AND e.data_source=1) LEFT JOIN members m ON m.id=t.member_id ";
|
||||
$mysql .= " WHERE e.id IS NOT NULL ORDER BY t.id DESC LIMIT 500";
|
||||
|
||||
|
||||
$trigger_query = array(
|
||||
"SURGESAVE" => array(
|
||||
"query" => $mysql,
|
||||
"message" => "You are spending too much. Let's save money",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
),
|
||||
"ETRG0001" => array(
|
||||
"query" => "SELECT id AS member_id,last_acct,count_acct,last_email,count_email, min_budget,count_acct+count_email AS total_data FROM members WHERE min_budget =0 AND count_email =0 AND count_acct =0 AND id > 0 ORDER BY notification_test ASC LIMIT 500",
|
||||
"message" => "Let's examine how much you spend on travel. We can save money.",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0001KEY",
|
||||
"start_save" => true
|
||||
),
|
||||
"ETRG0002" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE m.min_budget > 0 AND ma.spend_7 > 0 AND ma.spend_7/m.min_budget < 0.9 ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "Good Job, you're saving money",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0002KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
),
|
||||
"ETRG0003" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE m.min_budget > 0 AND ma.spend_7 > 0 AND ma.spend_7/m.min_budget > 1.1 ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "You are over budget. Let's see how we can save you money.",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0003KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
),
|
||||
"ETRG0004" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE ma.spend_7 > 4000 ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "We can see you spent $X on rideshare this month. Here's how Float can save you money",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0004KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
),
|
||||
"ETRG0005" => array(
|
||||
"query" => "SELECT b.member_id FROM members_bank_accounts b LEFT JOIN members m ON m.id=b.member_id WHERE m.id>0 AND m.country IN ('US','SG','NZ') GROUP BY b.member_id,m.notification_test ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "You have a Chase Freedom credit card. You should take Lyft this month",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0005KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
)
|
||||
,
|
||||
"ETRG0006" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget,(ma.spend_14 - 2*ma.spend_7) AS week_increase from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE min_budget = 0 AND ma.spend_7 > 0 AND ma.spend_14 > 2*ma.spend_7 ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "Your spending is up 23% this week. Would you like to create a budget?",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0006KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
),
|
||||
"ETRG0007" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget,(ma.spend_14 - 2*ma.spend_7) AS week_increase,m.country AS country from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE m.decision_group IN('A1NUS25','USSF001') AND m.id NOT IN (SELECT member_id FROM members_carpool) ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "Deal Carpool Try carpooling and save $X and Y emissions this month",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0007KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
),
|
||||
"ETRG0008" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget,(ma.spend_14 - 2*ma.spend_7) AS week_increase from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE min_budget = 0 AND ma.spend_7 > 0 AND ma.spend_14 > 2*ma.spend_7 ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "We can save you $X by taxing (rideshare or taxi) at 5pm today.",
|
||||
"feed_msg" => "",
|
||||
"active" => 0,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0008KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
),
|
||||
"ETRG0009" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget,(ma.spend_14 - 2*ma.spend_7) AS week_increase from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE min_budget = 0 AND ma.spend_7 > 0 AND ma.spend_14 > 2*ma.spend_7 ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "We found that taking public transit and scooter is faster and cheaper for you.",
|
||||
"feed_msg" => "",
|
||||
"active" => 0,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0009KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
),
|
||||
"ETRG0010" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget,(ma.spend_14 - 2*ma.spend_7) AS week_increase from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE min_budget = 0 AND ma.spend_7 > 0 AND ma.spend_14 > 2*ma.spend_7 ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "Your spending is up 23% this week. Would you like to create a budget?",
|
||||
"feed_msg" => "",
|
||||
"active" => 0,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0010KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
),
|
||||
"ETRG0011" => array(
|
||||
"query" => "SELECT *, id AS member_id FROM members WHERE id > 0 AND id NOT IN (SELECT member_id FROM members_trips) ORDER BY notification_test ASC LIMIT 500",
|
||||
"message" => "Float found a better way for you to get to work. See route, save it and Float will remind you going forward.",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0011KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
),
|
||||
"ETRG0012" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget,(ma.spend_14 - 2*ma.spend_7) AS week_increase from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE min_budget = 0 AND ma.spend_7 > 0 AND ma.spend_14 > 2*ma.spend_7 ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "Your spending is up 23% this week. Would you like to create a budget?",
|
||||
"feed_msg" => "",
|
||||
"active" => 0,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0012KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
),
|
||||
"ETRG0014" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget,(2*ma.spend_7- ma.spend_14) AS week_increase from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE ma.spend_7 > 0 AND 2*ma.spend_7> ma.spend_14 ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "Your emissions output is 10% higher this week, lets see how we can lower it",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0014KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
),
|
||||
"ETRG0015" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget,(2*ma.spend_7 - ma.spend_14) AS week_decrease from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE min_budget = 0 AND ma.spend_7 > 0 AND ma.spend_14 < 2*ma.spend_7 ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "Hurray, you have spent X minutes less on the road this week. Shop for rewards with Float.",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0015KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
)
|
||||
,
|
||||
"ETRG0016" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget,(ma.spend_14 - 2*ma.spend_7) AS week_increase from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE min_budget = 0 AND ma.spend_7 > 0 AND ma.spend_14 > 2*ma.spend_7 ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "Good Job, you're saving X% more money than your peers.",
|
||||
"feed_msg" => "",
|
||||
"active" => 0,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0012KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
)
|
||||
,
|
||||
"ETRG0017" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget,(ma.spend_14 - 2*ma.spend_7) AS week_increase from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE min_budget = 0 AND ma.spend_7 > 0 AND ma.spend_14 > 2*ma.spend_7 ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "You are spending more X% money than your peers. Let's save money ",
|
||||
"feed_msg" => "",
|
||||
"active" => 0,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0017KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
)
|
||||
,
|
||||
"ETRG0019" => array(
|
||||
"query" => "SELECT * FROM members LIMIT 1",
|
||||
"message" => "THIS IS USED FOR THE POINTS SYSTEM ONLY - It is automatic",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOPOINT',
|
||||
"dynamic_key" => "ETRG0019KEY",
|
||||
"start_save" => false, "send_mail" => 1, "send_notification" => 1
|
||||
),
|
||||
"ETRG0020" => array(
|
||||
"query" => "SELECT * FROM members LIMIT 1",
|
||||
"message" => "THIS IS USED FOR THE TRIPS SYSTEM ONLY - It is automatic",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOPOINT',
|
||||
"dynamic_key" => "ETRG0020KEY",
|
||||
"start_save" => false, "send_mail" => 1, "send_notification" => 1
|
||||
),
|
||||
"ETRG0021" => array(
|
||||
"query" => "SELECT ma.member_id,ma.status,ma.bank_login_status FROM members_bank_accounts ma LEFT JOIN members m ON m.id=ma.member_id WHERE m.country ='SG' AND ma.bank_login_status='inactive' ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "Your bank connection has expired, import your latest transactions to stay on top of your spending",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOPROFILE',
|
||||
"dynamic_key" => "ETRG0021KEY",
|
||||
"start_save" => false, "send_mail" => 1, "send_notification" => 1
|
||||
)
|
||||
,
|
||||
"ETRG0022" => array(
|
||||
"query" => "SELECT b.member_id, count(b.id) AS total_rec,m.notification_test FROM members_bankimport b LEFT JOIN members m ON m.id=b.member_id WHERE lower(merchant_name)= LOWER('ComfortDelGro') GROUP BY b.member_id, m.notification_test ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "Be careful how you pay, credit and charge card payments get hit with a 10% surcharge in a Comfort Taxi",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0022KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 0
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
|
||||
$trigger_card = array(
|
||||
"ETRG0001" => array(
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0001KEY"
|
||||
),
|
||||
"ETRG0002" => array(
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0002KEY"
|
||||
),
|
||||
"ETRG0003" => array(
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0003KEY"
|
||||
),
|
||||
"ETRG0004" => array(
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0004KEY"
|
||||
),
|
||||
"ETRG0005" => array(
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0005KEY"
|
||||
),
|
||||
"ETRG0006" => array(
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0006KEY"
|
||||
),
|
||||
"ETRG0011" => array(
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0011KEY"
|
||||
),
|
||||
"ETRG0014" => array(
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0014KEY"
|
||||
),
|
||||
"ETRG0015" => array(
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0015KEY"
|
||||
),
|
||||
"ETRG0021" => array(
|
||||
"active" => 1,
|
||||
"cat" => 'GOPROFILE',
|
||||
"dynamic_key" => "ETRG0021KEY"
|
||||
)
|
||||
);
|
||||
|
||||
function generateCard($notice_id, $member_id, $cat) {
|
||||
|
||||
$out = array();
|
||||
global $trigger_card;
|
||||
global $readOnlyReplicaConn;
|
||||
|
||||
// print_r($trigger_card);
|
||||
//echo "\n ~~~~~56565656 ----------------------------->>>> ".rand(100,999);
|
||||
|
||||
$trigger_key = "";
|
||||
$dynamic_key = "";
|
||||
|
||||
$status_msg = '';
|
||||
if ($notice_id != '' && $member_id != '') {
|
||||
// echo "\n ~~~~~38383838383 ----------------------------->>>> ".rand(100,999);
|
||||
|
||||
$mysql = "SELECT * FROM members_notification WHERE id=$notice_id AND member_id=$member_id";
|
||||
$r = pg_query($readOnlyReplicaConn, $mysql);
|
||||
|
||||
|
||||
if ($r && pg_num_rows($r)) {
|
||||
$f = pg_fetch_assoc($r);
|
||||
$trigger_key = $f["trigger_key"];
|
||||
$message = $f["msg"];
|
||||
}
|
||||
|
||||
// echo "\n<br> ~~~~~55555 -----------------------------=====>>==>> ".rand(100,999);
|
||||
|
||||
$card_allowded = false;
|
||||
if (array_key_exists($trigger_key, $trigger_card)) {
|
||||
$status_msg = "The $trigger_key is in the array";
|
||||
|
||||
// print_r( $trigger_card[$trigger_key] );
|
||||
$dynamic_key = $trigger_card[$trigger_key]["dynamic_key"];
|
||||
$card_allowded = true;
|
||||
} else {
|
||||
$status_msg = "The $trigger_key not set up for cards";
|
||||
}
|
||||
|
||||
// echo "\n<br> ~~~~~66666 -----------------------------=====>>==>> ".rand(100,999);
|
||||
|
||||
if (true == $card_allowded && $message != '' && $trigger_key != '' && $dynamic_key != '') {
|
||||
$in = array();
|
||||
echo "~~~~~44444 -----------------------------";
|
||||
$in["dynamic_key"] = $dynamic_key;
|
||||
$in["member_id"] = $member_id;
|
||||
$in["trigger_key"] = $trigger_key;
|
||||
$in["message"] = $message;
|
||||
$in["notice_id"] = $notice_id;
|
||||
$in["cat"] = $cat;
|
||||
$in['action'] = FLOAT_SYSTEM_CREATE_DYNAMICCARD;
|
||||
|
||||
print_r($in);
|
||||
|
||||
$ret = Fextension_call($in, $out);
|
||||
|
||||
print_r($out);
|
||||
if ($ret == PHP_API_OK) {
|
||||
$message = 'Completed!';
|
||||
} else {
|
||||
$message = 'Failed to Create';
|
||||
}
|
||||
}
|
||||
}
|
||||
echo $status_msg;
|
||||
}
|
||||
@@ -0,0 +1,340 @@
|
||||
<?php
|
||||
|
||||
define("FLOAT_SYSTEM_CREATE_NOTIFICATION", 92025);
|
||||
define("FLOAT_SYSTEM_EMAIL_NOTIFICATION", 92027);
|
||||
define('FLOAT_SYSTEM_CREATE_DYNAMICCARD', 92026);
|
||||
|
||||
|
||||
$mysql = " SELECT ";
|
||||
$mysql .= " p.id,m.id AS member_id,m.email, p.travel_date,p.duration,p.cost_raw,p.trackedemail_item_id,p.cost,p.updated,p.distance, ";
|
||||
$mysql .= " CASE WHEN e.id IS NULL THEN '0' ELSE '1' END AS surge_price, ";
|
||||
$mysql .= " CASE WHEN (f.id IS NOT NULL AND f.cost>f.average) THEN ROUND(f.average/f.cost,2) ELSE 0 END AS cheaper_alternative ";
|
||||
$mysql .= " FROM parsedemail_item p LEFT JOIN trackedemail_item t ON t.id=p.trackedemail_item_id ";
|
||||
$mysql .= " LEFT JOIN trip_surge_price e ON (e.data_source_id=p.id AND e.data_source=1) ";
|
||||
$mysql .= " LEFT JOIN trip_price_comparison f ON (f.data_source_id=p.id AND e.data_source=1) LEFT JOIN members m ON m.id=t.member_id ";
|
||||
$mysql .= " WHERE e.id IS NOT NULL ORDER BY t.id DESC LIMIT 500";
|
||||
|
||||
|
||||
$trigger_query = array(
|
||||
"SURGESAVE" => array(
|
||||
"query" => $mysql,
|
||||
"message" => "You are spending too much. Let's save money",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
),
|
||||
"ETRG0001" => array(
|
||||
"query" => "SELECT id AS member_id,last_acct,count_acct,last_email,count_email, min_budget,count_acct+count_email AS total_data FROM members WHERE min_budget =0 AND count_email =0 AND count_acct =0 AND id > 0 ORDER BY notification_test ASC LIMIT 500",
|
||||
"message" => "Let's examine how much you spend on travel. We can save money.",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0001KEY",
|
||||
"start_save" => true
|
||||
),
|
||||
"ETRG0002" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE m.min_budget > 0 AND ma.spend_7 > 0 AND ma.spend_7/m.min_budget < 0.9 ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "Good Job, you're saving money",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0002KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
),
|
||||
"ETRG0003" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE m.min_budget > 0 AND ma.spend_7 > 0 AND ma.spend_7/m.min_budget > 1.1 ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "You are over budget. Let's see how we can save you money.",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0003KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
),
|
||||
"ETRG0004" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE ma.spend_7 > 4000 ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "We can see you spent $X on rideshare this month. Here's how Float can save you money",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0004KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
),
|
||||
"ETRG0005" => array(
|
||||
"query" => "SELECT b.member_id FROM members_bank_accounts b LEFT JOIN members m ON m.id=b.member_id WHERE m.id>0 AND m.country IN ('US','SG','NZ') GROUP BY b.member_id,m.notification_test ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "You have a Chase Freedom credit card. You should take Lyft this month",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0005KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
)
|
||||
,
|
||||
"ETRG0006" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget,(ma.spend_14 - 2*ma.spend_7) AS week_increase from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE min_budget = 0 AND ma.spend_7 > 0 AND ma.spend_14 > 2*ma.spend_7 ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "Your spending is up 23% this week. Would you like to create a budget?",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0006KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
),
|
||||
"ETRG0007" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget,(ma.spend_14 - 2*ma.spend_7) AS week_increase,m.country AS country from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE m.decision_group IN('A1NUS25','USSF001') AND m.id NOT IN (SELECT member_id FROM members_carpool) ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "Deal Carpool Try carpooling and save $X and Y emissions this month",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0007KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
),
|
||||
"ETRG0008" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget,(ma.spend_14 - 2*ma.spend_7) AS week_increase from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE min_budget = 0 AND ma.spend_7 > 0 AND ma.spend_14 > 2*ma.spend_7 ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "We can save you $X by taxing (rideshare or taxi) at 5pm today.",
|
||||
"feed_msg" => "",
|
||||
"active" => 0,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0008KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
),
|
||||
"ETRG0009" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget,(ma.spend_14 - 2*ma.spend_7) AS week_increase from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE min_budget = 0 AND ma.spend_7 > 0 AND ma.spend_14 > 2*ma.spend_7 ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "We found that taking public transit and scooter is faster and cheaper for you.",
|
||||
"feed_msg" => "",
|
||||
"active" => 0,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0009KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
),
|
||||
"ETRG0010" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget,(ma.spend_14 - 2*ma.spend_7) AS week_increase from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE min_budget = 0 AND ma.spend_7 > 0 AND ma.spend_14 > 2*ma.spend_7 ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "Your spending is up 23% this week. Would you like to create a budget?",
|
||||
"feed_msg" => "",
|
||||
"active" => 0,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0010KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
),
|
||||
"ETRG0011" => array(
|
||||
"query" => "SELECT *, id AS member_id FROM members WHERE id > 0 AND id NOT IN (SELECT member_id FROM members_trips) ORDER BY notification_test ASC LIMIT 500",
|
||||
"message" => "Float found a better way for you to get to work. See route, save it and Float will remind you going forward.",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0011KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
),
|
||||
"ETRG0012" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget,(ma.spend_14 - 2*ma.spend_7) AS week_increase from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE min_budget = 0 AND ma.spend_7 > 0 AND ma.spend_14 > 2*ma.spend_7 ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "Your spending is up 23% this week. Would you like to create a budget?",
|
||||
"feed_msg" => "",
|
||||
"active" => 0,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0012KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
),
|
||||
"ETRG0014" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget,(2*ma.spend_7- ma.spend_14) AS week_increase from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE ma.spend_7 > 0 AND 2*ma.spend_7> ma.spend_14 ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "Your emissions output is 10% higher this week, lets see how we can lower it",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0014KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
),
|
||||
"ETRG0015" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget,(2*ma.spend_7 - ma.spend_14) AS week_decrease from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE min_budget = 0 AND ma.spend_7 > 0 AND ma.spend_14 < 2*ma.spend_7 ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "Hurray, you have spent X minutes less on the road this week. Shop for rewards with Float.",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0015KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
)
|
||||
,
|
||||
"ETRG0016" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget,(ma.spend_14 - 2*ma.spend_7) AS week_increase from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE min_budget = 0 AND ma.spend_7 > 0 AND ma.spend_14 > 2*ma.spend_7 ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "Good Job, you're saving X% more money than your peers.",
|
||||
"feed_msg" => "",
|
||||
"active" => 0,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0012KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
)
|
||||
,
|
||||
"ETRG0017" => array(
|
||||
"query" => "SELECT ma.*,m.min_budget,(ma.spend_14 - 2*ma.spend_7) AS week_increase from members_analysis ma LEFT JOIN members m ON m.id = ma.member_id WHERE min_budget = 0 AND ma.spend_7 > 0 AND ma.spend_14 > 2*ma.spend_7 ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "You are spending more X% money than your peers. Let's save money ",
|
||||
"feed_msg" => "",
|
||||
"active" => 0,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0017KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 1
|
||||
)
|
||||
,
|
||||
"ETRG0019" => array(
|
||||
"query" => "SELECT * FROM members LIMIT 1",
|
||||
"message" => "THIS IS USED FOR THE POINTS SYSTEM ONLY - It is automatic",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOPOINT',
|
||||
"dynamic_key" => "ETRG0019KEY",
|
||||
"start_save" => false, "send_mail" => 1, "send_notification" => 1
|
||||
),
|
||||
"ETRG0020" => array(
|
||||
"query" => "SELECT * FROM members LIMIT 1",
|
||||
"message" => "THIS IS USED FOR THE TRIPS SYSTEM ONLY - It is automatic",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOPOINT',
|
||||
"dynamic_key" => "ETRG0020KEY",
|
||||
"start_save" => false, "send_mail" => 1, "send_notification" => 1
|
||||
),
|
||||
"ETRG0021" => array(
|
||||
"query" => "SELECT ma.member_id,ma.status,ma.bank_login_status FROM members_bank_accounts ma LEFT JOIN members m ON m.id=ma.member_id WHERE m.country ='SG' AND ma.bank_login_status='inactive' ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "Your bank connection has expired, import your latest transactions to stay on top of your spending",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOPROFILE',
|
||||
"dynamic_key" => "ETRG0021KEY",
|
||||
"start_save" => false, "send_mail" => 1, "send_notification" => 1
|
||||
)
|
||||
,
|
||||
"ETRG0022" => array(
|
||||
"query" => "SELECT b.member_id, count(b.id) AS total_rec,m.notification_test FROM members_bankimport b LEFT JOIN members m ON m.id=b.member_id WHERE lower(merchant_name)= LOWER('ComfortDelGro') GROUP BY b.member_id, m.notification_test ORDER BY m.notification_test ASC LIMIT 500",
|
||||
"message" => "Be careful how you pay, credit and charge card payments get hit with a 10% surcharge in a Comfort Taxi",
|
||||
"feed_msg" => "",
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0022KEY",
|
||||
"start_save" => false, "send_mail" => 0, "send_notification" => 0
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
|
||||
$trigger_card = array(
|
||||
"ETRG0001" => array(
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0001KEY"
|
||||
),
|
||||
"ETRG0002" => array(
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0002KEY"
|
||||
),
|
||||
"ETRG0003" => array(
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0003KEY"
|
||||
),
|
||||
"ETRG0004" => array(
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0004KEY"
|
||||
),
|
||||
"ETRG0005" => array(
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0005KEY"
|
||||
),
|
||||
"ETRG0006" => array(
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0006KEY"
|
||||
),
|
||||
"ETRG0011" => array(
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0011KEY"
|
||||
),
|
||||
"ETRG0014" => array(
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0014KEY"
|
||||
),
|
||||
"ETRG0015" => array(
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0015KEY"
|
||||
),
|
||||
"ETRG0019" => array(
|
||||
"active" => 1,
|
||||
"cat" => 'GOACTIVITY',
|
||||
"dynamic_key" => "ETRG0019KEY"
|
||||
),
|
||||
"ETRG0021" => array(
|
||||
"active" => 1,
|
||||
"cat" => 'GOPROFILE',
|
||||
"dynamic_key" => "ETRG0021KEY"
|
||||
)
|
||||
);
|
||||
|
||||
function generateCard($notice_id, $member_id, $cat) {
|
||||
|
||||
$out = array();
|
||||
global $trigger_card;
|
||||
global $readOnlyReplicaConn;
|
||||
|
||||
// print_r($trigger_card);
|
||||
//echo "\n ~~~~~56565656 ----------------------------->>>> ".rand(100,999);
|
||||
|
||||
$trigger_key = "";
|
||||
$dynamic_key = "";
|
||||
|
||||
$status_msg = '';
|
||||
if ($notice_id != '' && $member_id != '') {
|
||||
// echo "\n ~~~~~38383838383 ----------------------------->>>> ".rand(100,999);
|
||||
|
||||
$mysql = "SELECT * FROM members_notification WHERE id=$notice_id AND member_id=$member_id";
|
||||
$r = pg_query($readOnlyReplicaConn, $mysql);
|
||||
|
||||
|
||||
if ($r && pg_num_rows($r)) {
|
||||
$f = pg_fetch_assoc($r);
|
||||
$trigger_key = $f["trigger_key"];
|
||||
$message = $f["msg"];
|
||||
}
|
||||
|
||||
// echo "\n<br> ~~~~~55555 -----------------------------=====>>==>> ".rand(100,999);
|
||||
|
||||
$card_allowded = false;
|
||||
if (array_key_exists($trigger_key, $trigger_card)) {
|
||||
$status_msg = "The $trigger_key is in the array";
|
||||
|
||||
// print_r( $trigger_card[$trigger_key] );
|
||||
$dynamic_key = $trigger_card[$trigger_key]["dynamic_key"];
|
||||
$card_allowded = true;
|
||||
} else {
|
||||
$status_msg = "The $trigger_key not set up for cards";
|
||||
}
|
||||
|
||||
// echo "\n<br> ~~~~~66666 -----------------------------=====>>==>> ".rand(100,999);
|
||||
|
||||
if (true == $card_allowded && $message != '' && $trigger_key != '' && $dynamic_key != '') {
|
||||
$in = array();
|
||||
echo "~~~~~44444 -----------------------------";
|
||||
$in["dynamic_key"] = $dynamic_key;
|
||||
$in["member_id"] = $member_id;
|
||||
$in["trigger_key"] = $trigger_key;
|
||||
$in["message"] = $message;
|
||||
$in["notice_id"] = $notice_id;
|
||||
$in["cat"] = $cat;
|
||||
$in['action'] = FLOAT_SYSTEM_CREATE_DYNAMICCARD;
|
||||
|
||||
print_r($in);
|
||||
|
||||
$ret = Fextension_call($in, $out);
|
||||
|
||||
print_r($out);
|
||||
if ($ret == PHP_API_OK) {
|
||||
$message = 'Completed!';
|
||||
} else {
|
||||
$message = 'Failed to Create';
|
||||
}
|
||||
}
|
||||
}
|
||||
echo $status_msg;
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
$job_name = "update packing_lot Job";
|
||||
echo "[" . date("Y-m-d H:i:s") . "] $job_name is starting.\n";
|
||||
require('./lock.php');
|
||||
//$lock_file = lock_pid_file();
|
||||
require('./../backend.php');
|
||||
require('./common/SVY21.php');
|
||||
set_time_limit(0); // No limit!
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$con = pg_connect($connstr); // or die ("Could not connect to server\n");
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
|
||||
// Step 1: get URA token
|
||||
$curl = curl_init();
|
||||
curl_setopt_array($curl, array(
|
||||
CURLOPT_URL => "https://www.ura.gov.sg/uraDataService/insertNewToken.action",
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TIMEOUT => 1000, //1000s
|
||||
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
|
||||
CURLOPT_CUSTOMREQUEST => "GET",
|
||||
CURLOPT_HTTPHEADER => array(
|
||||
"accesskey: support@float.sg",
|
||||
"cache-control: no-cache",
|
||||
),
|
||||
));
|
||||
$response = json_decode(curl_exec($curl), true);
|
||||
$err = curl_error($curl);
|
||||
curl_close($curl);
|
||||
$token = $response['Result'] ?? '';
|
||||
if ($err) {
|
||||
echo "cURL Error #1: Cannot get URA token!!! - " . $err;
|
||||
}
|
||||
// Step2. get car parking
|
||||
$curl = curl_init();
|
||||
curl_setopt_array($curl, array(
|
||||
CURLOPT_URL => "https://www.ura.gov.sg/uraDataService/invokeUraDS?service=Car_Park_Details",
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TIMEOUT => 1000, //1000s
|
||||
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
|
||||
CURLOPT_CUSTOMREQUEST => "GET",
|
||||
CURLOPT_HTTPHEADER => array(
|
||||
"accesskey: support@float.sg",
|
||||
"token: $token",
|
||||
"cache-control: no-cache"
|
||||
),
|
||||
));
|
||||
$response = json_decode(curl_exec($curl), true);
|
||||
$err = curl_error($curl);
|
||||
curl_close($curl);
|
||||
$parking_lots = $response['Result'] ?? [];
|
||||
if ($err) {
|
||||
echo "cURL Error #2: Cannot get car parking - " . $err;
|
||||
}
|
||||
// Step 3. INSERT data to database
|
||||
if (!empty($parking_lots)) {
|
||||
$now = (new \DateTime())->format('Y-m-d H:i:s');
|
||||
$svy21 = new SVY21();
|
||||
pg_query($con, 'DELETE FROM parking_lot');
|
||||
pg_query($con, 'ALTER SEQUENCE parking_lot_id_seq RESTART WITH 1');
|
||||
foreach ($parking_lots as $key => $lot) {
|
||||
foreach ($lot['geometries']??[] as $geo){
|
||||
list($n, $e) = explode(',',$geo['coordinates']);
|
||||
list($lat, $long) = $svy21->CnvEN2LL($n, $e);
|
||||
$res = pg_insert($con, 'parking_lot', [
|
||||
'ppcode' => $lot['ppCode'] ?? '',
|
||||
'name' => $lot['ppName'] ?? '',
|
||||
'address' => $lot['ppName'] ?? '',
|
||||
'lat' => strval($lat),
|
||||
'long' => strval($long),
|
||||
'weekday_price' => (float)str_replace('$', '', $lot['weekdayRate']??0),
|
||||
'sat_price' => (float)str_replace('$', '', $lot['satdayRate']??0),
|
||||
'sun_price' => (float)str_replace('$', '', $lot['sunPHRate']??0),
|
||||
'start_time' => $lot['startTime'] ?? '',
|
||||
'end_time' => $lot['endTime'] ?? '',
|
||||
'updated_time' => $now,
|
||||
], PGSQL_DML_ASYNC);
|
||||
}
|
||||
}
|
||||
}
|
||||
//unlock_pid_file($lock_file);
|
||||
echo "[" . date("Y-m-d H:i:s") . "] " . $job_name . " completed.\n";
|
||||
?>
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
$job_name ='parsedemail_item_fix_missing email';
|
||||
echo "[" . date("Y-m-d H:i:s") . "] ".$job_name." job is starting.\n";
|
||||
|
||||
require 'common/utils.php';
|
||||
require 'common/config.php';
|
||||
require 'common/address_city.php';
|
||||
require 'common/parser.php';
|
||||
require 'common/Geocode.php';
|
||||
|
||||
$total = $success = $failed = 0;
|
||||
|
||||
$q = "SELECT id FROM trackedemail_item WHERE id NOT IN (SELECT trackedemail_item_id FROM parsedemail_item_payment) ORDER BY id DESC;";
|
||||
$q="select id from trackedemail_item where id not in (select trackedemail_item_id from parsedemail_item p INNER JOIN trackedemail_item t on p.trackedemail_item_id=t.id WHERE member_id=347) AND member_id=347 order by id desc;";
|
||||
#$q = "SELECT id FROM trackedemail_item WHERE member_id=472 ORDER BY id DESC;";
|
||||
$q="select id,subject,message_from, member_id, created from trackedemail_item where id not in (select trackedemail_item_id from parsedemail_item_payment) order by created desc limit 200;";
|
||||
$q="select * from trackedemail_item where parsed_status=0 order by created desc";
|
||||
$q="select id from trackedemail_item where parsed_status=0";
|
||||
$r = pg_query($conn, $q);
|
||||
while ($f = pg_fetch_assoc($r)) {
|
||||
$total++;
|
||||
$email_id = $f['id'];
|
||||
if (!empty($email_id)) {
|
||||
$data = parseEmail($email_id);
|
||||
echo "raw:".json_encode($data);
|
||||
if ( isset( $data['parsed_status'] ) && $data['parsed_status']==1 ) {
|
||||
echo "[" . date("Y-m-d H:i:s") . "] email id: ".$email_id." is success.\n";
|
||||
$success++;
|
||||
}else{
|
||||
echo "[" . date("Y-m-d H:i:s") . "] email id: ".$email_id." is failed.\n";
|
||||
$failed++;
|
||||
}
|
||||
} else {
|
||||
echo "[" . date("Y-m-d H:i:s") . "] email id: ".$email_id." is failed.\n";
|
||||
$failed++;
|
||||
}
|
||||
}
|
||||
|
||||
echo "Total: " . $total . ".\n";
|
||||
echo "Success: : " . $success . ".\n";
|
||||
echo "Failed: : " . $failed . ".\n";
|
||||
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] ".$job_name." job complete.\n";
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
$job_name ='parsedemail_item_fix_missing email';
|
||||
echo "[" . date("Y-m-d H:i:s") . "] ".$job_name." job is starting.\n";
|
||||
|
||||
require 'common/utils.php';
|
||||
require 'common/config.php';
|
||||
require 'common/address_city.php';
|
||||
require 'common/parser.php';
|
||||
require 'common/Geocode.php';
|
||||
|
||||
$total = $success = $failed = 0;
|
||||
|
||||
$q="SELECT trackedemail_item_id as id from parsedemail_item where duration > 600 and trackedemail_item_id is not null order by duration desc";
|
||||
$r = pg_query($conn, $q);
|
||||
while ($f = pg_fetch_assoc($r)) {
|
||||
$total++;
|
||||
$email_id = $f['id'];
|
||||
if (!empty($email_id)) {
|
||||
$data = parseEmail($email_id);
|
||||
if ( isset( $data['parsed_status'] ) && $data['parsed_status']==1 ) {
|
||||
echo "[" . date("Y-m-d H:i:s") . "] email id: ".$email_id." is success.\n";
|
||||
$success++;
|
||||
}else{
|
||||
echo "[" . date("Y-m-d H:i:s") . "] email id: ".$email_id." is failed.\n";
|
||||
$failed++;
|
||||
}
|
||||
} else {
|
||||
echo "[" . date("Y-m-d H:i:s") . "] email id: ".$email_id." is failed.\n";
|
||||
$failed++;
|
||||
}
|
||||
}
|
||||
|
||||
echo "Total: " . $total . ".\n";
|
||||
echo "Success: : " . $success . ".\n";
|
||||
echo "Failed: : " . $failed . ".\n";
|
||||
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] ".$job_name." job complete.\n";
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] parsedemail_item_cleanup job is starting.\n";
|
||||
|
||||
require '../backend.php';
|
||||
|
||||
global $pgconn;
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$conn_string = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$pgconn = pg_connect($conn_string);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
|
||||
$q = "SELECT b.id FROM parsedemail_item b LEFT JOIN address c ON (c.id=b.location_start_id) LEFT JOIN address d ON (d.id=b.location_end_id) WHERE (c.country='US' AND d.country='SG') OR (c.country='SG' AND d.country='US')";
|
||||
//$q = "SELECT id FROM parsedemail_item WHERE id>20209";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
while ($f=pg_fetch_row($r)) {
|
||||
echo "[".date("Y-m-d H:i:s")."] Cleaning up => ".$f[0]."\n";
|
||||
$q = "DELETE FROM parsedemail_item_advice_schedule WHERE parsedemail_item_id=".$f[0];
|
||||
$s = pg_query($pgconn, $q);
|
||||
echo "\t\tparsedemail_item_advice_schedule => ".pg_affected_rows($s)."\n";
|
||||
$q = "DELETE FROM google_directions_leg_step_details WHERE google_directions_leg_step_id IN (SELECT id FROM google_directions_leg_steps WHERE google_directions_leg_id IN (SELECT id FROM google_directions_legs WHERE parsedemail_item_advice_google_id IN (SELECT id FROM parsedemail_item_advice_google WHERE parsedemail_item_id=".$f[0].")))";
|
||||
$s = pg_query($pgconn, $q);
|
||||
echo "\t\tgoogle_directions_leg_step_details => ".pg_affected_rows($s)."\n";
|
||||
$q = "DELETE FROM leg_step_quote WHERE google_directions_leg_step_id IN (SELECT id FROM google_directions_leg_steps WHERE google_directions_leg_id IN (SELECT id FROM google_directions_legs WHERE parsedemail_item_advice_google_id IN (SELECT id FROM parsedemail_item_advice_google WHERE parsedemail_item_id=".$f[0].")))";
|
||||
$s = pg_query($pgconn, $q);
|
||||
echo "\t\tleg_step_quote => ".pg_affected_rows($s)."\n";
|
||||
$q = "DELETE FROM google_directions_leg_steps WHERE google_directions_leg_id IN (SELECT id FROM google_directions_legs WHERE parsedemail_item_advice_google_id IN (SELECT id FROM parsedemail_item_advice_google WHERE parsedemail_item_id=".$f[0]."))";
|
||||
$s = pg_query($pgconn, $q);
|
||||
echo "\t\tgoogle_directions_leg_stesp => ".pg_affected_rows($s)."\n";
|
||||
$q = "DELETE FROM google_directions_legs WHERE parsedemail_item_advice_google_id IN (SELECT id FROM parsedemail_item_advice_google WHERE parsedemail_item_id=".$f[0].")";
|
||||
$s = pg_query($pgconn, $q);
|
||||
echo "\t\tgoogle_directions_legs => ".pg_affected_rows($s)."\n";
|
||||
$q = "DELETE FROM parsedemail_item_advice_google WHERE parsedemail_item_id=".$f[0];
|
||||
$s = pg_query($pgconn, $q);
|
||||
echo "\t\tparsedemail_item_advice_google => ".pg_affected_rows($s)."\n";
|
||||
$q = "DELETE FROM parsedemail_item_extra WHERE parsedemail_item_id=".$f[0];
|
||||
$s = pg_query($pgconn, $q);
|
||||
echo "\t\tparsedemail_item_extra => ".pg_affected_rows($s)."\n";
|
||||
$q = "DELETE FROM parsedemail_item WHERE id=".$f[0];
|
||||
$s = pg_query($pgconn, $q);
|
||||
echo "\t\tparsedemail_item => ".pg_affected_rows($s)."\n";
|
||||
echo pg_last_error($pgconn)."\n";
|
||||
}
|
||||
|
||||
pg_close($pgconn);
|
||||
pg_close($readOnlyReplicaConn);
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] parsedemail_item_cleanup job complete.\n";
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
$job_name ='parsedemail_item_fix_address';
|
||||
echo "[" . date("Y-m-d H:i:s") . "] ".$job_name." job is starting.\n";
|
||||
|
||||
require 'common/utils.php';
|
||||
require 'common/config.php';
|
||||
require 'common/address_city.php';
|
||||
require 'common/parser.php';
|
||||
require 'common/Geocode.php';
|
||||
|
||||
$total = $success = $failed = 0;
|
||||
|
||||
$q = "SELECT id, trackedemail_item_id
|
||||
FROM parsedemail_item WHERE location_start_id = 22957 or location_end_id=22957;";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
while ($f = pg_fetch_assoc($r)) {
|
||||
$total++;
|
||||
|
||||
$email_id = $f['trackedemail_item_id'];
|
||||
if (!empty($email_id)) {
|
||||
$email_data = parseEmail($f['trackedemail_item_id']);
|
||||
if (is_array($email_data) && !empty(trim($email_data['location_start_value'])) && !empty(trim($email_data['location_end_value']))) {
|
||||
$id = $f['id'];
|
||||
$location_start_value = $email_data['location_start_value'];
|
||||
$location_end_value = $email_data['location_end_value'];
|
||||
$location_start_id = getAddressId($location_start_value);
|
||||
if(empty($location_start_id)){
|
||||
$result = Geocode::geocodeAddress($location_start_value);
|
||||
$result["address"] = $location_start_value;
|
||||
$location_start_id= saveAddress($result);
|
||||
}
|
||||
$location_end_id = getAddressId($location_end_value);
|
||||
if(empty($location_end_id)){
|
||||
$result = Geocode::geocodeAddress($location_end_value);
|
||||
$result["address"] = $location_end_value;
|
||||
$location_end_id= saveAddress($result);
|
||||
}
|
||||
if ($location_start_id && $location_end_id) {
|
||||
updateParsedEmail($id, $location_start_id, $location_end_id);
|
||||
$success++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$failed++;
|
||||
}
|
||||
}
|
||||
|
||||
echo "Total: " . $total . ".\n";
|
||||
echo "Success: : " . $success . ".\n";
|
||||
echo "Failed: : " . $failed . ".\n";
|
||||
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] ".$job_name." job complete.\n";
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] parsedemail_item_fix_time_travel job is starting.\n";
|
||||
|
||||
require '../backend.php';
|
||||
|
||||
global $pgconn;
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$conn_string = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$pgconn = pg_connect($conn_string);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
|
||||
/*get travel_time is measured with seconds*/
|
||||
$total = $success = $failed = 0;
|
||||
|
||||
$r = get_duration_in_seconds();
|
||||
while ($f = pg_fetch_array($r, NULL, PGSQL_ASSOC)) {
|
||||
$total++;
|
||||
$id = $f['id'];
|
||||
$condition = "id=".$id;
|
||||
$duration = $f['new_duration'];
|
||||
$data = [
|
||||
"duration" => $duration
|
||||
];
|
||||
$updated = update_data($data, $condition);
|
||||
if ($updated > 0) {
|
||||
$success++;
|
||||
} else {
|
||||
$failed++;
|
||||
}
|
||||
}
|
||||
|
||||
echo "Total: " . $total . ".\n";
|
||||
echo "Success: : " . $success . ".\n";
|
||||
echo "Failed: : " . $failed . ".\n";
|
||||
pg_close($pgconn);
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] parsedemail_item_fix_time_travel job complete.\n";
|
||||
function get_duration_in_seconds()
|
||||
{
|
||||
global $readOnlyReplicaConn;
|
||||
$q = "SELECT id, DATE_PART('hour', travel_date_end - travel_date)*60+DATE_PART('minute', travel_date_end - travel_date) AS new_duration
|
||||
FROM parsedemail_item
|
||||
WHERE transport_provider_id IS NOT NULL
|
||||
GROUP BY id, DATE_PART('hour', travel_date_end - travel_date)*60+DATE_PART('minute', travel_date_end - travel_date)
|
||||
HAVING duration >DATE_PART('hour', travel_date_end - travel_date)*60+DATE_PART('minute', travel_date_end - travel_date)
|
||||
AND DATE_PART('hour', travel_date_end - travel_date)*60+DATE_PART('minute', travel_date_end - travel_date)>0";
|
||||
return pg_query($readOnlyReplicaConn, $q);
|
||||
}
|
||||
|
||||
function update_data($data, $condition="1=1")
|
||||
{
|
||||
global $pgconn;
|
||||
if (count($data)>0) {
|
||||
$data_update="updated=NOW()";
|
||||
foreach ($data as $field => $val) {
|
||||
$data_update .= ", ${field}=" . ($val == 'NULL' ? "NULL" : "'${val}'");
|
||||
}
|
||||
$q = "UPDATE parsedemail_item SET " . $data_update . " WHERE " . $condition . "";
|
||||
$r = pg_query($pgconn, $q);
|
||||
if ($r) {
|
||||
return pg_affected_rows($r);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] parsedemail_item_fix_time_travel job is starting.\n";
|
||||
|
||||
require '../backend.php';
|
||||
|
||||
global $pgconn;
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$conn_string = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$pgconn = pg_connect($conn_string);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
|
||||
/*get travel_time is measured with seconds*/
|
||||
$total = $success = $failed = 0;
|
||||
|
||||
$r=get_negative_durations();
|
||||
while ($f = pg_fetch_array($r, NULL, PGSQL_ASSOC)) {
|
||||
$total++;
|
||||
$id = $f['id'];
|
||||
$duration = $f['duration'];
|
||||
$travel_date = $f['travel_date'];
|
||||
$transport_provider_id = $f['transport_provider_id'];
|
||||
|
||||
if (in_array($transport_provider_id, [1,5])) {//Uber, GOJEK
|
||||
$travel_date_end = $f['new_travel_date_end'];
|
||||
if(empty($duration)){
|
||||
$duration = $f['new_duration'];
|
||||
}
|
||||
} else {
|
||||
$new_travel_date_end = (new DateTime($f['travel_date']))->modify('+'.$duration.' minutes');
|
||||
$travel_date_end=$new_travel_date_end->format('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
$condition = "id=".$id;
|
||||
$data = [
|
||||
"duration" => $duration,
|
||||
"transport_provider_id" => $transport_provider_id,
|
||||
"travel_date" => $travel_date,
|
||||
"travel_date_end" => $travel_date_end
|
||||
];
|
||||
$updated = update_data($data, $condition);
|
||||
if ($updated > 0) {
|
||||
$success++;
|
||||
} else {
|
||||
$failed++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
echo "Total: " . $total . ".\n";
|
||||
echo "Success: : " . $success . ".\n";
|
||||
echo "Failed: : " . $failed . ".\n";
|
||||
pg_close($pgconn);
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] parsedemail_item_fix_time_travel job complete.\n";
|
||||
|
||||
function get_negative_durations(){
|
||||
global $readOnlyReplicaConn;
|
||||
$q = "SELECT p.id,
|
||||
duration,
|
||||
DATE_PART('hour', travel_date_end - travel_date)*60+DATE_PART('minute', travel_date_end - travel_date) AS new_duration,
|
||||
travel_date,
|
||||
travel_date_end,
|
||||
travel_date_end + interval '1' day as new_travel_date_end,
|
||||
transport_provider_id,
|
||||
message,
|
||||
message_date
|
||||
FROM parsedemail_item p INNER JOIN trackedemail_item t on p.trackedemail_item_id=t.id
|
||||
WHERE transport_provider_id IS NOT NULL
|
||||
GROUP BY p.id,
|
||||
duration,
|
||||
DATE_PART('hour', travel_date_end - travel_date)*60+DATE_PART('minute', travel_date_end - travel_date),
|
||||
travel_date,
|
||||
travel_date_end,
|
||||
travel_date_end + interval '1' day,
|
||||
transport_provider_id,
|
||||
message,
|
||||
message_date
|
||||
HAVING DATE_PART('hour', travel_date_end - travel_date)*60+DATE_PART('minute', travel_date_end - travel_date)<0
|
||||
ORDER BY transport_provider_id ASC";
|
||||
return pg_query($readOnlyReplicaConn, $q);
|
||||
}
|
||||
|
||||
function update_data($data, $condition="1=1")
|
||||
{
|
||||
global $pgconn;
|
||||
if (count($data)>0) {
|
||||
$data_update="updated=NOW()";
|
||||
foreach ($data as $field => $val) {
|
||||
$data_update .= ", ${field}=" . ($val == 'NULL' ? "NULL" : "'${val}'");
|
||||
}
|
||||
$q = "UPDATE parsedemail_item SET " . $data_update . " WHERE " . $condition . "";
|
||||
$r = pg_query($pgconn, $q);
|
||||
if ($r) {
|
||||
return pg_affected_rows($r);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
$job_name ='parsedemail_item_fix_address';
|
||||
echo "[" . date("Y-m-d H:i:s") . "] ".$job_name." job is starting.\n";
|
||||
|
||||
require 'common/utils.php';
|
||||
require 'common/config.php';
|
||||
require 'common/address_city.php';
|
||||
require 'common/parser.php';
|
||||
require 'common/Geocode.php';
|
||||
|
||||
$total = $success = $failed = 0;
|
||||
|
||||
$q = "SELECT id, trackedemail_item_id
|
||||
FROM parsedemail_item_payment WHERE member_id is null;";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
while ($f = pg_fetch_assoc($r)) {
|
||||
$total++;
|
||||
$id = $f['id'];
|
||||
$email_id = $f['trackedemail_item_id'];
|
||||
if (!empty($email_id)) {
|
||||
$member_id = getTrackedEmail($email_id);
|
||||
if ($member_id) {
|
||||
updateParsedPayment($id, $member_id);
|
||||
$success++;
|
||||
}
|
||||
} else {
|
||||
$failed++;
|
||||
}
|
||||
}
|
||||
|
||||
echo "Total: " . $total . ".\n";
|
||||
echo "Success: : " . $success . ".\n";
|
||||
echo "Failed: : " . $failed . ".\n";
|
||||
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] ".$job_name." job complete.\n";
|
||||
|
||||
function getTrackedEmail($id)
|
||||
{
|
||||
global $readOnlyReplicaConn;
|
||||
$q = "SELECT member_id FROM trackedemail_item WHERE id = " . $id . "";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
if ($r && pg_num_rows($r) && $f = pg_fetch_assoc($r)) {
|
||||
return $f['member_id'];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function updateParsedPayment($id, $member_id)
|
||||
{
|
||||
global $conn;
|
||||
$q = "UPDATE parsedemail_item_payment SET member_id='" . $member_id . "' WHERE id = " . $id . "";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r) && $f = pg_fetch_assoc($r)) {
|
||||
return [$f, null];
|
||||
}
|
||||
return [null, pg_last_error($conn)];
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] parsedemail_item_cleanup job is starting.\n";
|
||||
|
||||
require '../backend.php';
|
||||
|
||||
global $pgconn;
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$conn_string = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$pgconn = pg_connect($conn_string);
|
||||
|
||||
$q = "SELECT t.member_id,travel_date ,transport_provider_id,location_start_id,location_end_id, duration, cost, count(*)
|
||||
FROM parsedemail_item p INNER JOIN trackedemail_item t on p.trackedemail_item_id=t.id
|
||||
WHERE cost > 0 and member_id>0 AND dup_id is NULL
|
||||
GROUP BY t.member_id,travel_date ,transport_provider_id,location_start_id,location_end_id, duration, cost
|
||||
HAVING count(*)>1
|
||||
ORDER BY count(*) DESC,member_id ASC";
|
||||
//$q = "SELECT id FROM parsedemail_item WHERE id>20209";
|
||||
$r = pg_query($pgconn, $q);
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
$condition = "travel_date ='".$f['travel_date']."' and duration=".$f['duration']." and cost=".$f['cost']." and transport_provider_id=".$f['transport_provider_id']." AND member_id=".$f['member_id'];
|
||||
$keep = getKeepId($condition);
|
||||
|
||||
while ($k = pg_fetch_assoc($keep)) {
|
||||
$id = $k['id'];
|
||||
$conditionUpdate = $condition.=" AND p.id!=".$id;
|
||||
updateDuplicate($conditionUpdate,$id);
|
||||
//var_dump($k);exit;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pg_close($pgconn);
|
||||
function getKeepId($condition)
|
||||
{
|
||||
global $pgconn;
|
||||
$q = "SELECT p.id,member_id, t.id as trackedemail_item_id,travel_date, travel_date_end,transport_provider_id,location_start_id,location_end_id
|
||||
FROM parsedemail_item p INNER JOIN trackedemail_item t on p.trackedemail_item_id=t.id
|
||||
WHERE ".$condition."
|
||||
ORDER BY p.id ASC LIMIT 1";echo $q."\n";
|
||||
$r = pg_query($pgconn, $q);
|
||||
return $r;
|
||||
}
|
||||
|
||||
function updateDuplicate($condition,$dup_id){
|
||||
global $pgconn;
|
||||
$q="UPDATE
|
||||
parsedemail_item p
|
||||
SET
|
||||
dup_id=".$dup_id."
|
||||
FROM
|
||||
trackedemail_item t
|
||||
WHERE
|
||||
p.trackedemail_item_id = t.id
|
||||
AND ".$condition."";
|
||||
echo $q."\n";
|
||||
$r = pg_query($pgconn, $q);
|
||||
return $r;
|
||||
|
||||
}
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] parsedemail_item_cleanup job complete.\n";
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] parsedemail_item_update_base_cost job is starting.\n";
|
||||
|
||||
require '../backend.php';
|
||||
|
||||
global $pgconn, $readOnlyReplicaConn;
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$conn_string = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$pgconn = pg_connect($conn_string);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
|
||||
/*get travel_time is measured with seconds*/
|
||||
$q = "SELECT p.id, cost, promotions_credits
|
||||
FROM parsedemail_item p LEFT JOIN parsedemail_item_extra pa ON p.id=pa.parsedemail_item_id";
|
||||
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
$total = $success = $failed = 0;
|
||||
while ($f = pg_fetch_row($r)) {
|
||||
$total ++;
|
||||
$id = $f[0];
|
||||
$cost = $f[1];
|
||||
$promotions_credits = $f[2];
|
||||
//echo $cost,$promotions_credits;
|
||||
$base_cost = $cost+abs($promotions_credits);
|
||||
$updated = update_base_cost($id,$base_cost);
|
||||
if($updated>0){
|
||||
$success++;
|
||||
}else{
|
||||
$failed++;
|
||||
}
|
||||
}
|
||||
echo "Total: ".$total.".\n";
|
||||
echo "Success: : ".$success.".\n";
|
||||
echo "Failed: : ".$failed.".\n";
|
||||
pg_close($readOnlyReplicaConn);
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] parsedemail_item_update_base_cost job complete.\n";
|
||||
|
||||
function update_base_cost($id, $base_cost) {
|
||||
global $pgconn;
|
||||
$q = "UPDATE parsedemail_item SET base_cost=" . $base_cost . " WHERE id=" . $id . "";
|
||||
$r = pg_query($pgconn, $q);
|
||||
if ($r) {
|
||||
return pg_affected_rows($r);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
echo "[".date("Y-m-d H:i:s")."] Decision Generator job is starting.\n";
|
||||
include '../backend.php';
|
||||
define("FLOAT_SYSTEM_POINTS_GENERATOR", 92022);
|
||||
|
||||
function Fextension_call($in, &$out) {
|
||||
// logToFl("Merchant_Name count->" . $in["merchant_name"]);
|
||||
global $savvyext;
|
||||
$out = $savvyext->savvyext_api($in);
|
||||
$ret = $out["retval"];
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$inX["limit"] = 25;
|
||||
$inX["pid"] = 0;
|
||||
$inX["action"] = FLOAT_SYSTEM_POINTS_GENERATOR;
|
||||
$outX=array();
|
||||
|
||||
|
||||
$extension_call = true;
|
||||
|
||||
if ($extension_call == true ) {
|
||||
// logToFl("merchant_name count->" . $res->merchant_name);
|
||||
Fextension_call($inX, $outX);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
session_start();
|
||||
echo "[" . date("Y-m-d H:i:s") . "] GPS quotes_update_travel_time job is starting.\n";
|
||||
|
||||
require 'common/utils.php';
|
||||
require 'common/config.php';
|
||||
require 'common/address_city.php';
|
||||
$total = $success = $failed = 0;
|
||||
$conditions = [
|
||||
"completed is not null AND travel_date is null",//
|
||||
];
|
||||
$limit =100;
|
||||
$arr_timezones = [
|
||||
|
||||
];//address_id, timezone
|
||||
$start = floor(microtime(true)*1000);
|
||||
foreach ($conditions as $condition) {
|
||||
$total = getTotalQuotesByCondition($condition);
|
||||
for($i=0; $i<$total;$i+=$limit){
|
||||
$offset =$i;
|
||||
$quotes = getQuotesByCondition($condition,$limit, $offset);
|
||||
while ($f = pg_fetch_assoc($quotes)) {
|
||||
|
||||
$total++;
|
||||
$id = $f['id'];
|
||||
$completed = $f['completed'];
|
||||
if (!array_key_exists($f['location_start_id'], $arr_timezones)) {
|
||||
echo "query time zone==========================================\n";
|
||||
$timezone = getTzByAddressId($f['location_start_id']);
|
||||
$arr_timezones[$f['location_start_id']] = $timezone;
|
||||
}
|
||||
$timezone = $arr_timezones[$f['location_start_id']];
|
||||
$travel_date = convertUtcToLocal($completed, $timezone);
|
||||
$data_update = [
|
||||
'travel_date' => $travel_date,
|
||||
];
|
||||
$condition_update = "id = " . $id . "";
|
||||
$startu = floor(microtime(true)*1000);
|
||||
$updated = updateDataTable('quotes', $condition_update, $data_update);
|
||||
$endu = floor(microtime(true)*1000);
|
||||
$durationu=$endu-$startu;
|
||||
echo $durationu." miliseconds ********************************************\n";
|
||||
if ($updated) {
|
||||
$success++;
|
||||
} else {
|
||||
$failed++;
|
||||
}
|
||||
}
|
||||
if($i==200){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$end = floor(microtime(true)*1000);
|
||||
$duration = $end -$start;
|
||||
|
||||
echo "start: " . $start . ".\n";
|
||||
echo "end: " . $end . ".\n";
|
||||
echo "duration: " . $duration . " miliseconds.\n";
|
||||
echo "Total: " . $total . ".\n";
|
||||
echo "Success: : " . $success . ".\n";
|
||||
echo "Failed: : " . $failed . ".\n";
|
||||
echo "[" . date("Y-m-d H:i:s") . "] quotes_update_travel_time job complete.\n";
|
||||
|
||||
function getQuotesByCondition($condition, $limit=10, $offset=0)
|
||||
{
|
||||
global $readOnlyReplicaConn;
|
||||
$q = "SELECT id,created,completed,location_start_id, location_end_id, travel_date
|
||||
FROM quotes
|
||||
WHERE " . $condition . "
|
||||
ORDER BY id DESC
|
||||
LIMIT ".$limit." offset ". $offset."";
|
||||
echo $q."\n";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
return $r;
|
||||
}
|
||||
|
||||
function getTotalQuotesByCondition($condition)
|
||||
{
|
||||
global $readOnlyReplicaConn;
|
||||
$q = "SELECT count(*) as total
|
||||
FROM quotes
|
||||
WHERE " . $condition . "
|
||||
";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
while ($f=pg_fetch_array($r)) {
|
||||
return $f['total'];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
<?php
|
||||
|
||||
// require_once( '/Users/osx/Sites/Float/adminsavvy/backend.php' );
|
||||
include '../backend.php';
|
||||
require_once('../vendor/autoload.php');
|
||||
require_once( 'common/Logger.php' );
|
||||
|
||||
use \SendGrid\Mail\Mail;
|
||||
|
||||
/**
|
||||
* Send list email parsed fail report
|
||||
*/
|
||||
class SendEmailReceiptFail {
|
||||
|
||||
public $conn;
|
||||
public $repConn;
|
||||
|
||||
public $sendgrid_api;
|
||||
public $sender;
|
||||
public $sender_name;
|
||||
public $receivers;
|
||||
|
||||
protected $hard_limit = 550;
|
||||
|
||||
function __construct() {
|
||||
global $savvyext;
|
||||
$this->conn = self::__cnn( $savvyext );
|
||||
$this->repConn = self::__repCnn( $savvyext );
|
||||
|
||||
$this->sendgrid_api = $savvyext->cfgReadChar('mailsend.api_key');
|
||||
$this->sender = $savvyext->cfgReadChar('mailsend.from');
|
||||
$this->sender_name = $savvyext->cfgReadChar('mailsend.name');
|
||||
$this->receivers = array(
|
||||
'stew@float.sg' => 'Stew',
|
||||
'olu@float.sg' => 'Olu',
|
||||
'chelsea@float.sg' => 'Chelsea',
|
||||
'cornel@float.sg' => 'Cornel',
|
||||
'lviet@float.sg' => 'Le Viet',
|
||||
'tnguyen@float.sg' => 'Tri Nguyen',
|
||||
'helen@goldenowl.asia' => 'Helen',
|
||||
'george@goldenowl.asia' => 'George',
|
||||
);
|
||||
}
|
||||
|
||||
private static function __cnn( $savvyext ) {
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = sprintf( 'host=%s port=%s dbname=%s user=%s password=%s', $db_host, $db_port, $db_name, $db_user, $db_pass );
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
return $conn;
|
||||
}
|
||||
|
||||
private static function __repCnn( $savvyext ) {
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$connstr = sprintf( 'host=%s port=%s dbname=%s user=%s password=%s', $db_host, $db_port, $db_name, $db_user, $db_pass );
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
return $conn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send email report via SendGrid
|
||||
* @param array $data list email fail
|
||||
* @return mixed
|
||||
*/
|
||||
protected function send( $data ) {
|
||||
// create email layout
|
||||
ob_start();
|
||||
require_once( __DIR__ . '/email/email-parsed-fail.php' );
|
||||
$layout = ob_get_clean();
|
||||
// create sendgrid instance
|
||||
$sendgrid = new \SendGrid\Mail\Mail;
|
||||
$sendgrid->setFrom( $this->sender, $this->sender_name );
|
||||
$currentDate = date('D M j G:i');
|
||||
$last7days = date('D M j', strtotime('-7 days'));
|
||||
$sendgrid->setSubject("Report: Failed email parsers last 7 days - From $last7days to $currentDate UTC");
|
||||
$sendgrid->addTos( $this->receivers );
|
||||
$sendgrid->addContent( 'text/html', $layout );
|
||||
|
||||
// send
|
||||
$send = new \SendGrid( $this->sendgrid_api );
|
||||
$response = $send->send( $sendgrid );
|
||||
|
||||
if ( $response->statusCode() !== 202 ) {
|
||||
throw new Exception( 'Send email via Sendgrid get errors!' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all email receipt parsed fail
|
||||
* @return array
|
||||
*/
|
||||
public function getemails() {
|
||||
try {
|
||||
$sql = "
|
||||
SELECT pf.name AS merchant_name, ti.id AS trackedemail_item_id, m.email, m.id AS user_id, ti.subject, ti.message_date,
|
||||
CASE WHEN pf.reported_via_email IS TRUE THEN 'Yes' ELSE 'No' END AS reported
|
||||
FROM trackedemail_item ti
|
||||
INNER JOIN members m ON m.id = ti.member_id
|
||||
INNER JOIN (
|
||||
SELECT trackedemail_item_id, tp.name, reported_via_email
|
||||
FROM parsedemail_item_failed pi
|
||||
LEFT JOIN transport_providers tp ON tp.id = pi.transport_provider_id
|
||||
WHERE pi.parsed_status = 0 AND pi.added > CURRENT_DATE - 7
|
||||
) pf ON pf.trackedemail_item_id = ti.id
|
||||
WHERE ti.parsed_status = 0 AND date_parsed IS NOT NULL";
|
||||
|
||||
$results = pg_query( $this->repConn, $sql );
|
||||
|
||||
if ( $error = pg_last_error( $this->repConn ) ) {
|
||||
throw new Exception( $error );
|
||||
}
|
||||
|
||||
$results = pg_fetch_all( $results );
|
||||
|
||||
if (!$results) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$new_parsed_fail_email_arr = [];
|
||||
|
||||
foreach ($results as &$item) {
|
||||
// Save trackedemail item id for updating col 'reported_via_email' in table 'parsedemail_item_failed'
|
||||
if ($item['reported'] === 'No') {
|
||||
array_push($new_parsed_fail_email_arr, $item['trackedemail_item_id']);
|
||||
}
|
||||
}
|
||||
|
||||
return [$results, $new_parsed_fail_email_arr];
|
||||
|
||||
} catch (Exception $e) {
|
||||
Logger::debug( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Excute jobs
|
||||
* @return mixed
|
||||
*/
|
||||
public function excute() {
|
||||
try {
|
||||
list($data['emails'], $data['new_parsed_fail_email']) = $this->getemails();
|
||||
$data['summary']= $this->getReportByMerchantName();
|
||||
|
||||
if (empty($data['emails']) && empty($data['summary'])) {
|
||||
throw new Exception( 'No Email Receipt which parsed failed!' );
|
||||
}
|
||||
|
||||
$send = $this->send( $data );
|
||||
|
||||
// After report email has been sent, we will change 'reported_via_email' status
|
||||
if (!empty($data['new_parsed_fail_email'])) {
|
||||
foreach ($data['new_parsed_fail_email'] ?? [] as $email_id) {
|
||||
$sql = "UPDATE parsedemail_item_failed SET reported_via_email = TRUE WHERE trackedemail_item_id = $email_id";
|
||||
pg_query( $this->repConn, $sql );
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
Logger::debug( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
public function getReportByMerchantName() {
|
||||
$results = [];
|
||||
|
||||
$sql = "
|
||||
SELECT count(*) AS success, tp.name, tp.category
|
||||
FROM parsedemail_item pi
|
||||
LEFT JOIN transport_providers tp ON tp.id = pi.transport_provider_id
|
||||
WHERE pi.transport_provider_id IS NOT NULL AND pi.updated > CURRENT_DATE - 7
|
||||
GROUP BY pi.transport_provider_id, tp.name, tp.category";
|
||||
|
||||
$q = pg_query($this->repConn, $sql);
|
||||
$parsedSuccessSummary = pg_fetch_all($q);
|
||||
|
||||
if (!$parsedSuccessSummary) {
|
||||
$parsedSuccessSummary = [];
|
||||
}
|
||||
|
||||
$sql = "
|
||||
SELECT count(*) AS fail, tp.name, tp.category
|
||||
FROM parsedemail_item_failed pi
|
||||
LEFT JOIN transport_providers tp ON tp.id = pi.transport_provider_id
|
||||
WHERE pi.transport_provider_id IS NOT NULL AND pi.added > CURRENT_DATE - 7
|
||||
GROUP BY pi.transport_provider_id, tp.name, tp.category";
|
||||
|
||||
$q = pg_query($this->repConn, $sql);
|
||||
$parsedFailSummary = pg_fetch_all($q);
|
||||
|
||||
if (!$parsedFailSummary) {
|
||||
$parsedFailSummary = [];
|
||||
}
|
||||
|
||||
if (!$parsedSuccessSummary && !$parsedFailSummary) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Combine success and fail summary
|
||||
foreach ($parsedFailSummary as $item) {
|
||||
$isExistTranportProvider = false;
|
||||
|
||||
foreach ($parsedSuccessSummary as $item2) {
|
||||
if ($item2['name'] === $item['name']) {
|
||||
$isExistTranportProvider = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isExistTranportProvider) {
|
||||
array_push($parsedSuccessSummary, $item);
|
||||
}
|
||||
}
|
||||
|
||||
// Combine success and fail summary
|
||||
foreach ($parsedSuccessSummary as $item) {
|
||||
foreach ($parsedFailSummary as $item2) {
|
||||
if ($item2['name'] === $item['name']) {
|
||||
$item['fail'] = $item2['fail'];
|
||||
}
|
||||
}
|
||||
|
||||
$item['fail'] = $item['fail'] ?? 0;
|
||||
$item['success'] = $item['success'] ?? 0;
|
||||
|
||||
// Set transport
|
||||
if ($item['category'] !== 'Retail' && $item['category'] !== null) {
|
||||
$item['transport'] = 'Yes';
|
||||
} else {
|
||||
$item['transport'] = 'No';
|
||||
}
|
||||
|
||||
unset($item['category']);
|
||||
|
||||
array_push($results, $item);
|
||||
}
|
||||
|
||||
// Calculate total for each merchant name
|
||||
foreach ($results as &$result) {
|
||||
$result['total'] = intval($result['success']) + intval($result['fail']);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
|
||||
$instace = new SendEmailReceiptFail;
|
||||
$instace->excute();
|
||||
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] GPS singaport_mrtlrt_stop_fares job is starting.\n";
|
||||
|
||||
require('../backend.php');
|
||||
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
|
||||
$q = 'SELECT line,count(*) FROM singapore_bus_stops GROUP BY line';
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
while ($f=pg_fetch_row($r)) {
|
||||
singapore_bus_stops_line($f[0]);
|
||||
}
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] GPS singaport_mrtlrt_stop_fares job complete.\n";
|
||||
|
||||
function singapore_bus_stops_line($id) {
|
||||
global $readOnlyReplicaConn;
|
||||
$q = "SELECT * FROM singapore_bus_stops WHERE line='${id}'";
|
||||
$r = pg_query($readOnlyReplicaConn,$q);
|
||||
while ($from=pg_fetch_assoc($r)) {
|
||||
singapore_bus_stops_line_fares($id,$from);
|
||||
}
|
||||
}
|
||||
|
||||
function singapore_bus_stops_line_fares($id,$from) {
|
||||
global $readOnlyReplicaConn;
|
||||
$q = "SELECT * FROM singapore_bus_stops WHERE line='${id}' AND id<>".$from["id"]." ORDER BY RANDOM()";
|
||||
$r = pg_query($readOnlyReplicaConn,$q);
|
||||
while ($to=pg_fetch_assoc($r)) {
|
||||
singapore_bus_stops_line_fare($id,$from,$to);
|
||||
}
|
||||
}
|
||||
/*
|
||||
CREATE TABLE singapore_bus_stop_fares (id serial, boarding_id int references singapore_bus_stops(id), alight_id int references singapore_bus_stops(id), fare int, distance int, primary key(id), unique(boarding_id,alight_id));
|
||||
*/
|
||||
function singapore_bus_stops_line_fare($line,$from,$to) {
|
||||
global $conn, $readOnlyReplicaConn;
|
||||
echo "from=".$from["code"].", to=".$to["code"]."\n";
|
||||
$q = "SELECT * FROM singapore_bus_stop_fares WHERE boarding_id='".$from["id"]."'";
|
||||
$q.= " AND alight_id='".$to["id"]."'";
|
||||
$r = pg_query($readOnlyReplicaConn,$q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) {
|
||||
// Update
|
||||
if ($f["fare"]>0) {
|
||||
$q = "";
|
||||
} else {
|
||||
$q = "UPDATE singapore_bus_stop_fares SET fare=%d, distance=%d WHERE id=".$f["id"]." RETURNING id";
|
||||
}
|
||||
} else {
|
||||
// Insert
|
||||
$q = "INSERT INTO singapore_bus_stop_fares (boarding_id,alight_id,fare,distance) VALUES(";
|
||||
$q.= $from["id"].",".$to["id"].",%d,%d) RETURNING id";
|
||||
}
|
||||
if ($q!="") {
|
||||
$entryId = $from["code"];
|
||||
$exitId = $to["code"];
|
||||
list($res, $err) = getMyTransportSGQuote($line,$entryId,$exitId);
|
||||
if (is_array($res) && array_key_exists('data',$res) && is_array($res['data']) && array_key_exists('fare_raw',$res['data']) && $res['data']['fare_raw']>0) {
|
||||
$fare_raw = $res['data']['fare_raw'];
|
||||
$distance = $res['data']['distance_raw'] * 10;
|
||||
echo "--> ${fare_raw} (".$res['data']['distance']." => ${distance})\n";
|
||||
$q = sprintf($q, $fare_raw, $distance);
|
||||
//echo "$q\n";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) {
|
||||
echo "--> success: id=".$f[0]."\n";
|
||||
} else {
|
||||
echo "--> failure: ".pg_last_error($conn)."\n";
|
||||
}
|
||||
//var_dump($res);
|
||||
//var_dump($err);
|
||||
} else {
|
||||
echo "ERROR: $err\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getMyTransportSGQuote($line,$entryId,$exitId) {
|
||||
|
||||
$url = 'https://www.mytransport.sg/content/mytransport/home/commuting/busservices/jcr:content/par/mtp_generic_tab/mtp_generic_tab6/distancefare.busFare?busServiceId='.$line.'&entryMarkerId='.$entryId.'&exitMarkerId='.$exitId.'&ticketType=30&tripContextParameter=&tripId=1';
|
||||
$ch = curl_init($url);
|
||||
|
||||
//Create And Save Cookies
|
||||
/*
|
||||
$tmpfname = dirname(__FILE__).'/cookie.txt';
|
||||
curl_setopt($ch, CURLOPT_COOKIEJAR, $tmpfname);
|
||||
curl_setopt($ch, CURLOPT_COOKIEFILE, $tmpfname);
|
||||
*/
|
||||
/*
|
||||
Host: www.mytransport.sg
|
||||
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0
|
||||
Accept: *//*
|
||||
Accept-Language: en-US,en;q=0.5
|
||||
Accept-Encoding: gzip, deflate, br
|
||||
Referer: https://www.mytransport.sg/content/mytransport/home/commuting/busservices.html
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Connection: keep-alive
|
||||
Cookie: mtp_last_visit=Fare Calculator|/content/mytransport/home/commuting/busservices.html#Fare_Calculator,Bus Arrival Time|/content/mytransport/home/commuting/busservices.html#Bus_Arrival_Time,Bus Services|/content/mytransport/home/commuting/busservices.html; s_fid=1A0D8455C75F0629-03AFA1ACC259519D; s_cc=true
|
||||
*/
|
||||
$cookies = 'mtp_last_visit=Fare Calculator|/content/mytransport/home/commuting/busservices.html#Fare_Calculator,Bus Arrival Time|/content/mytransport/home/commuting/busservices.html#Bus_Arrival_Time,Bus Services|/content/mytransport/home/commuting/busservices.html; s_fid=1A0D8455C75F0629-03AFA1ACC259519D; s_cc=true';
|
||||
//'mtp_last_visit=Fare Calculator|/content/mytransport/home/commuting/busservices.html#Fare_Calculator,Bus Services|/content/mytransport/home/commuting/busservices.html';
|
||||
$headers = [
|
||||
'Accept: */*',
|
||||
'Accept-Language: en-US,en;q=0.5',
|
||||
'X-Requested-With: XMLHttpRequest',
|
||||
'Accept-Encoding: gzip, deflate, br'
|
||||
];
|
||||
curl_setopt($ch, CURLOPT_HEADER, false);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
//curl_setopt($ch, CURLOPT_HEADER, true);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
|
||||
curl_setopt($ch, CURLOPT_REFERER, 'https://www.mytransport.sg/content/mytransport/home/commuting/busservices.html');
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0');
|
||||
//curl_setopt($ch, CURLINFO_HEADER_OUT, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
|
||||
curl_setopt($ch, CURLOPT_COOKIE, $cookies);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
//https://stackoverflow.com/questions/310650/decode-gzipped-web-page-retrieved-via-curl-in-php
|
||||
curl_setopt($ch, CURLOPT_ENCODING , "gzip");
|
||||
|
||||
// EXECUTE
|
||||
sleep(1);
|
||||
$html = curl_exec($ch);
|
||||
//error_log($url);
|
||||
//error_log($html);
|
||||
//echo trim($html);
|
||||
curl_close($ch);
|
||||
|
||||
$dom = new DOMDocument;
|
||||
libxml_use_internal_errors(true);
|
||||
$dom->loadHTML(trim($html));
|
||||
$finder = new DomXPath($dom);
|
||||
|
||||
// distance_fare_result_nm => Trip 1
|
||||
// distance_fare_result_sv => Bus Svc 41
|
||||
// distance_fare_result_bd => 28641 - Blk 284
|
||||
// distance_fare_result_al => 42209 - Aft Toh Tuck Rise
|
||||
// distance_fare_result_dt => 7.7 km
|
||||
// distance_fare_result_fr => $1.29
|
||||
// fare_raw => 129
|
||||
// distance_raw => 770
|
||||
|
||||
$data = array(
|
||||
'name' => getItem($finder,'distance_fare_result_nm'),
|
||||
'service' => getItem($finder,'distance_fare_result_sv'),
|
||||
'board' => getItem($finder,'distance_fare_result_bd'),
|
||||
'alight' => getItem($finder,'distance_fare_result_al'),
|
||||
'distance' => getItem($finder,'distance_fare_result_dt'),
|
||||
'fare' => getItem($finder,'distance_fare_result_fr'),
|
||||
'fare_raw' => getItem($finder,'fare_raw'),
|
||||
'distance_raw' => getItem($finder,'distance_raw')
|
||||
);
|
||||
|
||||
return [['data'=>$data],$html];
|
||||
}
|
||||
|
||||
function getItem($finder,$class,$default='') {
|
||||
$nlist = $finder->query("//*[@class='${class}']");
|
||||
if ($nlist->length>0) {
|
||||
$item = $nlist->item(0);
|
||||
return $item->textContent;
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] GPS singaport_mrtlrt_stop_fares job is starting.\n";
|
||||
|
||||
require('../backend.php');
|
||||
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
|
||||
$q = "SELECT * FROM singapore_mrtlrt_stops_mytransport ORDER BY RANDOM()";
|
||||
$r = pg_query($readOnlyReplicaConn, $q);
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
singapore_mrtlrt_stop_fares($f);
|
||||
}
|
||||
|
||||
echo "[".date("Y-m-d H:i:s")."] GPS singaport_mrtlrt_stop_fares job complete.\n";
|
||||
|
||||
function singapore_mrtlrt_stop_fares($from) {
|
||||
global $readOnlyReplicaConn;
|
||||
$q = "SELECT * FROM singapore_mrtlrt_stops_mytransport WHERE id<>".$from["id"]." ORDER BY RANDOM()";
|
||||
$r = pg_query($readOnlyReplicaConn,$q);
|
||||
while ($to=pg_fetch_assoc($r)) {
|
||||
singapore_mrtlrt_stop_fare($from,$to);
|
||||
}
|
||||
}
|
||||
|
||||
function singapore_mrtlrt_stop_fare($from,$to) {
|
||||
global $conn, $readOnlyReplicaConn;
|
||||
echo "from=".$from["code1"]."_".$from["code2"].", to=".$to["code1"]."_".$to["code2"]."\n";
|
||||
$q = "SELECT * FROM singapore_mrtlrt_stop_fares WHERE boarding_id='".$from["id"]."'";
|
||||
$q.= " AND alight_id='".$to["id"]."'";
|
||||
$r = pg_query($readOnlyReplicaConn,$q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) {
|
||||
// Update
|
||||
if ($f["fare"]>0) {
|
||||
$q = "";
|
||||
} else {
|
||||
$q = "UPDATE singapore_mrtlrt_stop_fares SET fare=%d, distance=%d WHERE id=".$f["id"]." RETURNING id";
|
||||
}
|
||||
} else {
|
||||
// Insert
|
||||
$q = "INSERT INTO singapore_mrtlrt_stop_fares (boarding_id,alight_id,fare,distance) VALUES(";
|
||||
$q.= $from["id"].",".$to["id"].",%d,%d) RETURNING id";
|
||||
}
|
||||
if ($q!="") {
|
||||
$entryId = $from["code1"] . "_" . $from["code2"];
|
||||
$exitId = $to["code1"] . "_" . $to["code2"];
|
||||
list($res, $err) = getMyTransportSGQuote($entryId,$exitId);
|
||||
if (is_array($res) && array_key_exists('data',$res) && is_array($res['data']) && array_key_exists('fare_raw',$res['data']) && $res['data']['fare_raw']>0) {
|
||||
$fare_raw = $res['data']['fare_raw'];
|
||||
$distance = $res['data']['distance_raw'] * 10;
|
||||
echo "--> ${fare_raw} (".$res['data']['distance']." => ${distance})\n";
|
||||
$q = sprintf($q, $fare_raw, $distance);
|
||||
//echo "$q\n";
|
||||
$r = pg_query($conn, $q);
|
||||
if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) {
|
||||
echo "--> success: id=".$f[0]."\n";
|
||||
} else {
|
||||
echo "--> failure: ".pg_last_error($conn)."\n";
|
||||
}
|
||||
} else {
|
||||
echo "ERROR: $err\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getMyTransportSGQuote($entryId,$exitId) {
|
||||
|
||||
$url = 'https://www.mytransport.sg/content/mytransport/home/commuting/busservices/jcr:content/par/mtp_generic_tab/mtp_generic_tab6/distancefare.mrtFare?entryMarkerId='.$entryId.'&exitMarkerId='.$exitId.'&ticketType=30&tripContextParameter=&tripId=1';
|
||||
$ch = curl_init($url);
|
||||
|
||||
//Create And Save Cookies
|
||||
/*
|
||||
$tmpfname = dirname(__FILE__).'/cookie.txt';
|
||||
curl_setopt($ch, CURLOPT_COOKIEJAR, $tmpfname);
|
||||
curl_setopt($ch, CURLOPT_COOKIEFILE, $tmpfname);
|
||||
*/
|
||||
$cookies = 'mtp_last_visit=Fare Calculator|/content/mytransport/home/commuting/busservices.html#Fare_Calculator,Bus Services|/content/mytransport/home/commuting/busservices.html';
|
||||
$headers = [
|
||||
'X-Requested-With: XMLHttpRequest',
|
||||
'Sec-Fetch-Mode: cors',
|
||||
'Sec-Fetch-Site: same-origin'
|
||||
];
|
||||
curl_setopt($ch, CURLOPT_HEADER, false);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
//curl_setopt($ch, CURLOPT_HEADER, true);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
|
||||
curl_setopt($ch, CURLOPT_REFERER, 'https://www.mytransport.sg/content/mytransport/home/commuting/busservices.html');
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36');
|
||||
//curl_setopt($ch, CURLINFO_HEADER_OUT, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
|
||||
curl_setopt($ch, CURLOPT_COOKIE, $cookies);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
//https://stackoverflow.com/questions/310650/decode-gzipped-web-page-retrieved-via-curl-in-php
|
||||
curl_setopt($ch, CURLOPT_ENCODING , "gzip");
|
||||
|
||||
// EXECUTE
|
||||
sleep(1);
|
||||
$html = curl_exec($ch);
|
||||
//error_log($url);
|
||||
//error_log($html);
|
||||
//echo trim($html);
|
||||
curl_close($ch);
|
||||
|
||||
$dom = new DOMDocument;
|
||||
libxml_use_internal_errors(true);
|
||||
$dom->loadHTML(trim($html));
|
||||
$finder = new DomXPath($dom);
|
||||
|
||||
// distance_fare_result_nm => Trip 1
|
||||
// distance_fare_result_sv => Bus Svc 41
|
||||
// distance_fare_result_bd => 28641 - Blk 284
|
||||
// distance_fare_result_al => 42209 - Aft Toh Tuck Rise
|
||||
// distance_fare_result_dt => 7.7 km
|
||||
// distance_fare_result_fr => $1.29
|
||||
// fare_raw => 129
|
||||
// distance_raw => 770
|
||||
|
||||
$data = array(
|
||||
'name' => getItem($finder,'distance_fare_result_nm'),
|
||||
'service' => getItem($finder,'distance_fare_result_sv'),
|
||||
'board' => getItem($finder,'distance_fare_result_bd'),
|
||||
'alight' => getItem($finder,'distance_fare_result_al'),
|
||||
'distance' => getItem($finder,'distance_fare_result_dt'),
|
||||
'fare' => getItem($finder,'distance_fare_result_fr'),
|
||||
'fare_raw' => getItem($finder,'fare_raw'),
|
||||
'distance_raw' => getItem($finder,'distance_raw')
|
||||
);
|
||||
|
||||
return [['data'=>$data],$html];
|
||||
}
|
||||
|
||||
function getItem($finder,$class,$default='') {
|
||||
$nlist = $finder->query("//*[@class='${class}']");
|
||||
if ($nlist->length>0) {
|
||||
$item = $nlist->item(0);
|
||||
return $item->textContent;
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
<?php
|
||||
|
||||
// require_once( '/Users/osx/Sites/Float/adminsavvy/backend.php' );
|
||||
include '../backend.php';
|
||||
require_once( 'common/Logger.php' );
|
||||
|
||||
/**
|
||||
* Transfer Subscription Report
|
||||
*/
|
||||
class SubscribedSummary {
|
||||
|
||||
public $conn;
|
||||
public $repConn;
|
||||
|
||||
protected $hard_limit = 550;
|
||||
|
||||
function __construct() {
|
||||
global $savvyext;
|
||||
$this->conn = self::__cnn( $savvyext );
|
||||
$this->repConn = self::__repCnn( $savvyext );
|
||||
}
|
||||
|
||||
private static function __cnn( $savvyext ) {
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
$connstr = sprintf( 'host=%s port=%s dbname=%s user=%s password=%s', $db_host, $db_port, $db_name, $db_user, $db_pass );
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
return $conn;
|
||||
}
|
||||
|
||||
private static function __repCnn( $savvyext ) {
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$connstr = sprintf( 'host=%s port=%s dbname=%s user=%s password=%s', $db_host, $db_port, $db_name, $db_user, $db_pass );
|
||||
$conn = pg_connect($connstr);
|
||||
|
||||
return $conn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all members_card_assign items
|
||||
* @return array
|
||||
*/
|
||||
public function getDeals() {
|
||||
try {
|
||||
// get all deals card
|
||||
$sql = sprintf( "
|
||||
SELECT
|
||||
mc.id as cardid,
|
||||
case when mc.card_country is null then 'Worldwide' else mc.card_country end as country
|
||||
from main_cards mc
|
||||
where mc.button1_action in ('GOOFFERS')
|
||||
and mc.status = 1
|
||||
" );
|
||||
|
||||
$results = pg_query( $this->repConn, $sql );
|
||||
|
||||
if ( $error = pg_last_error( $this->repConn ) ) {
|
||||
throw new Exception( $error );
|
||||
}
|
||||
|
||||
$results = pg_fetch_all( $results );
|
||||
|
||||
return $results;
|
||||
|
||||
} catch (Exception $e) {
|
||||
Logger::debug( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total redeem by cards
|
||||
* @param array $card_ids list card ids
|
||||
* @return array
|
||||
*/
|
||||
private function getRedeem( $card_ids ) {
|
||||
$redeem = sprintf("
|
||||
SELECT
|
||||
mca.card_id as cardid,
|
||||
count( mca ) as redeem
|
||||
from members_card_assign mca
|
||||
left join main_cards mc ON mc.id = mca.card_id
|
||||
where
|
||||
mca.completed is not null
|
||||
and mca.status = 1
|
||||
and mca.card_id in (%s)
|
||||
group by cardid
|
||||
", $card_ids);
|
||||
$results = pg_query( $this->repConn, $redeem );
|
||||
|
||||
if ( $error = pg_last_error( $this->repConn ) ) {
|
||||
throw new Exception( $error );
|
||||
}
|
||||
|
||||
$redeem = pg_fetch_all( $results );
|
||||
|
||||
return $redeem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total report
|
||||
* @param array $card_ids list card ids
|
||||
* @return array
|
||||
*/
|
||||
private function getReport( $card_ids ) {
|
||||
$report = sprintf( "
|
||||
SELECT
|
||||
mca.card_id as cardid,
|
||||
sum( case when mca.added between now() - interval '24 hours' and now() then 1 else 0 end ) as last_24hours,
|
||||
sum( case when mca.added between now() - interval '7 days' and now() then 1 else 0 end ) as last_7days,
|
||||
sum( case when mca.added between now() - interval '14 days' and now() then 1 else 0 end ) as last_14days,
|
||||
sum( case when mca.added between now() - interval '30 days' and now() then 1 else 0 end ) as last_30days,
|
||||
count( mca.id ) as total_sub
|
||||
from members_card_assign mca
|
||||
left join main_cards mc ON mc.id = mca.card_id
|
||||
where
|
||||
mc.card_reciept is not null
|
||||
and mca.subscribe is not null
|
||||
and mca.completed is null
|
||||
and mca.reciept_count = 0
|
||||
and mca.card_id in (%s)
|
||||
group by cardid
|
||||
", $card_ids );
|
||||
$results = pg_query( $this->repConn, $report );
|
||||
|
||||
if ( $error = pg_last_error( $this->repConn ) ) {
|
||||
throw new Exception( $error );
|
||||
}
|
||||
|
||||
$report = pg_fetch_all( $results );
|
||||
|
||||
return $report;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all subscribed report
|
||||
* @return array
|
||||
*/
|
||||
public function getSubscripbed() {
|
||||
$deals = $this->getDeals();
|
||||
try {
|
||||
if ( !$deals ) {
|
||||
throw new Exception( 'Deals card not found!' );
|
||||
}
|
||||
|
||||
$card_ids = implode( ', ', array_column( $deals, 'cardid' ) );
|
||||
// get subscribed total redeem
|
||||
$redeem = $this->getRedeem( $card_ids );
|
||||
// get subscribed report
|
||||
$report = $this->getReport( $card_ids );
|
||||
|
||||
// combine report and redeem
|
||||
if ( $report ) {
|
||||
foreach ( $report as $key => $value ) {
|
||||
$report[ $key ]['total_redeem'] = 0;
|
||||
if ( $redeem ) {
|
||||
foreach ( $redeem as $subkey => $subvalue ) {
|
||||
if ( $subvalue['cardid'] == $value['cardid'] ) {
|
||||
$report[ $key ]['total_redeem'] = $subvalue['redeem'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$results = array();
|
||||
array_walk( $report, function( $value, $key ) use (&$results) {
|
||||
$results[ $value['cardid'] ] = $value;
|
||||
} );
|
||||
foreach ( $deals as $key => $value ) {
|
||||
$cardid = $value['cardid'];
|
||||
$deals[ $key ]['last_24hours'] = isset( $results[ $cardid ] ) ? $results[ $cardid ]['last_24hours'] : 0;
|
||||
$deals[ $key ]['last_7days'] = isset( $results[ $cardid ] ) ? $results[ $cardid ]['last_7days'] : 0;
|
||||
$deals[ $key ]['last_14days'] = isset( $results[ $cardid ] ) ? $results[ $cardid ]['last_14days'] : 0;
|
||||
$deals[ $key ]['last_30days'] = isset( $results[ $cardid ] ) ? $results[ $cardid ]['last_30days'] : 0;
|
||||
$deals[ $key ]['total_sub'] = isset( $results[ $cardid ] ) ? $results[ $cardid ]['total_sub'] : 0;
|
||||
$deals[ $key ]['total_redeem'] = isset( $results[ $cardid ] ) ? $results[ $cardid ]['total_redeem'] : 0;
|
||||
}
|
||||
}
|
||||
|
||||
return $deals;
|
||||
|
||||
} catch (Exception $e) {
|
||||
Logger::debug( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update report after get all subscribed
|
||||
* @return mixed
|
||||
*/
|
||||
public function updateSubscribedReport() {
|
||||
$results = $this->getSubscripbed();
|
||||
try {
|
||||
|
||||
if ( !$results ) {
|
||||
throw new Exception( 'Subscribed not found!' );
|
||||
}
|
||||
|
||||
$table_columns = array(
|
||||
'card_id',
|
||||
'country',
|
||||
'last_24hours',
|
||||
'last_7days',
|
||||
'last_14days',
|
||||
'last_30days',
|
||||
'total_sub',
|
||||
'total_redeem'
|
||||
);
|
||||
$table_results = array();
|
||||
array_filter( $results, function( $var ) use ( &$table_results ) {
|
||||
$content = array();
|
||||
array_walk( $var, function( $value, $key ) use ( &$content ) {
|
||||
$value = $value ?? 0;
|
||||
array_push( $content, $value );
|
||||
} );
|
||||
$table_results[] = sprintf( '(%s)', implode( ', ', $content ) );
|
||||
} );
|
||||
|
||||
$sql = sprintf( "
|
||||
begin;
|
||||
truncate table subscription_summary;
|
||||
insert into subscription_summary (%s)
|
||||
values %s;
|
||||
commit;
|
||||
rollback;
|
||||
",
|
||||
// insert
|
||||
implode( ', ', $table_columns ),
|
||||
preg_replace( '/([a-zA-Z]+)/m', '\'$0\'', implode( ', ', $table_results ) ) );
|
||||
|
||||
$results = pg_query( $this->conn, $sql );
|
||||
|
||||
if ( $error = pg_last_error( $this->repConn ) ) {
|
||||
throw new Exception( $error );
|
||||
}
|
||||
|
||||
return 'success';
|
||||
} catch (Exception $e) {
|
||||
Logger::debug( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] subscribed_summary job is starting.\n";
|
||||
|
||||
$instance = new SubscribedSummary();
|
||||
// $instance->getSubscripbed();
|
||||
echo $instance->updateSubscribedReport() . PHP_EOL;
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] subscribed_summary job is ending.\n";
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
echo "[".date("Y-m-d H:i:s")."] Account Audit job is starting.\n";
|
||||
include '../backend.php';
|
||||
define("FLOAT_SYSTEM_ACCOUNT_AUDIT", 92015);
|
||||
|
||||
function Fextension_call($in, &$out) {
|
||||
// logToFl("Merchant_Name count->" . $in["merchant_name"]);
|
||||
global $savvyext;
|
||||
$out = $savvyext->savvyext_api($in);
|
||||
$ret = $out["retval"];
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$inX["member_id"] = 13;
|
||||
$inX["pid"] = 0;
|
||||
$inX["action"] = 999999999; // DEBUG
|
||||
$outX=array();
|
||||
|
||||
|
||||
$extension_call = true;
|
||||
|
||||
if ($extension_call == true ) {
|
||||
// logToFl("merchant_name count->" . $res->merchant_name);
|
||||
$ret = Fextension_call($inX, $outX);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
$job_name ='parsedemail_item_fix_missing email';
|
||||
echo "[" . date("Y-m-d H:i:s") . "] ".$job_name." job is starting.\n";
|
||||
|
||||
require 'common/utils.php';
|
||||
require 'common/config.php';
|
||||
require 'common/address_city.php';
|
||||
require 'common/parser.php';
|
||||
require 'common/Geocode.php';
|
||||
|
||||
$total = $success = $failed = 0;
|
||||
$path = "/Users/admin/Work/FloatAdmin/adminsavvy/data/receipts/";
|
||||
$prefix = "grab_";
|
||||
$condition =" subject ilike '%your grab e-receipt%' and message_from ilike '%grab%' ";
|
||||
$prefix = "uber_";
|
||||
$condition =" subject ilike '%trip with uber%' OR subject ilike '%trip receipt%' OR subject ilike '%took an uber trip on%'";
|
||||
$prefix = "gojek_";
|
||||
$condition =" subject ilike '%your trip with gojek%' and message_from ilike '%go-jek%' ";
|
||||
/* $prefix = "comfortdelgro_";
|
||||
$condition =" subject ilike '%comfortdelgro taxi e-receipt%'";
|
||||
$condition =" subject ilike '%your trip with gojek%'";
|
||||
$prefix = "lyft_";
|
||||
$condition =" subject ilike '%your ride with%'"; */
|
||||
$q="SELECT DISTINCT ON (to_char(message_date,'YYYY-MM')) message, (to_char(message_date,'YYYY-MM')) as monthyear FROM trackedemail_item
|
||||
WHERE ".$condition." AND message_date is not null
|
||||
ORDER by monthyear DESC";
|
||||
$r = pg_query($conn, $q);
|
||||
|
||||
while ($f = pg_fetch_assoc($r)) {
|
||||
$total++;
|
||||
$message = $f['message'];
|
||||
$monthyear = $f['monthyear'];
|
||||
$file_name = $path.$prefix.$monthyear.".html";
|
||||
file_put_contents($file_name, $message);
|
||||
}
|
||||
echo "[" . date("Y-m-d H:i:s") . "] ".$job_name." job complete.\n";
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
$job_name ='parsedemail_item_fix_missing email';
|
||||
echo "[" . date("Y-m-d H:i:s") . "] ".$job_name." job is starting.\n";
|
||||
|
||||
require 'common/utils.php';
|
||||
require 'common/config.php';
|
||||
require 'common/address_city.php';
|
||||
require 'common/parser.php';
|
||||
require 'common/Geocode.php';
|
||||
|
||||
$total = $success = $failed = 0;
|
||||
|
||||
$q = "SELECT id FROM trackedemail_item WHERE id NOT IN (SELECT trackedemail_item_id FROM parsedemail_item_payment) ORDER BY id DESC;";
|
||||
$q="select id from trackedemail_item where id not in (select trackedemail_item_id from parsedemail_item p INNER JOIN trackedemail_item t on p.trackedemail_item_id=t.id WHERE member_id=347) AND member_id=347 order by id desc;";
|
||||
$r = pg_query($conn, $q);
|
||||
while ($f = pg_fetch_assoc($r)) {
|
||||
$total++;
|
||||
$email_id = $f['id'];
|
||||
if (!empty($email_id)) {
|
||||
$data = parseEmail($email_id);
|
||||
if ( isset( $data['parsed_status'] ) && $data['parsed_status']==1 ) {
|
||||
echo "[" . date("Y-m-d H:i:s") . "] email id: ".$email_id." is success.\n";
|
||||
$success++;
|
||||
}else{
|
||||
echo "[" . date("Y-m-d H:i:s") . "] email id: ".$email_id." is failed.\n";
|
||||
$failed++;
|
||||
}
|
||||
} else {
|
||||
echo "[" . date("Y-m-d H:i:s") . "] email id: ".$email_id." is failed.\n";
|
||||
$failed++;
|
||||
}
|
||||
}
|
||||
|
||||
echo "Total: " . $total . ".\n";
|
||||
echo "Success: : " . $success . ".\n";
|
||||
echo "Failed: : " . $failed . ".\n";
|
||||
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] ".$job_name." job complete.\n";
|
||||
@@ -0,0 +1,318 @@
|
||||
<?php
|
||||
|
||||
define('TRANSACTION_REMOVED', 'removed');
|
||||
|
||||
$job_name = pathinfo(__FILE__, PATHINFO_FILENAME);
|
||||
echo "[" . date("Y-m-d H:i:s") . "] " . $job_name . " job is starting.\n";
|
||||
|
||||
include '../backend.php';
|
||||
require_once('./lock.php');
|
||||
require_once('./common/Logger.php');
|
||||
$db_host = $savvyext->cfgReadChar('database.host');
|
||||
$db_name = $savvyext->cfgReadChar('database.name');
|
||||
$db_user = $savvyext->cfgReadChar('database.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database.port');
|
||||
|
||||
$connstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$con = pg_connect($connstr) or die("Could not connect to server\n");
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('database_replica.host');
|
||||
$db_name = $savvyext->cfgReadChar('database_replica.name');
|
||||
$db_user = $savvyext->cfgReadChar('database_replica.user');
|
||||
$db_pass = $savvyext->cfgReadChar('database_replica.pass');
|
||||
$db_port = $savvyext->cfgReadLong('database_replica.port');
|
||||
$readOnlyReplicaConnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$readOnlyReplicaConn = pg_connect($readOnlyReplicaConnstr);
|
||||
|
||||
if($readOnlyReplicaConn === FALSE){
|
||||
$readOnlyReplicaConn = $con;
|
||||
}
|
||||
|
||||
if ($con === FALSE || $readOnlyReplicaConn === FALSE) {
|
||||
unlock_pid_file($lock_file);
|
||||
die("Could not connect to server\n");
|
||||
}
|
||||
|
||||
function execute($inX = [])
|
||||
{
|
||||
$outX = [];
|
||||
|
||||
// get transaction list
|
||||
fetch_bank_transactions($inX, $outX);
|
||||
|
||||
if ($outX['count']) {
|
||||
|
||||
$response = $outX['results'];
|
||||
|
||||
remove_transaction($response);
|
||||
|
||||
// the rest of tranactions
|
||||
$import_transactions = array_filter($response, function ($ele) {
|
||||
return $ele['tstatus'] !== TRANSACTION_REMOVED;
|
||||
});
|
||||
|
||||
update_transaction($import_transactions, $imported_ids);
|
||||
insert_transaction($import_transactions, $imported_ids);
|
||||
}
|
||||
|
||||
if (!empty($outX['next'])) {
|
||||
|
||||
parse_str(parse_url($outX['next'], PHP_URL_QUERY), $inX);
|
||||
|
||||
execute($inX);
|
||||
} else {
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function generate_params($data) {
|
||||
$value = [];
|
||||
foreach ($data as $element) {
|
||||
|
||||
$value[] = [
|
||||
'import_id' => $element['id'],
|
||||
'account' => $element['account'],
|
||||
'member_id' => $element['member_id'],
|
||||
'amount' => $element['amount'],
|
||||
'currency' => $element['currency'],
|
||||
'status' => $element['status'],
|
||||
'tstatus' => $element['tstatus'],
|
||||
'description' => $element['description'],
|
||||
'time' => $element['time'],
|
||||
'category' => $element['category'],
|
||||
'provider_category' => $element['provider_category'],
|
||||
'merchant_provider_id' => $element['merchant_provider_id'],
|
||||
'merchant_name' => $element['merchant_name'],
|
||||
'extra' => json_encode($element['extra'])
|
||||
];
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
function fetch_bank_transactions($in, &$out) {
|
||||
global $savvyext;
|
||||
$target_url = str_replace("'", "", $savvyext->cfgReadChar('microservices.account'))
|
||||
. "/api/v1/transactions/get_raw_transactions";
|
||||
|
||||
$target_url = $target_url . "/?" . http_build_query($in);
|
||||
|
||||
//open connection
|
||||
$ch = curl_init();
|
||||
//set the url, number of POST vars, POST data
|
||||
curl_setopt($ch, CURLOPT_URL, $target_url);
|
||||
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
||||
'Content-Type: application/json',
|
||||
'Connection: Keep-Alive',
|
||||
'Authorization: Server-Token ' . $savvyext->cfgReadChar('system.bank_token'),
|
||||
'Accept: application/json'
|
||||
));
|
||||
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_FAILONERROR, true);
|
||||
|
||||
//execute post
|
||||
$result = curl_exec($ch);
|
||||
if (curl_errno($ch)) {
|
||||
$error_msg = curl_error($ch);
|
||||
}
|
||||
//close connection
|
||||
curl_close($ch);
|
||||
if (isset($error_msg)) {
|
||||
Logger::debug('transactions_record_import fetch_bank_transactions error:');
|
||||
Logger::debug($error_msg);
|
||||
}
|
||||
|
||||
$out = json_decode($result, true);
|
||||
}
|
||||
|
||||
function get_import_id_list_in_table($import_ids) {
|
||||
global $readOnlyReplicaConn;
|
||||
$query =
|
||||
'SELECT import_id
|
||||
FROM members_transactions_import_raw
|
||||
WHERE import_id IN (' . implode(',', $import_ids) . ')';
|
||||
$result = pg_query($readOnlyReplicaConn, $query);
|
||||
|
||||
$imported_ids = [];
|
||||
if ($result && pg_num_rows($result)) {
|
||||
while ($row = pg_fetch_row($result)) {
|
||||
$imported_ids[] = $row[0];
|
||||
}
|
||||
}
|
||||
|
||||
return $imported_ids;
|
||||
}
|
||||
|
||||
function delete_tranasction($remove_ids) {
|
||||
global $con;
|
||||
$query = 'DELETE FROM members_transactions_import_raw
|
||||
WHERE import_id IN (' . implode(',', $remove_ids) . ')';
|
||||
|
||||
if (!pg_query($con, $query)) {
|
||||
echo pg_last_error();
|
||||
Logger::debug('transactions_record_import delete_tranasction error:');
|
||||
Logger::debug(pg_last_error());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function mark_transaction_as_imported($id) {
|
||||
global $savvyext;
|
||||
$target_url = str_replace("'", "", $savvyext->cfgReadChar('microservices.account'))
|
||||
. "/api/v1/transactions/{$id}/";
|
||||
|
||||
//open connection
|
||||
$ch = curl_init();
|
||||
//set the url, number of POST vars, POST data
|
||||
curl_setopt($ch, CURLOPT_URL, $target_url);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(
|
||||
['points_imported' => date('Y-m-d\TH:i:s.Z\Z', time())]
|
||||
));
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
||||
'Content-Type: application/json',
|
||||
'Connection: Keep-Alive',
|
||||
'Authorization: Server-Token ' . $savvyext->cfgReadChar('system.bank_token'),
|
||||
'Accept: application/json'
|
||||
));
|
||||
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_FAILONERROR, true);
|
||||
|
||||
//execute post
|
||||
$result = curl_exec($ch);
|
||||
if (curl_errno($ch)) {
|
||||
$error_msg = curl_error($ch);
|
||||
}
|
||||
//close connection
|
||||
curl_close($ch);
|
||||
if (isset($error_msg)) {
|
||||
Logger::debug('transactions_record_import mark_transaction_as_imported error:');
|
||||
Logger::debug($error_msg);
|
||||
}
|
||||
$out = json_decode($result, true);
|
||||
if (isset($out['error'])) echo implode("\n",$out['non_field_errors']);
|
||||
}
|
||||
|
||||
function remove_transaction($data) {
|
||||
// transactions removed
|
||||
$remove_ids = array_column(array_filter($data, function ($ele) {
|
||||
return $ele['tstatus'] === TRANSACTION_REMOVED;
|
||||
}), 'id');
|
||||
|
||||
if ($remove_ids && delete_tranasction($remove_ids)) {
|
||||
|
||||
foreach ($remove_ids as $id) {
|
||||
mark_transaction_as_imported($id);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function update_transaction($data, &$imported_ids) {
|
||||
global $con;
|
||||
// get transactions imported
|
||||
$imported_ids = get_import_id_list_in_table(array_column($data, 'id'));
|
||||
|
||||
if ($imported_ids) {
|
||||
$imported_transactions = array_filter($data, function ($ele) use ($imported_ids) {
|
||||
return in_array($ele['id'], $imported_ids);
|
||||
});
|
||||
|
||||
$params_update = generate_params($imported_transactions);
|
||||
|
||||
foreach ($params_update as $val) {
|
||||
|
||||
$rs = pg_query_params($con,
|
||||
"UPDATE members_transactions_import_raw
|
||||
SET
|
||||
account = $2,
|
||||
member_id = $3,
|
||||
amount = $4,
|
||||
currency = $5,
|
||||
status = $6,
|
||||
tstatus = $7,
|
||||
description = $8,
|
||||
time = $9,
|
||||
category = $10,
|
||||
provider_category = $11,
|
||||
merchant_provider_id = $12,
|
||||
merchant_name = $13,
|
||||
extra = $14
|
||||
WHERE import_id = $1
|
||||
",
|
||||
$val
|
||||
);
|
||||
|
||||
if (!$rs) {
|
||||
|
||||
echo pg_last_error();
|
||||
Logger::debug('transactions_record_import update_transaction error:');
|
||||
Logger::debug(pg_last_error());
|
||||
} else {
|
||||
|
||||
mark_transaction_as_imported($val['import_id']);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function insert_transaction($data, $imported_ids) {
|
||||
global $con;
|
||||
// get the transactions not importedimported_ids
|
||||
$import_transactions = array_filter($data, function ($ele) use ($imported_ids) {
|
||||
return !in_array($ele['id'], $imported_ids);
|
||||
});
|
||||
|
||||
$params_insert = generate_params($import_transactions);
|
||||
|
||||
foreach ($params_insert as $val) {
|
||||
$rs = pg_query_params($con,
|
||||
"INSERT INTO members_transactions_import_raw
|
||||
(
|
||||
import_id,
|
||||
account,
|
||||
member_id,
|
||||
amount,
|
||||
currency,
|
||||
status,
|
||||
tstatus,
|
||||
description,
|
||||
time,
|
||||
category,
|
||||
provider_category,
|
||||
merchant_provider_id,
|
||||
merchant_name,
|
||||
extra
|
||||
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)
|
||||
ON CONFLICT(import_id) DO NOTHING",
|
||||
$val
|
||||
);
|
||||
|
||||
if (!$rs) {
|
||||
|
||||
echo "Cannot execute query with import id:" . $val['id']; // import_id
|
||||
Logger::debug('transactions_record_import insert_transaction error:');
|
||||
Logger::debug(pg_last_error());
|
||||
} else {
|
||||
|
||||
mark_transaction_as_imported($val['import_id']);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$lock_file = lock_pid_file();
|
||||
execute();
|
||||
unlock_pid_file($lock_file);
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] " . $job_name . " job complete.\n";
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* documentation: https://docs.google.com/document/d/19tMnCzGgUF5UT__0AhbptLnCbBBVxX6uA4a_S0M4lFg/edit#
|
||||
* Following up this model: https://drive.google.com/file/d/1iXlHDA4gD8UgFBBNGPeP6ypgN2YlLc9n/view
|
||||
*/
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] GPS trips job is starting.\n";
|
||||
|
||||
require __DIR__ . '/../../backend.php';
|
||||
|
||||
$db_host = $savvyext->cfgReadChar('gpsdatabase.host');
|
||||
$db_name = $savvyext->cfgReadChar('gpsdatabase.name');
|
||||
$db_user = $savvyext->cfgReadChar('gpsdatabase.user');
|
||||
$db_pass = $savvyext->cfgReadChar('gpsdatabase.pass');
|
||||
$db_port = $savvyext->cfgReadLong('gpsdatabase.port');
|
||||
$gpsconnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$gpsconn = pg_connect($gpsconnstr);
|
||||
|
||||
$gmclient = new GearmanClient();
|
||||
$gmclient->addServer('127.0.0.1', 4730);
|
||||
|
||||
$q = "SELECT member_id, count(*) as count FROM members_tracking ";
|
||||
$q .= "GROUP BY member_id";
|
||||
|
||||
$r = pg_query($gpsconn, $q);
|
||||
|
||||
if (!$r) {
|
||||
echo pg_last_error($gpsconn);
|
||||
}
|
||||
|
||||
if ($r && pg_num_rows($r) > 0) {
|
||||
while ($row = pg_fetch_object($r)) {
|
||||
$member_id = $row->member_id;
|
||||
echo "[" . date("Y-m-d H:i:s") . "] Processing member_id = $member_id (total member records: $row->count )\n";
|
||||
|
||||
// dispatch jobs
|
||||
echo "[" . date("Y-m-d H:i:s") . "] Dispatching jobs (member_id = $member_id) to gps_trips_worker.\n";
|
||||
$gmclient->doBackground('gps_trips_worker', $member_id);
|
||||
}
|
||||
}
|
||||
|
||||
if ($gmclient->returnCode() != GEARMAN_SUCCESS) {
|
||||
echo "bad return code\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
pg_close($gpsconn);
|
||||
echo "[" . date("Y-m-d H:i:s") . "] GPS trips job complete.\n";
|
||||
@@ -0,0 +1,9 @@
|
||||
[program:gps_trips_worker]
|
||||
command=/usr/bin/php /home/savvy/FloatAdmin/adminsavvy/CRONS/transportation_mode_detection/gps_trips_worker.php
|
||||
process_name=%(program_name)s_%(process_num)s
|
||||
autostart=true
|
||||
autorestart=true
|
||||
numprocs=5
|
||||
#add this setting to log error
|
||||
stderr_logfile=/var/log/supervisor/%(program_name)s_p%(process_num)s.err.log
|
||||
stdout_logfile=/var/log/supervisor/%(program_name)s_p%(process_num)s.out.log
|
||||
@@ -0,0 +1,589 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* documentation: https://docs.google.com/document/d/19tMnCzGgUF5UT__0AhbptLnCbBBVxX6uA4a_S0M4lFg/edit#
|
||||
* Following up this model: https://drive.google.com/file/d/1iXlHDA4gD8UgFBBNGPeP6ypgN2YlLc9n/view
|
||||
*/
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] GPS trips job is starting.\n";
|
||||
|
||||
require __DIR__ . '/../../backend.php';
|
||||
|
||||
/***** connect database *****/
|
||||
$db_host = $savvyext->cfgReadChar('gpsdatabase.host');
|
||||
$db_name = $savvyext->cfgReadChar('gpsdatabase.name');
|
||||
$db_user = $savvyext->cfgReadChar('gpsdatabase.user');
|
||||
$db_pass = $savvyext->cfgReadChar('gpsdatabase.pass');
|
||||
$db_port = $savvyext->cfgReadLong('gpsdatabase.port');
|
||||
$gpsconnstr = "host=${db_host} port=${db_port} dbname=${db_name} user=${db_user} password=${db_pass}";
|
||||
$gpsconn = pg_connect($gpsconnstr);
|
||||
|
||||
/***** load configuration *****/
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
$encryptionAlg = $savvyext->cfgReadChar('encryption.algorithm');
|
||||
$encryptionKey = $savvyext->cfgReadChar('encryption.key');
|
||||
$encryptionIV = $savvyext->cfgReadChar('encryption.iv');
|
||||
$baseURL = $savvyext->cfgReadChar('system.api_url');
|
||||
$googleApiKey = $savvyext->cfgReadChar('google.api_key');
|
||||
|
||||
/***** definition *****/
|
||||
define('STOPPED', 'stopped');
|
||||
define('WALKING', 'walking');
|
||||
define('DRIVING_AND_PUBLIC_TRANSPORT', 'driving_and_public_tranport');
|
||||
define('UNKNOWN', 'unknown');
|
||||
|
||||
$segment_duration_limit = 1; // min
|
||||
$trip_limit = 20;
|
||||
$needed_trip_limit = 18;
|
||||
|
||||
// km/h
|
||||
$walking_low_avg_speed = 3;
|
||||
$walking_high_avg_speed = 10;
|
||||
$low_avg_speed = 10;
|
||||
$high_avg_speed = 160;
|
||||
|
||||
/***** start worker to process a job *****/
|
||||
$worker = new GearmanWorker();
|
||||
$worker->addServer('127.0.0.1', 4730);
|
||||
|
||||
$worker->addFunction('gps_trips_worker', function (GearmanJob $job) {
|
||||
$member_id = $job->workload();
|
||||
|
||||
processMemberGPSTrips($member_id);
|
||||
|
||||
echo "Waiting for job...\n";
|
||||
});
|
||||
|
||||
while ($worker->work()) {
|
||||
if ($worker->returnCode() != GEARMAN_SUCCESS) {
|
||||
echo "return_code: " . $worker->returnCode() . "\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pg_close($gpsconn);
|
||||
echo "[" . date("Y-m-d H:i:s") . "] GPS trips job complete.\n";
|
||||
|
||||
/********************* Functions *********************/
|
||||
function processMemberGPSTrips(int $member_id)
|
||||
{
|
||||
global $gpsconn, $high_avg_speed, $segment_duration_limit, $trip_limit;
|
||||
|
||||
$lastProcessedDatetime = getLastProcessedDatetime($member_id);
|
||||
if ($lastProcessedDatetime === NULL) {
|
||||
echo 'There something wrong with member_id = '.$member_id;
|
||||
return;
|
||||
}
|
||||
|
||||
$whereQuery = '';
|
||||
if ($lastProcessedDatetime !== '') {
|
||||
$whereQuery .= " AND ttime > '" . $lastProcessedDatetime . "' ";
|
||||
}
|
||||
|
||||
// and take the data not newer than 24 hrs
|
||||
$track_query = " SELECT
|
||||
id as members_tracking_id,
|
||||
member_id,
|
||||
lat,
|
||||
lng,
|
||||
ttime as time
|
||||
FROM
|
||||
members_tracking
|
||||
WHERE
|
||||
member_id = $member_id
|
||||
AND ttime <= (now() - INTERVAL '24 HOURS')
|
||||
" . $whereQuery . "
|
||||
ORDER BY
|
||||
ttime ASC
|
||||
";
|
||||
|
||||
$track_res = pg_query($gpsconn, $track_query);
|
||||
if (!$track_res) {
|
||||
echo pg_last_error($gpsconn);
|
||||
}
|
||||
|
||||
if ($track_res && pg_num_rows($track_res) > 0) {
|
||||
$first_data = NULL;
|
||||
$last_data = NULL;
|
||||
$dataset = [];
|
||||
|
||||
$rowCount = 0;
|
||||
$i = 0;
|
||||
$tripStartIndex = 'NONE';
|
||||
|
||||
echo "[" . date("Y-m-d H:i:s") . "] Processing member_id=" . $member_id . " . Waiting for a moment.\n";
|
||||
while ($row = pg_fetch_array($track_res)) {
|
||||
if ($first_data === NULL) {
|
||||
$first_data = $row;
|
||||
}
|
||||
$last_data = $row;
|
||||
|
||||
$avg_speed_data = calculateAvgSpeed($first_data, $last_data);
|
||||
$trip_segment = [
|
||||
'members_tracking_id' => $last_data['members_tracking_id'],
|
||||
'member_id' => $last_data['member_id'],
|
||||
'lat' => $last_data['lat'],
|
||||
'lng' => $last_data['lng'],
|
||||
'geo' => calculateGeo($last_data['lat'], $last_data['lng']),
|
||||
'time' => $last_data['time'],
|
||||
'duration' => $avg_speed_data['duration'],
|
||||
'distance' => $avg_speed_data['distance'],
|
||||
'avg_speed' => $avg_speed_data['avg_speed'],
|
||||
'trip_detection_1' => 'NO-TRIP', // initialize it as NO_TRIP, then we will update it later
|
||||
'trip_detection_2' => 'NO-TRIP', // initialize it as NO_TRIP, then we will update it later
|
||||
];
|
||||
|
||||
// calculate trip_detection_1 base on duration or avg speed
|
||||
// if duration of a segement > $segment_duration_limit minute
|
||||
// OR avg speed of a segment > $high_avg_speed km/h => segment may not belongs to a trip
|
||||
if ($avg_speed_data['duration'] > $segment_duration_limit || $avg_speed_data['duration'] <= 0
|
||||
|| $avg_speed_data['avg_speed'] > $high_avg_speed
|
||||
) {
|
||||
$trip_segment['trip_detection_1'] = 'NO-TRIP';
|
||||
} else {
|
||||
$trip_segment['trip_detection_1'] = 'TRIP';
|
||||
}
|
||||
|
||||
$dataset[] = $trip_segment;
|
||||
$rowCount++;
|
||||
$first_data = $last_data;
|
||||
|
||||
// calculate trip_detection_2 base on trip_detection_1
|
||||
if ($rowCount === $trip_limit) {
|
||||
detectTrips($dataset, $tripStartIndex, $i);
|
||||
$i++;
|
||||
$rowCount--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pg_free_result($track_res);
|
||||
}
|
||||
|
||||
function getLastProcessedDatetime(int $member_id)
|
||||
{
|
||||
global $gpsconn;
|
||||
$q = " SELECT
|
||||
travel_date_end
|
||||
FROM
|
||||
gps_trips
|
||||
WHERE
|
||||
member_id = $member_id
|
||||
ORDER BY
|
||||
travel_date_end DESC
|
||||
LIMIT 1
|
||||
";
|
||||
|
||||
$lastProcessedDatetime = NULL;
|
||||
|
||||
$r = pg_query($gpsconn, $q);
|
||||
|
||||
if (!$r) {
|
||||
echo pg_last_error($gpsconn);
|
||||
}
|
||||
|
||||
if ($r && pg_num_rows($r) > 0) {
|
||||
$data = pg_fetch_object($r, 0);
|
||||
|
||||
$lastProcessedDatetime = $data->travel_date_end;
|
||||
} else {
|
||||
$lastProcessedDatetime = '';
|
||||
}
|
||||
|
||||
return $lastProcessedDatetime;
|
||||
}
|
||||
|
||||
function detectTrips(array &$dataset, &$tripStartIndex, int &$i)
|
||||
{
|
||||
global $needed_trip_limit, $trip_limit;
|
||||
|
||||
// calculate trip_detection_2 base on trip_detection_1
|
||||
$j = $i;
|
||||
$segmentCount = 0;
|
||||
|
||||
while ($j < $i + $trip_limit) {
|
||||
if ($dataset[$j]['trip_detection_1'] === 'TRIP') {
|
||||
$segmentCount++;
|
||||
}
|
||||
|
||||
$j++;
|
||||
}
|
||||
|
||||
if ($segmentCount >= $needed_trip_limit) {
|
||||
$dataset[$i]['trip_detection_2'] = 'TRIP';
|
||||
}
|
||||
|
||||
// detect a trip based on trip_detection_2
|
||||
if ($dataset[$i]['trip_detection_2'] === 'TRIP' && $tripStartIndex === 'NONE') {
|
||||
$tripStartIndex = $i;
|
||||
}
|
||||
if ($tripStartIndex !== 'NONE' && $dataset[$i]['trip_detection_2'] !== 'TRIP') {
|
||||
$trip_data = array_slice($dataset, $tripStartIndex, ($i - 1) - $tripStartIndex + 1);
|
||||
processEachTrip($trip_data);
|
||||
|
||||
// remove rows that were calculated for a detected trip, reduce memory
|
||||
array_splice($dataset, 0, ($i - 1) - 0 + 1);
|
||||
$i = 0;
|
||||
$tripStartIndex = 'NONE';
|
||||
}
|
||||
}
|
||||
|
||||
function processEachTrip(array $trip_data)
|
||||
{
|
||||
global $walking_low_avg_speed, $walking_high_avg_speed, $low_avg_speed, $high_avg_speed;
|
||||
|
||||
// detect legs of a trip
|
||||
$cumulative_duration_total = 0;
|
||||
$cumulative_distance_total = 0;
|
||||
foreach ($trip_data as $key => $item) {
|
||||
// note: in case first item, cumulative_duration and cumulative_distance will be 0
|
||||
if ($key != 0) {
|
||||
$cumulative_duration_total += $item['duration'];
|
||||
$cumulative_distance_total += $item['distance'];
|
||||
}
|
||||
|
||||
// km/h
|
||||
$cumulative_avg_speed = $cumulative_duration_total > 0 ? round($cumulative_distance_total / $cumulative_duration_total * 60, 2) : 0;
|
||||
|
||||
$trip_data[$key]['cumulative_duration'] = $cumulative_duration_total;
|
||||
$trip_data[$key]['cumulative_distance'] = $cumulative_distance_total;
|
||||
$trip_data[$key]['cumulative_avg_speed'] = $cumulative_avg_speed;
|
||||
$trip_data[$key]['transport_mode'] = '';
|
||||
|
||||
// how to detect transport mode
|
||||
if ($cumulative_avg_speed < $walking_low_avg_speed) {
|
||||
$trip_data[$key]['transport_mode'] = STOPPED;
|
||||
} else if ($cumulative_avg_speed >= $walking_low_avg_speed && $cumulative_avg_speed <= $walking_high_avg_speed) {
|
||||
$trip_data[$key]['transport_mode'] = WALKING;
|
||||
} else if ($cumulative_avg_speed >= $low_avg_speed && $cumulative_avg_speed <= $high_avg_speed) {
|
||||
$trip_data[$key]['transport_mode'] = DRIVING_AND_PUBLIC_TRANSPORT;
|
||||
} else if ($cumulative_avg_speed > $high_avg_speed) {
|
||||
$trip_data[$key]['transport_mode'] = UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
$gps_trip_id = insertATripIntoDatabase($trip_data);
|
||||
|
||||
splitLegsFromATrip($gps_trip_id, $trip_data);
|
||||
}
|
||||
|
||||
function insertATripIntoDatabase(array $trip_data): int
|
||||
{
|
||||
global $gpsconn;
|
||||
|
||||
if (count($trip_data) <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$query = "
|
||||
INSERT INTO gps_trips(member_id, travel_date, travel_date_end, duration,
|
||||
distance, location_start_lat, location_start_lng, location_start,
|
||||
location_start_id, location_end_lat, location_end_lng, location_end,
|
||||
location_end_id, avg_speed, start_members_tracking_id, last_members_tracking_id)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16) RETURNING id;
|
||||
";
|
||||
$uniq = 'insert_gps_trips_' . uniqid(rand(), true);
|
||||
pg_prepare($gpsconn, $uniq, $query);
|
||||
|
||||
$first_item = $trip_data[0];
|
||||
$last_item = end($trip_data);
|
||||
|
||||
$avg_speed_data = calculateAvgSpeed($first_item, $last_item);
|
||||
|
||||
$duration_total = round($avg_speed_data['duration'], 2);
|
||||
$distance_total = round($avg_speed_data['distance'], 2);
|
||||
$avg_speed = round($avg_speed_data['avg_speed'], 2);
|
||||
|
||||
$res = pg_execute($gpsconn, $uniq, [
|
||||
$first_item['member_id'],
|
||||
$first_item['time'],
|
||||
$last_item['time'],
|
||||
$duration_total,
|
||||
$distance_total,
|
||||
$first_item['lat'],
|
||||
$first_item['lng'],
|
||||
$first_item['geo'],
|
||||
getAddressId($first_item['lat'], $first_item['lng']),
|
||||
$last_item['lat'],
|
||||
$last_item['lng'],
|
||||
$last_item['geo'],
|
||||
getAddressId($last_item['lat'], $last_item['lng']),
|
||||
$avg_speed,
|
||||
$first_item['members_tracking_id'],
|
||||
$last_item['members_tracking_id']
|
||||
]);
|
||||
|
||||
if ($res) {
|
||||
$id = (int) pg_fetch_result($res, 0);
|
||||
return $id;
|
||||
} else {
|
||||
echo pg_last_error($gpsconn);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
function splitLegsFromATrip(int $gps_trip_id, array $trip_data)
|
||||
{
|
||||
$trip_data_count = count($trip_data);
|
||||
if ($trip_data_count <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$transport_mode = '';
|
||||
$change_point_index = 0;
|
||||
$array_key_last = array_keys($trip_data)[$trip_data_count - 1];
|
||||
|
||||
foreach ($trip_data as $key => $item) {
|
||||
$leg_last_index = $key;
|
||||
|
||||
if ((isset($trip_data[$leg_last_index + 1]['transport_mode']) && $trip_data[$leg_last_index]['transport_mode'] != $trip_data[$leg_last_index + 1]['transport_mode'])
|
||||
|| ($array_key_last == $leg_last_index)
|
||||
) {
|
||||
// precess save for each leg
|
||||
$leg_start_index = $change_point_index == 0 ? 0 : $change_point_index - 1;
|
||||
$leg_data = array_slice($trip_data, $leg_start_index, $leg_last_index - $leg_start_index + 1);
|
||||
insertALegIntoDatabase($gps_trip_id, $leg_data, $trip_data[$leg_last_index]['transport_mode']);
|
||||
|
||||
$change_point_index = $leg_last_index + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function insertALegIntoDatabase(int $gps_trip_id, array $trip_data, string $transport_mode)
|
||||
{
|
||||
global $gpsconn;
|
||||
|
||||
if (count($trip_data) <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$query = "
|
||||
INSERT INTO gps_trips_legs(member_id, gps_trip_id, travel_date, travel_date_end, duration,
|
||||
distance, location_start_lat, location_start_lng, location_start,
|
||||
location_start_id, location_end_lat, location_end_lng, location_end,
|
||||
location_end_id, avg_speed, transport_mode, start_members_tracking_id, last_members_tracking_id)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18);
|
||||
";
|
||||
$uniq = 'insert_gps_trips_legs_' . uniqid(rand(), true);
|
||||
pg_prepare($gpsconn, $uniq, $query);
|
||||
|
||||
$first_item = $trip_data[0];
|
||||
$last_item = end($trip_data);
|
||||
|
||||
$avg_speed_data = calculateAvgSpeed($first_item, $last_item);
|
||||
|
||||
$duration_total = round($avg_speed_data['duration'], 2);
|
||||
$distance_total = round($avg_speed_data['distance'], 2);
|
||||
$avg_speed = round($avg_speed_data['avg_speed'], 2);
|
||||
|
||||
$res = pg_execute($gpsconn, $uniq, [
|
||||
$first_item['member_id'],
|
||||
$gps_trip_id,
|
||||
$first_item['time'],
|
||||
$last_item['time'],
|
||||
$duration_total,
|
||||
$distance_total,
|
||||
$first_item['lat'],
|
||||
$first_item['lng'],
|
||||
$first_item['geo'],
|
||||
getAddressId($first_item['lat'], $first_item['lng']),
|
||||
$last_item['lat'],
|
||||
$last_item['lng'],
|
||||
$last_item['geo'],
|
||||
getAddressId($last_item['lat'], $last_item['lng']),
|
||||
$avg_speed,
|
||||
$transport_mode,
|
||||
$first_item['members_tracking_id'],
|
||||
$last_item['members_tracking_id']
|
||||
]);
|
||||
|
||||
if (!$res) {
|
||||
echo pg_last_error($gpsconn);
|
||||
}
|
||||
}
|
||||
|
||||
function calculateGeo($lat, $lng)
|
||||
{
|
||||
global $gpsconn;
|
||||
|
||||
$q = "
|
||||
SELECT ST_SetSRID(ST_MakePoint('" . $lng . "','" . $lat . "'), 4326)::geography as geo
|
||||
";
|
||||
|
||||
$r = pg_query($gpsconn, $q);
|
||||
if (!$r) {
|
||||
echo pg_last_error($gpsconn);
|
||||
}
|
||||
|
||||
if ($r && pg_num_rows($r) > 0) {
|
||||
$data = pg_fetch_object($r, 0);
|
||||
|
||||
return $data->geo;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function calculateAvgSpeed(array $first_data, array $last_data): array
|
||||
{
|
||||
$start_date = strtotime($first_data['time']);
|
||||
$end_date = strtotime($last_data['time']);
|
||||
$duration = abs($start_date - $end_date);
|
||||
|
||||
$duration = $duration / 60; // convert sec to min
|
||||
$distance = sqrt(pow(abs(($last_data['lng'] - $first_data['lng']) * 111), 2) + pow(abs(($last_data['lat'] - $first_data['lat']) * 111), 2));
|
||||
$avg_speed = ($duration > 0) ? ($distance / $duration * 60) : 0; // convert km/m to km/h
|
||||
|
||||
return [
|
||||
'duration' => $duration,
|
||||
'distance' => $distance,
|
||||
'avg_speed' => $avg_speed,
|
||||
];
|
||||
}
|
||||
|
||||
function getAddressId(float $lat, float $lng) : int {
|
||||
$reverse_data = reverseGeocode($lat, $lng);
|
||||
if (empty($reverse_data)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
list($fAddress, $err) = geocode($reverse_data['address_name'], $reverse_data['country_short_name']);
|
||||
if (!is_array($fAddress) || !array_key_exists('geocode',$fAddress) || !is_array($fAddress['geocode'])
|
||||
|| !array_key_exists('id',$fAddress['geocode']) || $fAddress['geocode']['id']<1) {
|
||||
// Failed to geocode from address
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $fAddress['geocode']['id'];
|
||||
}
|
||||
|
||||
function geocode(string $address_name, string $country_code, int $member_id=0) : array{
|
||||
global $encryptionAlg, $encryptionKey, $encryptionIV, $baseURL, $httpAuthToken;
|
||||
|
||||
$in = [
|
||||
'address' => $address_name,
|
||||
'member_id' => $member_id,
|
||||
'country' => $country_code
|
||||
];
|
||||
$data = http_build_query($in);
|
||||
|
||||
$url = $baseURL . "/trips/api/geocode/?".$data;
|
||||
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_VERBOSE, false);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
||||
'Content-Type: application/json',
|
||||
'Authorization: Server-Token ' . $httpAuthToken,
|
||||
"client_id: BATCH"
|
||||
)
|
||||
);
|
||||
|
||||
$body = curl_exec($ch);
|
||||
|
||||
$result = json_decode($body,true);
|
||||
|
||||
$payload = openssl_decrypt(
|
||||
hex2bin(
|
||||
$result['payload']
|
||||
),
|
||||
$encryptionAlg,
|
||||
$encryptionKey,
|
||||
OPENSSL_RAW_DATA,
|
||||
$encryptionIV
|
||||
);
|
||||
|
||||
return [json_decode($payload,true),$body];
|
||||
}
|
||||
|
||||
function reverseGeocode(float $lat, float $lng) : array
|
||||
{
|
||||
// LINK: https://developers.google.com/maps/documentation/geocoding/start#reverse
|
||||
|
||||
global $googleApiKey;
|
||||
$url = "https://maps.googleapis.com/maps/api/geocode/json?latlng=${lat},${lng}&key=${googleApiKey}";
|
||||
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_VERBOSE, false);
|
||||
|
||||
$body = curl_exec($ch);
|
||||
|
||||
$res = json_decode($body);
|
||||
|
||||
$country_short_name = '';
|
||||
$address_name = '';
|
||||
if (isset($res->status) && $res->status === 'OK') {
|
||||
$address_components = $res->results[0]->address_components;
|
||||
$address_name = $res->results[0]->formatted_address;
|
||||
|
||||
for ($i = 0;$i < count($address_components);$i++) {
|
||||
$cn = array($address_components[$i]->types[0]);
|
||||
if (in_array("country", $cn)) {
|
||||
$country_short_name = $address_components[$i]->short_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($country_short_name) && !empty($address_name)) {
|
||||
return [
|
||||
'country_short_name' => $country_short_name,
|
||||
'address_name' => $address_name,
|
||||
];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
// export for DEBUG
|
||||
function exportCsv(array $data)
|
||||
{
|
||||
$fp = fopen('/Users/inmac/Sites/FloatAdmin/adminsavvy/CRONS/transportation_mode_detection/trip.csv', 'a+');
|
||||
|
||||
$data = array_map(function ($el) {
|
||||
return [
|
||||
$el['members_tracking_id'],
|
||||
$el['lng'],
|
||||
$el['lat'],
|
||||
$el['time'],
|
||||
round($el['duration'], 2),
|
||||
round($el['distance'], 2),
|
||||
round($el['avg_speed'], 2),
|
||||
$el['trip_detection_1'],
|
||||
$el['trip_detection_2'],
|
||||
round($el['cumulative_duration'], 2),
|
||||
round($el['cumulative_distance'], 2),
|
||||
round($el['cumulative_avg_speed'], 2),
|
||||
$el['transport_mode'],
|
||||
];
|
||||
}, $data);
|
||||
|
||||
array_unshift($data, [
|
||||
'members_tracking_id',
|
||||
'lng',
|
||||
'lat',
|
||||
'time',
|
||||
'duration',
|
||||
'distance',
|
||||
'avg_speed',
|
||||
'trip_detection_1',
|
||||
'trip_detection_2',
|
||||
'cumulative_duration',
|
||||
'cumulative_distance',
|
||||
'cumulative_avg_speed',
|
||||
'transport_mode',
|
||||
]);
|
||||
|
||||
foreach ($data as $row) {
|
||||
fputcsv($fp, $row);
|
||||
}
|
||||
|
||||
fclose($fp);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user