From 48350f297780136238ac5f406fbe1d0e0b5d1bd0 Mon Sep 17 00:00:00 2001 From: patrick Date: Mon, 15 Jul 2019 17:41:37 +1000 Subject: [PATCH] get distance for two user logins is done and tested with google map api --- AddrMap.php | 174 ++++++++++++++++++++++++++++++++++++++++++++ Xero.php | 24 +++++- js/bts_timesheet.js | 59 +++++++++------ ts.php | 58 +++++++++++++-- 4 files changed, 285 insertions(+), 30 deletions(-) create mode 100644 AddrMap.php diff --git a/AddrMap.php b/AddrMap.php new file mode 100644 index 0000000..4779277 --- /dev/null +++ b/AddrMap.php @@ -0,0 +1,174 @@ +error = false; + $this->user1 = get_user_by('login', $user1_login); + $this->user2 = get_user_by('login', $user2_login); + + //convert user to their address + $this->origin = $this->get_user_address($user1_login); + $this->destination = $this->get_user_address($user2_login); + + //get distance from db + $this->dist = $this->get_distance_from_db(); + if ($this->dist == false){ + //get distance from google map + $response = $this->get_google_direction($this->origin, $this->destination); + if ($response == false){ + //mark error + $this->error == true; + }else{ + $this->json = $response; + $this->dist = $this->convert_response_to_dist_in_meter($response); + } + //store it in db for future use + $this->update_db(); + } + + } + + public function has_error(){ + return $this->error; + } + + public function get_error_msg(){ + if($this->error) + return "Cannot get distance getween $this->user1->display_name and $this->user2->display_name"; + else + return ""; + } + + public function get_dist(){ + if ($this->error) + return 0; + return $this->dist; + } + + public function get_dist_in_km(){ + if ($this->error) + return 0; + return $this->dist/1000; + } + + private function update_db() + { + global $wpdb; + $table_name= $this->get_table_name(); + $sql = "INSERT INTO $table_name (origin,destination,response,distance) VALUES ('%s', '%s', '%s', %d) ;"; + $query = $wpdb->prepare($sql, array( + $this->origin, + $this->destination, + json_encode($this->json), + $this->dist, + )); + $results = $wpdb->get_results($query); + + if ( $results == false) { + //failed + $lastid = $wpdb->insert_id; + $msg = sprintf("Insert into address distance db error: date=%s, user1_id=%s, user2_id=%s, orign=%s, dest=%s, resp=%s, dist=%d, db_error=%s", + date('Y-m-d, H:i:s'), + $this->user1->ID, + $this->user2->ID, + $this->origin, + $this->destination, + json_encode($this->json), + $this->dist, + $wpdb->last_error + ); + $error_log = plugin_dir_path(__FILE__) . "/logs/addr.log"; + file_put_contents($error_log, $msg, FILE_APPEND); + } + } + + + private function get_user_address($login){ + $user = get_user_by('login', $login); + $addr = get_user_meta($user->ID, 'address', true); + return $addr; + } + + + private function get_table_name() + { + global $wpdb; + $table_name = $wpdb->prefix . 'acare_addr_distance'; + return $table_name; + } + + private function get_distance_from_db(){ + global $wpdb; + $table_name = $this->get_table_name(); + $sql = "SELECT * FROM $table_name WHERE origin='%s' and destination='%s' "; + $query = $wpdb->prepare($sql, array( + $this->origin, + $this->destination, + )); + $row = $wpdb->get_row($query); + if ( $row == null ) + return false; + return (int) $row->distance; //in meters; + } + + private function super_json_decode($json, &$value, $assoc = false, $depth = 512, $options = 0) { + $pValue = false; + $result = json_decode($json, $assoc, $depth); + if(json_last_error() == JSON_ERROR_NONE) { + $value = $result; + return true; + } + return false; + } + + private function convert_response_to_dist_in_meter($resp){ + $distance = -1; + if (count($resp->routes) >0) + { + $legs = $resp->routes[0]->legs; + foreach ($legs as $l){ + $distance += $l->distance->value; + } + } + return $distance; + } + + private function get_google_direction($origin, $destination) { + $data = ""; + $arg = array( + 'origin' => $origin, + 'destination' => $destination, + 'key'=>'AIzaSyDMRjRh3wu0zTQneYboTk5VgQio3XABz_o', + ); + + $ch = curl_init("https://maps.googleapis.com/maps/api/directions/json?". http_build_query($arg)); + curl_setopt_array($ch, array( + CURLOPT_CONNECTTIMEOUT => 10, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 60, + )); + + $response = false; + if($this->super_json_decode(curl_exec($ch), $data)) { + $response = $data; + } + + $info = curl_getinfo($ch); + if($info['http_code'] !== 200) { + return false; + } + + return $response; + //var_dump($response); + } +} \ No newline at end of file diff --git a/Xero.php b/Xero.php index 70cc92a..be8fe46 100644 --- a/Xero.php +++ b/Xero.php @@ -80,7 +80,7 @@ class Xero { try{ $this->sync_clients(); - //$this->sync_employees(); + $this->sync_employees(); }catch(RateLimitExceededException $e){ $msg= "Xero API rate limit exceeded, please try again later, existing sync within 600 seconds will by passed automatically\n"; $this->logConsole($msg); @@ -198,6 +198,7 @@ class Xero { $id = wp_insert_user($args); $user = get_user_by('ID', $id); update_user_meta($user->ID, 'mobile', $args['mobile']); + update_user_meta($user->ID, 'address', $args['address']); }else{ if ($this->is_too_close_to_sync($user)){ return; @@ -208,6 +209,7 @@ class Xero { unset($args['user_pass']); wp_update_user($args); update_user_meta($user->ID, 'mobile', $args['mobile']); + update_user_meta($user->ID, 'address', $args['address']); } $this->mark_updated($user->ID); } @@ -222,11 +224,31 @@ class Xero { 'last_name' => $e->getLastName(), 'nickname' => $e->getFirstName(), 'mobile' => $e->getMobile(), + 'address'=> $this->get_employee_address($e), 'role' => 'staff', ]; return $args; } + private function get_employee_address($e){ +// "HomeAddress": { +// "AddressLine1": "16 Quist Avenue", +// "City": "Lurnea", +// "Region": "NSW", +// "PostalCode": "2170", +// "Country": "AUSTRALIA" +// }, + $addr = ""; + $home = $e->getHomeAddress(); + $addr .= $home->getAddressLine1() .","; + $addr .= $home->getAddressLine2() .","; + $addr .= $home->getCity() . ","; + $addr .= $home->getRegion() . " "; + $addr .= $home->getCountry() ." "; + $addr .= $home->getPostalCode(); + return $addr; + } + private function mark_updated($userid){ update_user_meta($userid, 'lastsync', time()); } diff --git a/js/bts_timesheet.js b/js/bts_timesheet.js index 3fa1d5a..e16b8df 100644 --- a/js/bts_timesheet.js +++ b/js/bts_timesheet.js @@ -151,7 +151,7 @@ new People("#p" + u.login,'#staff_item', u); }); hide_loading_staff(); - calculate_total_working_hour(); + calculate_total_hour_and_money(); }else{ alert('error getting staff list'); } @@ -324,7 +324,6 @@ } - load_data(data) { this.set_job_id(data.id); @@ -340,16 +339,9 @@ this.data = data; this.el.data({job:this, data:data}); - if (typeof(data.id) === 'undefined' || data.id == ''){ - this.mark_dirty(); - this.mark_new(); - } - else{ - this.mark_saved(); - } + this.mark_dirty_on_new_record(data); this.mark_week_color(); - console.log('this job money = %o', this.get_payment_summary()); - this.validate(); + this.validate(); //also triggers mark errors } get_job_id(){ @@ -479,6 +471,16 @@ }); } + mark_dirty_on_new_record(data){ + if (typeof(data.id) === 'undefined' || data.id == ''){ + this.mark_dirty(); + this.mark_new(); + } + else{ + this.mark_saved(); + } + } + mark_dirty() //need save { var d = this.el.find('.bsave'); @@ -563,7 +565,7 @@ { var str = this.get_finish(); if (! is_valid_date_str(str)){ - this.set_err_msg_finish('wront date'); + this.set_err_msg_finish('wrong date'); this.mark_finish_invalid(); return false; } @@ -836,8 +838,8 @@ $('div.prevweek.left').click(function(){ if (number_of_unsaved_job() > 0){ - alert ("you have unsaved jobs,please save it before proceed"); - return; + if(!confirm("you have unsaved jobs, proceed will lost them")) + return; } $('div.weekdays span.weekday').each(function(i, e){ var date = $(e).data().date; @@ -850,8 +852,8 @@ }); $('div.nextweek.right').click(function(){ if (number_of_unsaved_job() > 0){ - alert ("you have unsaved jobs,please save it before proceed"); - return; + if(!confirm("you have unsaved jobs,proceed will lost them")) + return; } $('div.weekdays span.weekday').each(function(i, e){ @@ -1055,7 +1057,7 @@ }); filter_workspace(staffs, clients); - calculate_total_working_hour(); + calculate_total_hour_and_money(); } function filter_workspace(staffs, clients){ @@ -1081,10 +1083,15 @@ }); } - function calculate_total_working_hour() + var debounced_calculate = debounce(calculate_total_hour_and_money, 2000); + + function calculate_total_hour_and_money() { //init pays for all staff; - var pays=[]; + var pays={ + total: 0, + hours: 0, + }; $('.stafflist > div.peopleitem').each(function(i,e){ var people = $(this).data().obj; people.reset_summary(); @@ -1092,12 +1099,20 @@ $('div.workspace > .divTable').each(function(i,e){ var job = $(e).data().job; //class Job + if (typeof job === 'undefined') + return; var ps = job.get_payment_summary(); + + pays.total += ps.money; + pays.hours += ps.hour; + var staff = job.get_staff(); var people = find_staff(staff); //class People if (people !=false) people.add_payment_summary(ps); }); + set_wages(pays.total.toFixed(2)); + set_working_hours(pays.hours.toFixed(2)); } function find_staff(login) @@ -1108,15 +1123,11 @@ return $('#p'+login).data().obj; } - function calculate_total_money() - { - - } - $(document).on('change', '.divTableRow select, .divTableRow input', function() { var job = $(this).closest('.divTable').data().job; job.validate(); job.mark_dirty(); + debounced_calculate(); }); function init_ts(){ diff --git a/ts.php b/ts.php index 42f8084..018138a 100644 --- a/ts.php +++ b/ts.php @@ -9,18 +9,20 @@ */ namespace Biukop; +use XeroPHP\Models\Accounting\Address; + require_once(dirname(__FILE__) . '/autoload.php'); require_once (ABSPATH . 'wp-includes/pluggable.php'); class AcareOffice{ - private $nonce; //for ajax verification private $pages = array('time-sheets', 'user-list'); private $acaresydney_userid = 0; private $xero ; private $db; private $table_name; + private $addr_table; public function __construct() { add_option( "acare_ts_db_version", "1.0" ); @@ -42,6 +44,8 @@ class AcareOffice{ add_shortcode( 'bts_select_staff', array($this, 'bts_select_staff')); add_shortcode( 'bts_select_client', array($this, 'bts_select_client')); add_shortcode( 'bts_type_of_service', array($this, 'bts_type_of_service')); + //user profile page + add_shortcode( 'bts_user_name', array($this,'bts_user_name')); add_action('wp_ajax_list_staff', array($this,'list_staff' )); @@ -53,10 +57,16 @@ class AcareOffice{ add_action('wp_ajax_earnings_rate', array($this,'get_payitem_earnings_rate' )); add_action('wp_ajax_nopriv_earnings_rate', array($this,'get_payitem_earnings_rate' )); + // hook add_rewrite_rules function into rewrite_rules_array + add_filter('rewrite_rules_array', array($this,'my_add_rewrite_rules')); + // hook add_query_vars function into query_vars + add_filter('query_vars', array($this,'add_query_vars')); + global $wpdb; $this->db = $wpdb; $this->table_name = $wpdb->prefix . 'acare_ts'; + $this->addr_table = $wpdb->prefix . 'acare_addr_distance'; } @@ -77,6 +87,8 @@ class AcareOffice{ $this->xero = new Xero(); $this->xero->init_wp(); + + $abc = new AddrMap("01515b52-6936-46b2-a000-9ad4cd7a5b50", "0768db6d-e5f4-4b45-89a2-29f7e8d2953c"); } //init database @@ -84,9 +96,8 @@ class AcareOffice{ global $wpdb; $charset_collate = $wpdb->get_charset_collate(); - //table name: broker transactions + //table name: timesheets jobs $table_name = $this->table_name; - $sql = "CREATE TABLE $table_name ( id INT NOT NULL AUTO_INCREMENT, tos VARCHAR(45) NULL, @@ -99,12 +110,40 @@ class AcareOffice{ rating INT(4) NULL DEFAULT 0, PRIMARY KEY (id) ) $charset_collate;"; + + //addr distance + $addr_table = $this->addr_table; + $sql_addr = "CREATE TABLE $addr_table ( + id INT NOT NULL AUTO_INCREMENT, + origin VARCHAR(1024) NULL, + destination VARCHAR(1024) NULL, + response VARCHAR(40960) NULL, + distance INT NULL, + PRIMARY KEY (id) + ) $charset_collate;"; //create database require_once( ABSPATH . 'wp-admin/includes/upgrade.php' ); dbDelta( $sql ); + dbDelta( $sql_addr); + } + + // + //query var + public function add_query_vars($aVars) { + $aVars[] = "bts_user_id"; // represents the name of the product category as shown in the URL + return $aVars; + } + + //for customer profile and broker trans + public function my_add_rewrite_rules($aRules) { + $aNewRules = array('user/([^/]+)/?$' => 'index.php?pagename=user&bts_user_id=$matches[1]'); + $aRules = $aNewRules + $aRules; + + return $aRules; } + // // @@ -228,6 +267,13 @@ class AcareOffice{ return $result; } + public function bts_user_name($attr) + { + //echo '
A hahah
;'; + $content = '[vc_row wpex_bg_overlay="color" wpex_bg_overlay_color="#ffffff"][vc_column][vcex_heading text="Heading13331" style="bottom-border-w-color" css_animation="flipInY" icon="fa fa-handshake-o" inner_bottom_border_color="#000000" width="100%;"][/vc_column][/vc_row][vc_row][vc_column][/vc_column][/vc_row][vc_row][vc_column][/vc_column][/vc_row]'; + echo do_shortcode($content); + } + //generate template based on html file private function template($id, $file) { @@ -246,8 +292,8 @@ class AcareOffice{ 'users' => [], ); //search all users that are staff - $staffq = new \WP_User_Query(array('role'=>'staff','meta_key'=>'first_name', 'orderby'=>'meta_value', order=>'ASC')); - $staff = $staffq->get_results(); + $staffq = new \WP_User_Query(array('role'=>'staff','meta_key'=>'first_name', 'orderby'=>'meta_value', 'order'=>'ASC')); + $staff = $staffq->get_results(); if (! empty($staff)){ $response['status'] = 'success'; foreach( $staff as $s){ @@ -449,3 +495,5 @@ $bb = new AcareOffice(); if ( defined( 'WP_CLI' ) && WP_CLI ) { \WP_CLI::add_command( 'sync_users', array($bb, 'sync_user_cli')); } + +