timesheet source code
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

975 lines
36KB

  1. <?php
  2. /**
  3. * Plugin Name: Acare Advanced Office
  4. * Plugin URI: http://biukop.com.au/acaresydney/timesheets
  5. * Description: Advanced Office system, timesheet, Payroll for AcareSydney
  6. * Version: 2.1
  7. * Author: Biukop Intelligence
  8. * Author URI: http://biukop.com.au/
  9. */
  10. namespace Biukop;
  11. use XeroPHP\Models\Accounting\Address;
  12. require_once(dirname(__FILE__) . '/autoload.php');
  13. require_once (ABSPATH . 'wp-includes/pluggable.php');
  14. class AcareOffice{
  15. private $nonce; //for ajax verification
  16. private $pages = array('time-sheets', 'user-list');
  17. private $bts_user_id = 0;
  18. private $bts_week_id = 1; //week 1, we will try to calculate current week;
  19. private $xero ;
  20. private $db;
  21. private $table_name;
  22. private $addr_table;
  23. public function __construct() {
  24. add_option( "acare_ts_db_version", "1.0" );
  25. register_activation_hook( __FILE__, array($this, 'db_install') );
  26. add_action('init', array($this, 'class_loader'));
  27. add_action('wp', array($this, 'check_auth'));
  28. add_action('wp_enqueue_scripts', array($this, 'register_js_css'), 99);
  29. add_filter('show_admin_bar', '__return_false');
  30. //ts-xx for sync single user
  31. add_shortcode( 'ts-sync-users', array($this, 'sync_users'));
  32. //bts-xx for webpage
  33. add_shortcode( 'bts_staff_item', array($this, 'bts_staff_item'));
  34. add_shortcode( 'bts_client_item', array($this, 'bts_client_item'));
  35. add_shortcode( 'bts_job_item', array($this, 'bts_job_item'));
  36. add_shortcode( 'bts_rate_options', array($this, 'bts_rate_options'));
  37. add_shortcode( 'bts_select_staff', array($this, 'bts_select_staff'));
  38. add_shortcode( 'bts_select_client', array($this, 'bts_select_client'));
  39. add_shortcode( 'bts_type_of_service', array($this, 'bts_type_of_service'));
  40. add_shortcode( 'bts_staff_job_summary', array($this, 'bts_staff_job_summary'));
  41. add_shortcode( 'bts_feedback_card', array($this, 'bts_feedback_card'));
  42. add_shortcode( 'bb_timesheet_canvas', array($this, 'bb_timesheet_canvas'));
  43. //user profile page
  44. add_shortcode( 'bts_user_name', array($this,'bts_user_name'));
  45. add_action('wp_ajax_list_staff', array($this,'list_staff' ));
  46. add_action('wp_ajax_list_client', array($this,'list_client' ));
  47. add_action('wp_ajax_save_job', array($this,'save_job' ));
  48. add_action('wp_ajax_list_job', array($this,'list_job' ));
  49. add_action('wp_ajax_delete_job', array($this,'delete_job' ));
  50. add_action('wp_ajax_email_job', array($this,'email_job' ));
  51. add_action('wp_ajax_earnings_rate', array($this,'get_payitem_earnings_rate' ));
  52. add_action('wp_ajax_nopriv_earnings_rate', array($this,'get_payitem_earnings_rate' ));
  53. add_action('wp_ajax_list_job_by_staff', array($this,'list_job_by_staff' ));
  54. add_action('wp_ajax_nopriv_list_job_by_staff', array($this,'list_job_by_staff' ));
  55. add_action('wp_ajax_staff_ack_job', array($this,'staff_ack_job' ));
  56. add_action('wp_ajax_nopriv_staff_ack_job', array($this,'staff_ack_job' ));
  57. add_action('wp_ajax_list_job_by_client', array($this,'list_job_by_client' ));
  58. add_action('wp_ajax_nopriv_list_job_by_client', array($this,'list_job_by_client' ));
  59. add_action('wp_ajax_client_ack_job', array($this,'client_ack_job' ));
  60. add_action('wp_ajax_nopriv_client_ack_job', array($this,'client_ack_job' ));
  61. // hook add_rewrite_rules function into rewrite_rules_array
  62. add_filter('rewrite_rules_array', array($this,'my_add_rewrite_rules'));
  63. // hook add_query_vars function into query_vars
  64. add_filter('query_vars', array($this,'add_query_vars'));
  65. global $wpdb;
  66. $this->db = $wpdb;
  67. $this->table_name = $wpdb->prefix . 'acare_ts';
  68. $this->addr_table = $wpdb->prefix . 'acare_addr_distance';
  69. $this->ndis_table = $wpdb->prefix . 'acare_ndis_price';
  70. }
  71. /**
  72. * Autoload the custom theme classes
  73. */
  74. public function class_loader()
  75. {
  76. // Create a new instance of the autoloader
  77. $loader = new \Psr4AutoloaderClass();
  78. // Register this instance
  79. $loader->register();
  80. // Add our namespace and the folder it maps to
  81. $loader->addNamespace('\XeroPHP', dirname(__FILE__) . '/xero-php-master/src/XeroPHP');
  82. $loader->addNamespace('\Biukop', dirname(__FILE__) . '/' );
  83. $this->xero = new Xero();
  84. $this->xero->init_wp();
  85. //$abc = new AddrMap("01515b52-6936-46b2-a000-9ad4cd7a5b50", "0768db6d-e5f4-4b45-89a2-29f7e8d2953c");
  86. $abc = new AddrMap("122eb1d0-d8c4-4fc3-8bf8-b7825bee1a01", "0768db6d-e5f4-4b45-89a2-29f7e8d2953c");
  87. }
  88. //init database
  89. public function db_install () {
  90. global $wpdb;
  91. $charset_collate = $wpdb->get_charset_collate();
  92. //table name: timesheets jobs
  93. $table_name = $this->table_name;
  94. $sql = "CREATE TABLE $table_name (
  95. id INT NOT NULL AUTO_INCREMENT,
  96. tos VARCHAR(45) NULL,
  97. start DATETIME NULL,
  98. finish DATETIME NULL,
  99. rate VARCHAR(45) NULL,
  100. staff VARCHAR(45) NULL,
  101. client VARCHAR(45) NULL,
  102. ack TINYINT(4) NULL,
  103. rating INT(4) NULL DEFAULT 0,
  104. PRIMARY KEY (id)
  105. ) $charset_collate;";
  106. //addr distance
  107. $addr_table = $this->addr_table;
  108. $sql_addr = "CREATE TABLE $addr_table (
  109. id INT NOT NULL AUTO_INCREMENT,
  110. origin VARCHAR(1024) NULL,
  111. destination VARCHAR(1024) NULL,
  112. response VARCHAR(40960) NULL,
  113. distance INT NULL,
  114. PRIMARY KEY (id)
  115. ) $charset_collate;";
  116. $ndis_table = $this->ndis_table;
  117. $sql_ndis_price = "
  118. CREATE TABLE $ndis_table (
  119. code VARCHAR(45) NOT NULL,
  120. name VARCHAR(45) NULL,
  121. level INT NULL,
  122. unit VARCHAR(45) NULL,
  123. price FLOAT NULL,
  124. year INT NOT NULL,
  125. PRIMARY KEY (code, year)
  126. )$charset_collate;";
  127. //create database
  128. require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
  129. dbDelta( $sql );
  130. dbDelta( $sql_addr);
  131. dbDelta( $sql_ndis_price);
  132. }
  133. //
  134. //query var
  135. public function add_query_vars($aVars) {
  136. $aVars[] = "bts_user_id"; // represents the name of the product category as shown in the URL
  137. $aVars[] = "bts_week_id"; // represents the name of the product category as shown in the URL
  138. $aVars[] = "bts_job_start"; // represents the name of the product category as shown in the URL
  139. $aVars[] = "bts_job_finish"; // represents the name of the product category as shown in the URL
  140. return $aVars;
  141. }
  142. //for customer profile and broker trans
  143. public function my_add_rewrite_rules($aRules) {
  144. $aNewRules = array(
  145. 'user/([^/]+)/?$' => 'index.php?pagename=user&bts_user_id=$matches[1]',
  146. 'task/week-([^/]+)/?$' => 'index.php?pagename=task&bts_week_id=$matches[1]',
  147. 'task/start-([^/]+)/finish-([^/]+)/?$' => 'index.php?pagename=task&bts_job_start=$matches[1]&bts_job_finish=$matches[2]',
  148. 'task/([^/]+)/?$' => 'index.php?pagename=task&bts_user_id=$matches[1]',
  149. 'task/([^/]+)/week-([^/]+)/?$' => 'index.php?pagename=task&bts_user_id=$matches[1]&bts_week_id=$matches[2]',
  150. 'task/([^/]+)/start-([^/]+)/finish-([^/]+)/?$' => 'index.php?pagename=task&bts_user_id=$matches[1]&bts_job_start=$matches[2]&bts_job_finish=$matches[3]',
  151. 'feedback_card/week-([^/]+)/?$' => 'index.php?pagename=feedback_card&bts_week_id=$matches[1]',
  152. 'feedback_card/start-([^/]+)/finish-([^/]+)/?$' => 'index.php?pagename=feedback_card&bts_job_start=$matches[1]&bts_job_finish=$matches[2]',
  153. 'feedback_card/([^/]+)/?$' => 'index.php?pagename=feedback_card&bts_user_id=$matches[1]',
  154. 'feedback_card/([^/]+)/week-([^/]+)/?$' => 'index.php?pagename=feedback_card&bts_user_id=$matches[1]&bts_week_id=$matches[2]',
  155. 'feedback_card/([^/]+)/start-([^/]+)/finish-([^/]+)/?$' => 'index.php?pagename=feedback_card&bts_user_id=$matches[1]&bts_job_start=$matches[2]&bts_job_finish=$matches[3]',
  156. );
  157. $aRules = $aNewRules + $aRules;
  158. return $aRules;
  159. }
  160. //
  161. //
  162. ///check auth
  163. public function check_auth(){
  164. global $pagename;
  165. switch($pagename){
  166. case 'task':
  167. $this->cauth_task();
  168. break;
  169. case 'time-sheets':
  170. $this->cauth_time_sheet();
  171. break;
  172. case 'feedback_card':
  173. $this->cauth_feedback_card();
  174. break;
  175. }
  176. }
  177. private function cauth_task(){
  178. $login = get_query_var( 'bts_user_id' );
  179. $this->bts_job_start = get_query_var( 'bts_job_start' );
  180. $this->bts_job_finish = get_query_var( 'bts_job_finish' );
  181. $this->bts_week_id = get_query_var('bts_week_id');
  182. $redirect_url = $this->get_redirect_url_for_task();
  183. // wp_send_json(array(
  184. // 'week'=> $week,
  185. // 'userid'=>$login,
  186. // 'job_start' => $this->bts_job_start,
  187. // 'job_finish' => $this->bts_job_finish,
  188. // 'redirect' => $redirect_url,
  189. // ));
  190. if ($login != "")//perform autologin, and redirect
  191. {
  192. $staff = get_user_by('login', $login);
  193. if ($this->is_staff($staff)){//is valid staff;
  194. $current = wp_get_current_user();
  195. if($current->ID != $staff->ID){
  196. wp_logout();
  197. wp_set_current_user($staff->ID, $staff->display_name); //this is a must
  198. wp_set_auth_cookie($staff->ID, true);//only with this, wordpress calls login + redirect and lost week-%d
  199. }
  200. }
  201. wp_redirect($redirect_url);
  202. return;
  203. }
  204. //no auto login is required if reach here.
  205. $current = wp_get_current_user();
  206. if ($this->is_admin($current)){
  207. wp_redirect("/time-sheets/");
  208. return;
  209. }
  210. if (!$this->is_staff($current) && ! $this->is_admin($current))
  211. {
  212. wp_logout();
  213. wp_redirect("/login/");
  214. return;
  215. }
  216. }
  217. private function cauth_feedback_card(){
  218. $login = get_query_var( 'bts_user_id' );
  219. $this->bts_job_start = get_query_var( 'bts_job_start' );
  220. $this->bts_job_finish = get_query_var( 'bts_job_finish' );
  221. $this->bts_week_id = get_query_var('bts_week_id');
  222. $redirect_url = $this->get_redirect_url_for_feedback_card();
  223. if ($login != "")//perform autologin, and redirect
  224. {
  225. $client = get_user_by('login', $login);
  226. if ($this->is_client($client)){//is valid client;
  227. $current = wp_get_current_user();
  228. if($current->ID != $client->ID){
  229. wp_logout();
  230. wp_set_current_user($client->ID, $client->display_name); //this is a must
  231. wp_set_auth_cookie($client->ID, true);//only with this, wordpress calls login + redirect and lost week-%d
  232. }
  233. }
  234. wp_redirect($redirect_url);
  235. return;
  236. }
  237. //no auto login is required if reach here.
  238. $current = wp_get_current_user();
  239. if ($this->is_admin($current)){
  240. wp_redirect("/time-sheets/");
  241. return;
  242. }
  243. if (!$this->is_client($current) && ! $this->is_admin($current))
  244. {
  245. wp_logout();
  246. wp_redirect("/login/");
  247. return;
  248. }
  249. }
  250. private function get_week_id()
  251. {
  252. $week = get_query_var( 'bts_week_id' );
  253. $week_id = intval($week);
  254. if ($week_id == 0 || $week_id >53 ||$week_id < 1)
  255. return $this->get_current_week_id();
  256. else
  257. return $week;
  258. }
  259. private function get_current_week_id()
  260. {
  261. $now = new \DateTime();
  262. $week = $now->format("W");
  263. return $week;
  264. }
  265. private function get_redirect_url_for_task()
  266. {
  267. if ($this->bts_week_id != "")
  268. return "/task/week-" . $this->bts_week_id . "/";
  269. if ($this->bts_job_start!="" && $this->bts_job_finish !="")
  270. return "/task/start-" . $this->bts_job_start . "/finish-" .$this->bts_job_finish . "/";
  271. return '/task/';
  272. }
  273. private function get_redirect_url_for_feedback_card()
  274. {
  275. if ($this->bts_week_id != "")
  276. return "/feedback_card/week-" . $this->bts_week_id . "/";
  277. if ($this->bts_job_start!="" && $this->bts_job_finish !="")
  278. return "/feedback_card/start-" . $this->bts_job_start . "/finish-" .$this->bts_job_finish . "/";
  279. return '/feedback_card/';
  280. }
  281. private function cauth_time_sheet()
  282. {
  283. $current = wp_get_current_user();
  284. if ($current->ID == 0 ) { //visitor not logged in
  285. wp_redirect("/wp-login.php?");
  286. return;
  287. }
  288. if ($this->is_staff($current)){
  289. wp_redirect("/task");
  290. return;
  291. }
  292. if ($this->is_admin($current)){
  293. //proceed
  294. return;
  295. }
  296. if ($this->is_client($current)){
  297. wp_redirect("/service");
  298. return;
  299. }
  300. //everything else
  301. wp_redirect("/?invalid-access");
  302. }
  303. ///
  304. // enqueue / register css /js
  305. //
  306. public function register_js_css() {
  307. $this->nonce = wp_create_nonce('acaresydney');
  308. $this->bts_user_id = get_query_var( 'bts_user_id' ) ;
  309. $this->register_bts_js();
  310. $this->register_timesheet_js_css();
  311. $this->register_task_js_css();
  312. $this->register_feedback_card_js_css();
  313. }
  314. private function register_bts_js()
  315. {
  316. wp_enqueue_style( 'bts', plugins_url('css/ts.css', __FILE__));
  317. wp_enqueue_script('bts', plugins_url('js/ts.js', __FILE__), array('jquery', 'jquery-ui-core'));
  318. wp_localize_script( 'bts', 'bts1', array(
  319. 'ajax_url' => admin_url( 'admin-ajax.php' ),
  320. 'nonce' => $this->nonce, // It is common practice to comma after
  321. 'display_name' => wp_get_current_user()->display_name,
  322. 'anonymous' => !is_user_logged_in(),
  323. 'me'=> get_current_user_id(),
  324. 'userid'=> $this->bts_user_id,
  325. 'load_user_img'=> plugins_url('img/loading_user.gif', __FILE__),
  326. 'load_job_img'=> plugins_url('img/loading_job.gif', __FILE__),
  327. 'earnings_rate'=> get_option('bts_payitem_earnings_rate'),
  328. 'high_pay_keywords' => ['sat ', 'sun ', 'high ', 'public holiday'], //space is important
  329. ) );
  330. }
  331. private function register_timesheet_js_css(){
  332. global $pagename;
  333. if ($pagename != 'time-sheets'){
  334. return;
  335. }
  336. wp_enqueue_style( 'bts_ts', plugins_url('css/bts_timesheet.css', __FILE__));
  337. wp_enqueue_script( 'bts_ts', plugins_url('js/bts_timesheet.js', __FILE__), array( 'jquery' , 'bts' ));
  338. wp_enqueue_script('mustache', plugins_url('js/mustache.min.js', __FILE__), array('jquery'));
  339. global $wp_scripts;
  340. wp_enqueue_script('jquery-ui-datepicker');
  341. // get registered script object for jquery-ui
  342. //$ui = $wp_scripts->query('jquery-ui-core');
  343. // tell WordPress to load the Smoothness theme from Google CDN
  344. //$protocol = is_ssl() ? 'https' : 'http';
  345. // $url = "$protocol://ajax.googleapis.com/ajax/libs/jqueryui/{$ui->ver}/themes/smoothness/jquery-ui.min.css";
  346. $url = plugins_url('jquery-ui-1.11.4.theme/jquery-ui.min.css', __FILE__);
  347. wp_enqueue_style('jquery-ui-smoothness', $url, false, null);
  348. }
  349. private function register_task_js_css(){
  350. global $pagename;
  351. if ($pagename != 'task'){
  352. return;
  353. }
  354. $this->bts_job_start = get_query_var( 'bts_job_start' );
  355. $this->bts_job_finish = get_query_var( 'bts_job_finish' );
  356. $this->bts_week_id = get_query_var('bts_week_id');
  357. wp_enqueue_style( 'bts_task', plugins_url('css/bts_task.css', __FILE__));
  358. wp_enqueue_script( 'bts_task', plugins_url('js/bts_task.js', __FILE__), array( 'jquery' , 'bts' ));
  359. wp_enqueue_script('mustache', plugins_url('js/mustache.min.js', __FILE__), array('jquery'));
  360. wp_localize_script('bts_task','bts_task1',array(
  361. 'ajax_url' => admin_url( 'admin-ajax.php' ),
  362. 'nonce' => wp_create_nonce('bts_task'),
  363. 'week_id' => $this->bts_week_id,
  364. 'bts_job_start' => $this->bts_job_start,
  365. 'bts_job_finish' => $this->bts_job_finish,
  366. ) );
  367. }
  368. private function register_feedback_card_js_css()
  369. {
  370. global $pagename;
  371. if ($pagename != 'feedback_card'){
  372. return;
  373. }
  374. $this->bts_job_start = get_query_var( 'bts_job_start' );
  375. $this->bts_job_finish = get_query_var( 'bts_job_finish' );
  376. $this->bts_week_id = get_query_var('bts_week_id');
  377. wp_enqueue_style( 'feedback_card', plugins_url('css/feedback_card.css', __FILE__));
  378. wp_enqueue_script( 'feedback_card', plugins_url('js/feedback_card.js', __FILE__), array( 'jquery' , 'bts' ));
  379. wp_enqueue_script('mustache', plugins_url('js/mustache.min.js', __FILE__), array('jquery'));
  380. wp_localize_script('feedback_card','feedback_card',array(
  381. 'ajax_url' => admin_url( 'admin-ajax.php' ),
  382. 'nonce' => wp_create_nonce('feedback_card'),
  383. 'week_id' => $this->bts_week_id,
  384. 'bts_job_start' => $this->bts_job_start,
  385. 'bts_job_finish' => $this->bts_job_finish,
  386. ) );
  387. }
  388. public function sync_users()
  389. {
  390. //dummy sync
  391. return;
  392. }
  393. // Usage: `wp sync_users --mininterval=123
  394. public function sync_user_cli($args = array(), $assoc_args = array()){
  395. $arguments = wp_parse_args( $assoc_args, array(
  396. 'mininterval' => 600,
  397. 'employeeonly' => false,
  398. 'clientsonly' => false,
  399. ) );
  400. $this->xero->sync_users($arguments['mininterval'], $arguments['employeeonly'], $arguments['clientsonly']);
  401. return;
  402. }
  403. public function email_jobs($args = array(), $assoc_args = array()){
  404. $users = get_users(array('role' => 'staff'));
  405. foreach ($users as $u){
  406. $n = new UserJob($u->user_login);
  407. $resp = $n->list_jobs_by_staff("2019-07-22 00:00:00", "2019-07-28 23:59:59");
  408. if ($resp['status']=='success' && $resp['job_count'] >0 ){
  409. if( $u->user_login != "9aa3308e-cc19-4c21-a110-f2c6abec4337" )
  410. continue;
  411. $msg = sprintf("Staff = %s, Login=%s, email=%s Job=%d\n", $u->display_name, $u->user_login, $u->user_email, $resp['job_count']);
  412. echo $msg;
  413. $this->send_email_with_job_link($u, "2019-07-22", "2019-07-28");
  414. }
  415. }
  416. return;
  417. }
  418. private function send_email_with_job_link($staff, $start, $finish)
  419. {
  420. $message = file_get_contents(plugin_dir_path(__FILE__) . "/html/email_job.html");
  421. $message = str_ireplace("{{display_name}}", $staff->display_name, $message);
  422. $message = str_ireplace("{{user_login}}", $staff->user_login, $message);
  423. $message = str_ireplace("{{job_start}}", $start, $message);
  424. $message = str_ireplace("{{job_finish}}", $finish, $message);
  425. $headers = ['Bcc: patrick@biukop.com.au, timesheet@acaresydney.com.au'];
  426. $subject = $staff->display_name . " Job arrangement $start ~ $finish";
  427. //wp_mail("sp@lawipac.com", $subject, $message, $headers);
  428. //wp_mail("timesheet@acaresydney.com.au", $subject, $message, $headers);
  429. wp_mail($staff->user_email, $subject, $message, $headers);
  430. }
  431. public function bts_staff_item($attr){
  432. return $this->template('staff_item', 'staff.html');
  433. }
  434. public function bts_client_item($attr){
  435. return $this->template('client_item', 'client.html');
  436. }
  437. public function bts_job_item($attr){
  438. $html =$this->template('job_item', 'job.html');
  439. //$html = str_replace('[bts-tos-options]', $this->bts_tos_options([]), $html);
  440. $html = do_shortcode($html);
  441. return $html;
  442. }
  443. public function bts_rate_options($attr){
  444. $result = "<select> \n";
  445. $options = get_option('bts_payitem_earnings_rate');
  446. foreach($options as $o){
  447. $result.=sprintf("<option value='%s'> $%3.2f-%s</option>",
  448. $o['EarningsRateID'], $o['RatePerUnit'], $o['Name']);
  449. }
  450. $result .="</select>";
  451. return $result;
  452. }
  453. public function bts_select_staff($attr){
  454. $result = "<select> \n";
  455. $staff = $this->get_people_by_role('staff');
  456. foreach ($staff as $u){
  457. $result .= sprintf("<option value=%s> %s</option>", $u->user_login, $u->first_name . " " . $u->last_name);
  458. }
  459. $result .="</select>";
  460. return $result;
  461. }
  462. public function bts_select_client($attr){
  463. $result = "<select> \n";
  464. $staff = $this->get_people_by_role('client');
  465. foreach ($staff as $u){
  466. $result .= sprintf("<option value=%s> %s</option>", $u->user_login, $u->display_name);
  467. }
  468. $result .="</select>";
  469. return $result;
  470. }
  471. public function bts_type_of_service($attr){
  472. $n = new NdisPrice(2019);
  473. return $n->get_html();
  474. }
  475. public function bts_user_name($attr)
  476. {
  477. $user = wp_get_current_user();
  478. return $user->display_name;
  479. }
  480. public function bts_staff_job_summary($attr)
  481. {
  482. $result ="<span>
  483. If there is more than one job, please click on 'confirm' to make sure it is included in your payment.
  484. </span>";
  485. return $result;
  486. }
  487. public function bts_feedback_card($attr)
  488. {
  489. return $this->template('bts_feedback_card', 'feedback_card.html');
  490. }
  491. public function bb_timesheet_canvas($attr)
  492. {
  493. return file_get_contents(plugin_dir_path(__FILE__) . "/html/timesheet.html");
  494. }
  495. //generate template based on html file
  496. private function template($id, $file)
  497. {
  498. $text = '<script id="' . $id .'" type="text/x-biukop-template">';
  499. $text .= file_get_contents(plugin_dir_path(__FILE__) . "/html/$file");
  500. $text .= '</script>';
  501. return $text;
  502. }
  503. function list_staff(){
  504. check_ajax_referer('acaresydney');
  505. // Handle the ajax request
  506. $response = array(
  507. 'status' =>'error',
  508. 'users' => [],
  509. );
  510. //search all users that are staff
  511. $staffq = new \WP_User_Query(array('role'=>'staff','meta_key'=>'first_name', 'orderby'=>'meta_value', 'order'=>'ASC'));
  512. $staff = $staffq->get_results();
  513. if (! empty($staff)){
  514. $response['status'] = 'success';
  515. foreach( $staff as $s){
  516. $response['users'][] = array(
  517. 'login' => $s->user_login,
  518. 'firstname'=> $s->first_name,
  519. 'lastname'=> $s->last_name,
  520. 'mobile'=> get_user_meta($s->ID, 'mobile', true),
  521. 'email'=> $s->user_email,
  522. 'wages'=> 0,
  523. 'hour' => 0 ,
  524. 'OT' => 0 ,
  525. 'petrol'=> 0 ,
  526. 'rating'=> 0,
  527. 'unconfirmedjob'=> 0,
  528. );
  529. }
  530. }
  531. wp_send_json($response);
  532. wp_die();
  533. }
  534. function list_client(){
  535. check_ajax_referer('acaresydney');
  536. // Handle the ajax request
  537. $response = array(
  538. 'status' =>'error',
  539. 'users' => [],
  540. );
  541. //search all users that are staff
  542. $clientq = new \WP_User_Query(array('role'=>'client', 'meta_key'=>'first_name', 'orderby'=>'meta_value', 'order'=>'ASC'));
  543. $client = $clientq->get_results();
  544. if (! empty($client)){
  545. $response['status'] = 'success';
  546. foreach( $client as $s){
  547. $response['users'][] = array(
  548. 'login' => $s->user_login,
  549. 'firstname'=> $s->first_name,
  550. 'lastname'=> $s->last_name,
  551. 'display_name'=> $s->display_name,
  552. 'mobile'=> get_user_meta($s->ID, 'mobile', true),
  553. 'email'=> $s->user_email,
  554. 'account'=> get_user_meta($s->ID, 'account', true),
  555. 'address' => get_user_meta($s->ID, 'address', true),
  556. 'rating'=> 0,
  557. 'unconfirmedjob'=> 0,
  558. );
  559. }
  560. }
  561. wp_send_json($response);
  562. wp_die();
  563. }
  564. private function get_people_by_role($role){
  565. //search all users that are staff
  566. $staffq = new \WP_User_Query(array('role'=>$role, 'meta_key'=>'first_name', 'orderby'=>'meta_value', 'order'=>'ASC'));
  567. $staff = $staffq->get_results();
  568. return $staff;
  569. }
  570. //ajax get earnings rates
  571. function get_payitem_earnings_rate()
  572. {
  573. $response= array(
  574. 'status' => 'success',
  575. 'options'=> get_option('bts_payitem_earnings_rate'),
  576. );
  577. wp_send_json($response);
  578. }
  579. //ajax job CRUD
  580. function save_job()
  581. {
  582. check_ajax_referer('acaresydney');
  583. $r = $_POST['record'];
  584. $response = array();
  585. $d = array(
  586. 'tos' => $r['tos'],
  587. 'start' => $r['start'],
  588. 'finish' => $r['finish'],
  589. 'rate' => $r['rate'],
  590. 'staff' => $r['staff'],
  591. 'client' => $r['client'],
  592. 'ack' => $r['ack']=='true'?1:0,
  593. 'rating'=>$r['rating'],
  594. );
  595. //this is an update
  596. if ( isset($r['id']) && trim($r['id']) !='' && is_numeric($r['id'])){
  597. $response['isNew'] = false; //add or update?
  598. $result = $this->db->update($this->table_name, $d, array('id' =>$r['id']));
  599. if ($result !== false && $this->db->last_error == ''){
  600. $d['id'] = $r['id'];
  601. $response['status'] = 'success';
  602. //do data type conversion, string to int
  603. $response['newdata'] = $this->get_ts_record($r['id']);
  604. $response['errors'] = array(); //empty array
  605. }else{
  606. $response['status'] = 'error';
  607. $repsonse['errors'] = array(
  608. 'db' => "network database error" . $this->db->last_error,
  609. );
  610. }
  611. }else{
  612. $response['isNew'] = true;
  613. $result = $this->db->insert($this->table_name, $d);
  614. $lastid = $this->db->insert_id;
  615. if ($result != false && $this->db->last_error == ''){
  616. $response['status'] = 'success';
  617. $response['newdata'] = $this->get_ts_record($lastid);
  618. }else{
  619. $response['status'] = 'error';
  620. $response['errors'] = array(
  621. 'db' => 'network database error ' . $this->db->last_error,
  622. );
  623. }
  624. }
  625. wp_send_json($response);
  626. wp_die();
  627. }
  628. private function get_ts_record($id){
  629. $sql = "SELECT * FROM $this->table_name WHERE id=%d";
  630. $row = $this->db->get_row($this->db->prepare ($sql, array($id)));
  631. $response = [];
  632. if ($row != null){
  633. $response = array(
  634. 'id' => (int)$row->id,
  635. 'tos' => $row->tos,
  636. 'start' => $row->start,
  637. 'finish' => $row->finish,
  638. 'rate' => $row->rate,
  639. 'staff' => $row->staff,
  640. 'client' => $row->client,
  641. 'ack' => (int)$row->ack,
  642. 'rating' =>(int) $row->rating,
  643. );
  644. }
  645. return $response;
  646. }
  647. //ajax delete job
  648. function delete_job(){
  649. check_ajax_referer('acaresydney');
  650. $id = $_POST['jobid'];
  651. $result = $this->db->delete($this->table_name, array('id'=> $id));
  652. $response=array(
  653. 'status' => 'success',
  654. 'id' => $id,
  655. 'action'=> 'delete',
  656. 'error' => '',
  657. );
  658. if ($result == 1){
  659. wp_send_json($response);
  660. }else{
  661. $response['status'] = 'error';
  662. $response['error'] = $this->db->last_error;
  663. wp_send_json($response);
  664. }
  665. wp_die();
  666. }
  667. //ajax email staff their job arrangement
  668. function email_job()
  669. {
  670. check_ajax_referer('acaresydney');
  671. $staff = $_POST['staff'];
  672. $start = $_POST['start'];
  673. $finish = $_POST['finish'];
  674. $response=array(
  675. 'status' => 'success',
  676. 'staff' => $staff,
  677. 'start' => $start,
  678. 'finish' => $finish,
  679. 'error' => '',
  680. 'sent' => false,
  681. 'emailstatus'=>"Bypass (no job)",
  682. );
  683. $u = get_user_by('login', $staff);
  684. if ($this->is_staff($u)){
  685. $n = new UserJob($staff);
  686. $resp = $n->list_jobs("$start 00:00:00", "$finish 23:59:59");
  687. if ($resp['status']=='success' && $resp['job_count'] >0 ){
  688. $msg = sprintf("Email to <strong>%s</strong> (with job=%d) \n", $u->user_email, $resp['job_count']);
  689. $this->send_email_with_job_link($u, $start, $finish);
  690. $response['sent'] = true;
  691. $response['emailstatus'] = $msg;
  692. }
  693. }
  694. wp_send_json($response);
  695. }
  696. //ajax browse job with different filters
  697. function list_job(){
  698. check_ajax_referer('acaresydney');
  699. $start = $_POST['start'] . " 00:00:00";
  700. $finish = $_POST['finish']. " 23:59:59";
  701. $response = array(
  702. 'status'=>'success',
  703. 'jobs' => [],
  704. );
  705. $sql = "SELECT * FROM $this->table_name WHERE start>='%s' and start <='%s' order by start ASC ,staff ASC";
  706. $query = $this->db->prepare ($sql, array($start, $finish));
  707. $response['sql'] = $query;
  708. $jobs = $this->db->get_results($query);
  709. if (! empty($jobs)){
  710. $response['status'] = 'success';
  711. foreach( $jobs as $s){
  712. $response['jobs'][] = array(
  713. 'id' => $s->id,
  714. 'tos' => $s->tos,
  715. 'start'=> $s->start,
  716. 'finish'=> $s->finish,
  717. 'rate'=> $s->rate,
  718. 'staff'=> $s->staff,
  719. 'client'=> $s->client,
  720. 'ack' => $s->ack,
  721. 'rating' =>$s->rating,
  722. );
  723. }
  724. }
  725. wp_send_json($response);
  726. wp_die();
  727. }
  728. public function list_job_by_staff()
  729. {
  730. check_ajax_referer('acaresydney');
  731. $start = $_POST['start'];
  732. $finish = $_POST['finish'];
  733. //$start="2019-07-01 00:00:00";
  734. //$finish="2019-07-14 23:59:59";
  735. $user = wp_get_current_user();// should be staff;
  736. if ( $this->is_staff($user) || $this->is_admin($user) ){
  737. $n = new UserJob($user->user_login);
  738. $response = $n->list_jobs_by_staff($start, $finish);
  739. wp_send_json($response);
  740. }else{
  741. $response = array(
  742. 'status' => 'error',
  743. 'errmsg' => 'invalid access',
  744. 'user' => $user,
  745. );
  746. wp_send_json($response);
  747. }
  748. wp_die();
  749. }
  750. public function list_job_by_client()
  751. {
  752. check_ajax_referer('acaresydney');
  753. $start = $_POST['start'];
  754. $finish = $_POST['finish'];
  755. //$start="2019-07-01 00:00:00";
  756. //$finish="2019-07-14 23:59:59";
  757. $user = wp_get_current_user();// should be staff;
  758. if ( $this->is_client($user) || $this->is_admin($user) ){
  759. $n = new UserJob($user->user_login);
  760. $response = $n->list_jobs_by_client($start, $finish);
  761. wp_send_json($response);
  762. }else{
  763. $response = array(
  764. 'status' => 'error',
  765. 'errmsg' => 'invalid access',
  766. 'user' => $user,
  767. );
  768. wp_send_json($response);
  769. }
  770. wp_die();
  771. }
  772. private function is_staff($user)
  773. {
  774. return ($user->ID !=0 && in_array('staff', $user->roles));
  775. }
  776. private function is_client($user)
  777. {
  778. return ($user->ID !=0 && in_array('client', $user->roles));
  779. }
  780. private function is_admin($user)
  781. {
  782. $allowed_roles = array('administrator', 'acare_owner');
  783. if( array_intersect($allowed_roles, $user->roles ) ) {
  784. return true;
  785. }
  786. }
  787. public function staff_ack_job()
  788. {
  789. check_ajax_referer('acaresydney');
  790. $jobs = $_POST['jobs'];
  791. $response = array(
  792. 'status'=>'success',
  793. 'jobs'=>$jobs,
  794. );
  795. $yes=[];
  796. $no=[];
  797. foreach($jobs as $job){
  798. if ( $job['ack'] == "true")
  799. $yes[] =(int) $job['id'];
  800. else
  801. $no[] = (int) $job['id'];
  802. }
  803. $err = $this->ack_multiple_job($yes, $no);
  804. if ($this->db->last_error !='')
  805. {
  806. $response['status']= 'error';
  807. $response['err_msg']= $err;
  808. }
  809. $response['yes'] = $yes;
  810. $response['no'] = $no;
  811. wp_send_json($response);
  812. wp_die();
  813. }
  814. public function ack_multiple_job($yes, $no)
  815. {
  816. $str_yes_ids = implode(",", $yes);
  817. $str_no_ids = implode(",", $no);
  818. $err = "";
  819. if (count($yes) >0 ){
  820. $sql = "UPDATE $this->table_name SET ack=1 WHERE id IN ( $str_yes_ids) ; ";
  821. $r = $this->db->get_results($sql);
  822. $err = $this->db->last_error;
  823. }
  824. if (count($no) >0 ){
  825. $sql = "UPDATE $this->table_name SET ack=0 WHERE id IN ( $str_no_ids) ; ";
  826. $r = $this->db->get_results($sql);
  827. $err .= $this->db->last_error;
  828. }
  829. return $err;
  830. }
  831. public function client_ack_job()
  832. {
  833. check_ajax_referer('acaresydney');
  834. $job_id = $_POST['job_id'];
  835. $rating = $_POST['rating'];
  836. $response = array(
  837. 'status'=>'success',
  838. );
  839. $sql= "UPDATE $this->table_name SET rating=%d WHERE id = %d ; ";
  840. $sql= $this->db->prepare($sql, array($rating, $job_id));
  841. $result = $this->db->get_results($sql);
  842. $response['rating'] = (int) $rating;
  843. if ($this->db->last_error !='')
  844. {
  845. $response['status']= 'error';
  846. $response['err_msg']= $this->db->last_error;
  847. $response['rating'] = 0;
  848. }
  849. wp_send_json($response);
  850. }
  851. public function feedback_url()
  852. {
  853. $users = get_users(array('role'=>'client'));
  854. foreach($users as $u){
  855. echo sprintf("%s:\t https://acaresydney.com.au/feedback_card/%s/\n", $u->display_name, $u->user_login);
  856. }
  857. }
  858. }
  859. $bb = new AcareOffice();
  860. if ( defined( 'WP_CLI' ) && WP_CLI ) {
  861. \WP_CLI::add_command( 'sync_users', array($bb, 'sync_user_cli'));
  862. \WP_CLI::add_command( 'email_jobs', array($bb, 'email_jobs'));
  863. \WP_CLI::add_command( 'feedback_url', array($bb, 'feedback_url'));
  864. }
  865. //$bb->class_loader();
  866. //$bb->list_job_by_staff();