timesheet source code
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

221 lines
7.7KB

  1. <?php
  2. namespace Biukop;
  3. use \XeroPHP\Application\PrivateApplication;
  4. use \XeroPHP\Remote\Exception\RateLimitExceededException;
  5. class Xero {
  6. private $xero;
  7. private $clientgroup="48646f3d-cf5e-4fea-8c8b-5812bd540e1b";
  8. private $minimum_sync_interval_in_seconds = 600;
  9. private function default_config(){
  10. $config = array(
  11. 'oauth' => [
  12. 'callback' => 'http://acaresydney.com.au/',
  13. 'consumer_key' => 'G6AJIRWTH0X3C5SVS3ETZXNFCMDNGG',
  14. 'consumer_secret' => 'LP0PTSBCJLBB4CGYYKOHDXYF2NWXWD',
  15. 'rsa_private_key' => 'file://' . dirname(__FILE__) . '/keys/privatekey.pem',
  16. ],
  17. );
  18. return $config;
  19. }
  20. private function office_config(){
  21. $office_config = [
  22. 'xero' => [
  23. // 'payroll_version' =>'1.9',
  24. ],
  25. 'curl' => [
  26. CURLOPT_USERAGENT =>'AcareSydneyWebOffice',
  27. ],
  28. 'oauth' => [
  29. 'callback' => 'http://acaresydney.com.au/',
  30. 'consumer_key' => 'JE4LWKCJ6NHED30RFZWCT7WQYTS8JD',
  31. 'consumer_secret' => 'JXVZAZWKGM7MLUZSVIMK7ZSJE9GNYQ',
  32. 'rsa_private_key' => 'file://' . dirname(__FILE__) . '/keys/privatekey.pem',
  33. ],
  34. ];
  35. return $office_config;
  36. }
  37. public function __construct(){
  38. $this->xero = new PrivateApplication($this->office_config());
  39. }
  40. public function getClients($contact_group_id){
  41. $xero = $this->xero;
  42. $cg = $xero->loadByGUID("Accounting\\ContactGroup", $contact_group_id);
  43. $contacts = $cg->getContacts();
  44. return $contacts;
  45. }
  46. public function getContact($id){
  47. $user = $this->xero->loadByGUID("Accounting\\Contact",$id);
  48. return $user;
  49. }
  50. public function getEmployees(){
  51. $employees = $this->xero->load("PayrollAU\\Employee")
  52. ->where('EmployeeGroupName="Web-Employee"')
  53. ->execute();
  54. return $employees;
  55. }
  56. public function getEmployee($id){
  57. $employee = $this->xero->loadByGUID("PayrollAU\\Employee",$id);
  58. return $employee;
  59. }
  60. //
  61. //sync users to wordpress system
  62. //does not work for too many users or employees
  63. public function sync_users($mininterval){
  64. $this->usage();
  65. $this->minimum_sync_interval_in_seconds = $mininterval;
  66. $msg="Sync users with minimum interval set to $mininterval \n";
  67. $this->logConsole($msg);
  68. try{
  69. //$this->sync_clients();
  70. $this->sync_employees();
  71. }catch(RateLimitExceededException $e){
  72. $msg= "Xero API rate limit exceeded, please try again later, existing sync within 600 seconds will by passed automatically\n";
  73. $this->logConsole($msg);
  74. }
  75. }
  76. private function sync_clients(){
  77. $contacts = $this->getClients($this->clientgroup);
  78. foreach ($contacts as $c){
  79. $msg = sprintf("SYNC Client name=[%s] {%s} \n", $c->getName(), $c->getContactID());
  80. $this->logConsole($msg);
  81. $this->ensure_contact_exists($c);
  82. }
  83. }
  84. private function sync_employees(){
  85. $employees = $this->getEmployees();
  86. foreach ( $employees as $e){
  87. $msg = sprintf("SYNC employee name=[%s %s] {%s} \n", $e->getFirstName(), $e->getLastName(), $e->getEmployeeID());
  88. $this->logConsole($msg);
  89. $this->ensure_staff_exists($e);
  90. }
  91. }
  92. private function ensure_contact_exists($contact){
  93. $login = $contact->getContactID();
  94. $user = get_user_by('login', $login);
  95. if ($user === false){
  96. $xero_contact = $this->getContact($login);
  97. $args = $this->xero_contact_profile($xero_contact);
  98. $id = wp_insert_user($args);
  99. $user = get_user_by('ID', $id);
  100. }else{//update user
  101. if ($this->is_too_close_to_sync($user)){
  102. return;
  103. }
  104. $xero_contact = $this->getContact($login);
  105. $args = $this->xero_contact_profile($xero_contact);
  106. $args['ID'] = $user->ID;
  107. unset($args['user_pass']); //we don't change password
  108. wp_update_user($args);
  109. }
  110. $this->mark_updated($user->ID);
  111. }
  112. private function xero_contact_profile($c){
  113. $args = [
  114. 'user_login' => $username = $c->getContactID(),
  115. 'user_pass' => md5(uniqid(rand() + time(), true)),
  116. 'display_name' =>$c->getName(),
  117. 'user_email' => $c->getEmailAddress(),
  118. 'first_name' => $c->getFirstName(),
  119. 'last_name' => $c->getLastName(),
  120. 'nickname' => $c->getName(),
  121. 'role' => 'client',
  122. ];
  123. return $args;
  124. }
  125. private function ensure_staff_exists($employee)
  126. {
  127. $login = $employee->getEmployeeID();
  128. $user = get_user_by('login', $login);
  129. if ($user === false){
  130. $xero_employee = $this->getEmployee($login);
  131. $args = $this->xero_employee_profile($xero_employee);
  132. $id = wp_insert_user($args);
  133. $user = get_user_by('ID', $id);
  134. }else{
  135. if ($this->is_too_close_to_sync($user)){
  136. return;
  137. }
  138. $xero_employee = $this->getEmployee($login);
  139. $args = $this->xero_employee_profile($xero_employee);
  140. $args['ID'] = $user->ID;
  141. unset($args['user_pass']);
  142. wp_update_user($args);
  143. update_user_meta($user->ID, 'mobile', $args['mobile']);
  144. }
  145. $this->mark_updated($user->ID);
  146. }
  147. private function xero_employee_profile($e){
  148. $args = [
  149. 'user_login' => $username = $e->getEmployeeID(),
  150. 'user_pass' => md5(uniqid(rand() + time(), true)),
  151. 'display_name' =>$e->getFirstName() . " " . $e->getLastName(),
  152. 'user_email' => $e->getEmail(),
  153. 'first_name' => $e->getFirstName(),
  154. 'last_name' => $e->getLastName(),
  155. 'nickname' => $e->getFirstName(),
  156. 'mobile' => $e->getMobile(),
  157. 'role' => 'staff',
  158. ];
  159. return $args;
  160. }
  161. private function mark_updated($userid){
  162. update_user_meta($userid, 'lastsync', time());
  163. }
  164. private function get_last_sync($userid){
  165. $lastsync = get_user_meta($userid, 'lastsync', true);
  166. return (int)($lastsync);
  167. }
  168. private function is_too_close_to_sync($user){
  169. $userid = $user->ID;
  170. $lastsync = $this->get_last_sync($user->ID);
  171. $now = time();
  172. $diff = $now - (int) $lastsync;
  173. if ($diff < $this->minimum_sync_interval_in_seconds){
  174. $msg = sprintf("\tSKIP userid(%d),login=%s,display_name=%s,(lastsync=%d secs ago, mininterval=%d) \n",
  175. $user->ID, $user->user_login, $user->display_name, $diff, $this->minimum_sync_interval_in_seconds);
  176. $this->logConsole($msg);
  177. return true;
  178. }
  179. return false;
  180. }
  181. private function logConsole($str){
  182. //if is commandline
  183. if ( defined( 'WP_CLI' ) && WP_CLI ) {
  184. echo $str;
  185. }
  186. }
  187. private function usage(){
  188. $msg = "_____________________________________________\n";
  189. $msg .= "run this command at public_html/, where wp-config.php exist \n";
  190. $msg .= "wp sync_users --mininterval=6000 \n";
  191. $msg .= "6000 means those users synced within 6000 seconds will be bypassed \n";
  192. $msg .= "to sync everything \n";
  193. $msg .= "wp sync_users --mininterval=0 \n";
  194. $msg .= "but it may hit XERO rate limit, 60call/sec, 5000/day \n";
  195. $msg .= "---------------------------------------------\n";
  196. $this->logConsole($msg);
  197. }
  198. }