Files
FloatBackOfffice/CRONS/automation_report.php
T
dev-chiefworks f76abffdcd first commit
2022-05-31 16:21:53 -04:00

423 lines
14 KiB
PHP

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