2 // +----------------------------------------------------------------------+
 
   3 // | Anuko Time Tracker
 
   4 // +----------------------------------------------------------------------+
 
   5 // | Copyright (c) Anuko International Ltd. (https://www.anuko.com)
 
   6 // +----------------------------------------------------------------------+
 
   7 // | LIBERAL FREEWARE LICENSE: This source code document may be used
 
   8 // | by anyone for any purpose, and freely redistributed alone or in
 
   9 // | combination with other software, provided that the license is obeyed.
 
  11 // | There are only two ways to violate the license:
 
  13 // | 1. To redistribute this code in source form, with the copyright
 
  14 // |    notice or license removed or altered. (Distributing in compiled
 
  15 // |    forms without embedded copyright notices is permitted).
 
  17 // | 2. To redistribute modified versions of this code in *any* form
 
  18 // |    that bears insufficient indications that the modifications are
 
  19 // |    not the work of the original author(s).
 
  21 // | This license applies to this document only, not any other software
 
  22 // | that it may be combined with.
 
  24 // +----------------------------------------------------------------------+
 
  26 // | https://www.anuko.com/time_tracker/credits.htm
 
  27 // +----------------------------------------------------------------------+
 
  29 import('ttUserHelper');
 
  30 import('DateAndTime');
 
  31 import('ttInvoiceHelper');
 
  33 // Class ttTeamHelper - contains helper functions that operate with groups.
 
  36   // The getUsersForClient obtains all active and inactive users in a group that are relevant to a client.
 
  37   static function getUsersForClient() {
 
  39     $mdb2 = getConnection();
 
  41     $sql = "select u.id, u.name from tt_user_project_binds upb".
 
  42       " inner join tt_client_project_binds cpb on (upb.project_id = cpb.project_id and cpb.client_id = $user->client_id)".
 
  43       " inner join tt_users u on (u.id = upb.user_id)".
 
  44       " where (u.status = 1 or u.status = 0)".
 
  46       " order by upper(u.name)";
 
  47     $res = $mdb2->query($sql);
 
  49     if (is_a($res, 'PEAR_Error'))
 
  51     while ($val = $res->fetchRow()) {
 
  57   // The getActiveUsers obtains all active users in a given group.
 
  58   static function getActiveUsers($options = null) {
 
  61     $mdb2 = getConnection();
 
  63     $group_id = $user->getGroup();
 
  64     $org_id = $user->org_id;
 
  66     if (isset($options['getAllFields']))
 
  67       $sql = "select u.*, r.name as role_name, r.rank from tt_users u left join tt_roles r on (u.role_id = r.id) where u.group_id = $group_id and u.org_id = $org_id and u.status = 1 order by upper(u.name)";
 
  69       $sql = "select id, name from tt_users where group_id = $group_id and org_id = $org_id and status = 1 order by upper(name)";
 
  70     $res = $mdb2->query($sql);
 
  72     if (is_a($res, 'PEAR_Error'))
 
  74     while ($val = $res->fetchRow()) {
 
  75       // Localize top manager role name, as it is not localized in db.
 
  76       if ($val['rank'] == 512)
 
  77         $val['role_name'] = $i18n->get('role.top_manager.label');
 
  81     if (isset($options['putSelfFirst'])) {
 
  82       // Put own entry at the front.
 
  83       $cnt = count($user_list);
 
  84       for($i = 0; $i < $cnt; $i++) {
 
  85         if ($user_list[$i]['id'] == $user->id) {
 
  86           $self = $user_list[$i]; // Found self.
 
  87           array_unshift($user_list, $self); // Put own entry at the front.
 
  88           array_splice($user_list, $i+1, 1); // Remove duplicate.
 
  95   // The swapRolesWith swaps existing user role with that of another user.
 
  96   static function swapRolesWith($user_id) {
 
  98     $mdb2 = getConnection();
 
 100     // Obtain role id for the user we are swapping ourselves with.
 
 101     $sql = "select u.id, u.role_id from tt_users u left join tt_roles r on (u.role_id = r.id) where u.id = $user_id and u.group_id = $user->group_id and u.status = 1 and r.rank < $user->rank";
 
 102     $res = $mdb2->query($sql);
 
 103     if (is_a($res, 'PEAR_Error'))
 
 105     $val = $res->fetchRow();
 
 106     if (!$val['id'] || !$val['role_id'])
 
 109     $modified_part = ', modified = now(), modified_ip = '.$mdb2->quote($_SERVER['REMOTE_ADDR']).', modified_by = '.$user->id;
 
 112     $sql = "update tt_users set role_id = $user->role_id".$modified_part." where id = $user_id and group_id = $user->group_id";
 
 113     $affected = $mdb2->exec($sql);
 
 114     if (is_a($affected, 'PEAR_Error')) return false;
 
 117     $role_id = $val['role_id'];
 
 118     $sql = "update tt_users set role_id = $role_id".$modified_part." where id = $user->id and group_id = $user->group_id";
 
 119     $affected = $mdb2->exec($sql);
 
 120     if (is_a($affected, 'PEAR_Error')) return false;
 
 125   // The getUsersForSwap obtains all users a current user can swap roles with.
 
 126   static function getUsersForSwap() {
 
 128     $mdb2 = getConnection();
 
 130     $sql = "select u.id, u.name, r.rank, r.rights from tt_users u left join tt_roles r on (u.role_id = r.id) where u.group_id = $user->group_id and u.status = 1 and r.rank < $user->rank order by upper(u.name)";
 
 131     $res = $mdb2->query($sql);
 
 132     $user_list = array();
 
 133     if (is_a($res, 'PEAR_Error'))
 
 135     while ($val = $res->fetchRow()) {
 
 136       $isClient = in_array('track_own_time', explode(',', $val['rights'])) ? 0 : 1; // Clients do not have track_own_time right.
 
 138         continue; // Skip adding clients.
 
 145   // The getUsers obtains all active and inactive (but not deleted) users in a group.
 
 146   static function getUsers() {
 
 148     $mdb2 = getConnection();
 
 149     $sql = "select id, name from tt_users where group_id = $user->group_id and (status = 1 or status = 0) order by upper(name)";
 
 150     $res = $mdb2->query($sql);
 
 151     $user_list = array();
 
 152     if (is_a($res, 'PEAR_Error'))
 
 154     while ($val = $res->fetchRow()) {
 
 160   // The getInactiveUsers obtains all inactive users in a group.
 
 161   static function getInactiveUsers($group_id, $all_fields = false) {
 
 162     $mdb2 = getConnection();
 
 165       $sql = "select u.*, r.name as role_name from tt_users u left join tt_roles r on (u.role_id = r.id) where u.group_id = $group_id and u.status = 0 order by upper(u.name)";
 
 167       $sql = "select id, name from tt_users where group_id = $group_id and status = 0 order by upper(name)";
 
 168     $res = $mdb2->query($sql);
 
 170     if (!is_a($res, 'PEAR_Error')) {
 
 171       while ($val = $res->fetchRow()) {
 
 179   // The getAllProjects obtains all projects in a group.
 
 180   static function getAllProjects($group_id, $all_fields = false) {
 
 181     $mdb2 = getConnection();
 
 184       $sql = "select * from tt_projects where group_id = $group_id order by status, upper(name)";
 
 186       $sql = "select id, name from tt_projects where group_id = $group_id order by status, upper(name)";
 
 187     $res = $mdb2->query($sql);
 
 189     if (!is_a($res, 'PEAR_Error')) {
 
 190       while ($val = $res->fetchRow()) {
 
 198   // getActiveTasks - returns an array of active tasks for a group.
 
 199   static function getActiveTasks($group_id)
 
 202     $mdb2 = getConnection();
 
 204     $sql = "select id, name, description from tt_tasks where group_id = $group_id and status = 1 order by upper(name)";
 
 205     $res = $mdb2->query($sql);
 
 207     if (!is_a($res, 'PEAR_Error')) {
 
 208       while ($val = $res->fetchRow()) {
 
 215   // getInactiveTasks - returns an array of inactive tasks for a group.
 
 216   static function getInactiveTasks($group_id)
 
 219     $mdb2 = getConnection();
 
 221     $sql = "select id, name, description from tt_tasks
 
 222       where group_id = $group_id and status = 0 order by upper(name)";
 
 223     $res = $mdb2->query($sql);
 
 225     if (!is_a($res, 'PEAR_Error')) {
 
 226       while ($val = $res->fetchRow()) {
 
 233   // The getAllTasks obtains all tasks in a group.
 
 234   static function getAllTasks($group_id, $all_fields = false) {
 
 235     $mdb2 = getConnection();
 
 238       $sql = "select * from tt_tasks where group_id = $group_id order by status, upper(name)";
 
 240       $sql = "select id, name from tt_tasks where group_id = $group_id order by status, upper(name)";
 
 241     $res = $mdb2->query($sql);
 
 243     if (!is_a($res, 'PEAR_Error')) {
 
 244       while ($val = $res->fetchRow()) {
 
 252   // getActiveRolesForUser - returns an array of relevant active roles for user with rank less than self.
 
 253   // "Relevant" means that client roles are filtered out if Client plugin is disabled.
 
 254   static function getActiveRolesForUser()
 
 258     $mdb2 = getConnection();
 
 260     $group_id = $user->getGroup();
 
 261     $org_id = $user->org_id;
 
 263     // Determine max rank. If we are working in on behalf group
 
 264     // then rank restriction does not apply.
 
 265     $max_rank = $user->behalfGroup ? MAX_RANK : $user->rank;
 
 267     $sql = "select id, name, description, rank, rights from tt_roles where group_id = $group_id and org_id = $org_id and rank < $max_rank and status = 1 order by rank";
 
 268     $res = $mdb2->query($sql);
 
 270     if (!is_a($res, 'PEAR_Error')) {
 
 271       while ($val = $res->fetchRow()) {
 
 272         $val['is_client'] = in_array('track_own_time', explode(',', $val['rights'])) ? 0 : 1; // Clients do not have data entry right.
 
 273         if ($val['is_client'] && !$user->isPluginEnabled('cl'))
 
 274           continue; // Skip adding a client role.
 
 281   // getActiveRoles - returns an array of active roles for a group.
 
 282   static function getActiveRoles($group_id)
 
 285     $mdb2 = getConnection();
 
 287     $sql = "select id, name, description, rank, rights from tt_roles where group_id = $group_id and status = 1 order by rank";
 
 288     $res = $mdb2->query($sql);
 
 290     if (!is_a($res, 'PEAR_Error')) {
 
 291       while ($val = $res->fetchRow()) {
 
 292         $val['is_client'] = in_array('track_own_time', explode(',', $val['rights'])) ? 0 : 1; // Clients do not have track_own_time right.
 
 299   // getInactiveRoles - returns an array of inactive roles for a group.
 
 300   static function getInactiveRoles($group_id)
 
 303     $mdb2 = getConnection();
 
 305     $sql = "select id, name, rank, description from tt_roles
 
 306       where group_id = $group_id and status = 0 order by rank";
 
 307     $res = $mdb2->query($sql);
 
 309     if (!is_a($res, 'PEAR_Error')) {
 
 310       while ($val = $res->fetchRow()) {
 
 317   // getInactiveRolesForUser - returns an array of relevant active roles for user with rank less than self.
 
 318   // "Relevant" means that client roles are filtered out if Client plugin is disabled.
 
 319   static function getInactiveRolesForUser()
 
 323     $mdb2 = getConnection();
 
 325     $group_id = $user->getGroup();
 
 326     $org_id = $user->org_id;
 
 328     // Determine max rank. If we are working in on behalf group
 
 329     // then rank restriction does not apply.
 
 330     $max_rank = $user->behalfGroup ? MAX_RANK : $user->rank;
 
 332     $sql = "select id, name, description, rank, rights from tt_roles where group_id = $group_id and org_id = $org_id and rank < $max_rank and status = 0 order by rank";
 
 333     $res = $mdb2->query($sql);
 
 335     if (!is_a($res, 'PEAR_Error')) {
 
 336       while ($val = $res->fetchRow()) {
 
 337         $val['is_client'] = in_array('track_own_time', explode(',', $val['rights'])) ? 0 : 1; // Clients do not have data entry right.
 
 338         if ($val['is_client'] && !$user->isPluginEnabled('cl'))
 
 339           continue; // Skip adding a client role.
 
 346   // The getAllClients obtains all clients in a group.
 
 347   static function getAllClients($group_id, $all_fields = false) {
 
 348     $mdb2 = getConnection();
 
 351       $sql = "select * from tt_clients where group_id = $group_id order by status, upper(name)";
 
 353       $sql = "select id, name from tt_clients where group_id = $group_id order by status, upper(name)";
 
 355     $res = $mdb2->query($sql);
 
 357     if (!is_a($res, 'PEAR_Error')) {
 
 358       while ($val = $res->fetchRow()) {
 
 366   // The getAllInvoices returns an array of all invoices for a group.
 
 367   static function getAllInvoices()
 
 372     $mdb2 = getConnection();
 
 374     $sql = "select * from tt_invoices where group_id = $user->group_id";
 
 375     $res = $mdb2->query($sql);
 
 377     if (!is_a($res, 'PEAR_Error')) {
 
 378       $dt = new DateAndTime(DB_DATEFORMAT);
 
 379       while ($val = $res->fetchRow()) {
 
 386   // The getRecentInvoices returns an array of recent invoices (max 3) for a client.
 
 387   static function getRecentInvoices($group_id, $client_id)
 
 392     $mdb2 = getConnection();
 
 394     $sql = "select i.id, i.name from tt_invoices i
 
 395       left join tt_clients c on (c.id = i.client_id)
 
 396       where i.group_id = $group_id and i.status = 1 and c.id = $client_id
 
 397       order by i.id desc limit 3";
 
 398     $res = $mdb2->query($sql);
 
 400     if (!is_a($res, 'PEAR_Error')) {
 
 401       $dt = new DateAndTime(DB_DATEFORMAT);
 
 402       while ($val = $res->fetchRow()) {
 
 409   // getUserToProjectBinds - obtains all user to project binds for a group.
 
 410   static function getUserToProjectBinds($group_id) {
 
 411     $mdb2 = getConnection();
 
 414     $sql = "select * from tt_user_project_binds where user_id in (select id from tt_users where group_id = $group_id) order by user_id, status, project_id";
 
 415     $res = $mdb2->query($sql);
 
 417     if (!is_a($res, 'PEAR_Error')) {
 
 418       while ($val = $res->fetchRow()) {
 
 426   // The getAllCustomFields obtains all custom fields in a group.
 
 427   static function getAllCustomFields($group_id) {
 
 428     $mdb2 = getConnection();
 
 430     $sql = "select * from tt_custom_fields where group_id = $group_id order by status";
 
 432     $res = $mdb2->query($sql);
 
 434     if (!is_a($res, 'PEAR_Error')) {
 
 435       while ($val = $res->fetchRow()) {
 
 443   // The getAllCustomFieldOptions obtains all custom field options in a group.
 
 444   static function getAllCustomFieldOptions($group_id) {
 
 445     $mdb2 = getConnection();
 
 447     $sql = "select * from tt_custom_field_options where field_id in (select id from tt_custom_fields where group_id = $group_id) order by id";
 
 449     $res = $mdb2->query($sql);
 
 451     if (!is_a($res, 'PEAR_Error')) {
 
 452       while ($val = $res->fetchRow()) {
 
 460   // The getCustomFieldLog obtains all custom field log entries for a group.
 
 461   static function getCustomFieldLog($group_id) {
 
 462     $mdb2 = getConnection();
 
 464     $sql = "select * from tt_custom_field_log where field_id in (select id from tt_custom_fields where group_id = $group_id) order by id";
 
 466     $res = $mdb2->query($sql);
 
 468     if (!is_a($res, 'PEAR_Error')) {
 
 469       while ($val = $res->fetchRow()) {
 
 477   // getFavReports - obtains all favorite reports for all users in a group.
 
 478   static function getFavReports($group_id) {
 
 479     $mdb2 = getConnection();
 
 482     $sql = "select * from tt_fav_reports where user_id in (select id from tt_users where group_id = $group_id)";
 
 483     $res = $mdb2->query($sql);
 
 485     if (!is_a($res, 'PEAR_Error')) {
 
 486       while ($val = $res->fetchRow()) {
 
 494   // getExpenseItems - obtains all expense items for all users in a group.
 
 495   static function getExpenseItems($group_id) {
 
 496     $mdb2 = getConnection();
 
 499     $sql = "select * from tt_expense_items where user_id in (select id from tt_users where group_id = $group_id)";
 
 500     $res = $mdb2->query($sql);
 
 502     if (!is_a($res, 'PEAR_Error')) {
 
 503       while ($val = $res->fetchRow()) {
 
 511   // getMonthlyQuotas - obtains monthly quotas for a group.
 
 512   static function getMonthlyQuotas($group_id) {
 
 513     $mdb2 = getConnection();
 
 516     $sql = "select year, month, minutes from tt_monthly_quotas where group_id = $group_id";
 
 517     $res = $mdb2->query($sql);
 
 519     if (!is_a($res, 'PEAR_Error')) {
 
 520       while ($val = $res->fetchRow()) {
 
 528   // The delete function permanently deletes all data for a group.
 
 529   static function delete($group_id) {
 
 530     $mdb2 = getConnection();
 
 533     $sql = "select id from tt_users where group_id = $group_id";
 
 534     $res = $mdb2->query($sql);
 
 535     if (is_a($res, 'PEAR_Error')) return false;
 
 536     while ($val = $res->fetchRow()) {
 
 537       $user_id = $val['id'];
 
 538       if (!ttUserHelper::delete($user_id)) return false;
 
 542     if (!ttTeamHelper::deleteTasks($group_id)) return false;
 
 544     // Delete client to project binds.
 
 545     $sql = "delete from tt_client_project_binds where client_id in (select id from tt_clients where group_id = $group_id)";
 
 546     $affected = $mdb2->exec($sql);
 
 547     if (is_a($affected, 'PEAR_Error')) return false;
 
 550     $sql = "delete from tt_projects where group_id = $group_id";
 
 551     $affected = $mdb2->exec($sql);
 
 552     if (is_a($affected, 'PEAR_Error')) return false;
 
 555     $sql = "delete from tt_clients where group_id = $group_id";
 
 556     $affected = $mdb2->exec($sql);
 
 557     if (is_a($affected, 'PEAR_Error')) return false;
 
 560     $sql = "delete from tt_invoices where group_id = $group_id";
 
 561     $affected = $mdb2->exec($sql);
 
 562     if (is_a($affected, 'PEAR_Error')) return false;
 
 564     // Delete custom fields.
 
 565     if (!ttTeamHelper::deleteCustomFields($group_id)) return false;
 
 568     $sql = "delete from tt_roles where group_id = $group_id";
 
 569     $affected = $mdb2->exec($sql);
 
 570     if (is_a($affected, 'PEAR_Error')) return false;
 
 572     // Delete cron entries.
 
 573     $sql = "delete from tt_cron where group_id = $group_id";
 
 574     $affected = $mdb2->exec($sql);
 
 575     if (is_a($affected, 'PEAR_Error')) return false;
 
 577     // Delete predefined expenses.
 
 578     $sql = "delete from tt_predefined_expenses where group_id = $group_id";
 
 579     $affected = $mdb2->exec($sql);
 
 580     if (is_a($affected, 'PEAR_Error')) return false;
 
 582     // Delete monthly quotas.
 
 583     $sql = "delete from tt_monthly_quotas where group_id = $group_id";
 
 584     $affected = $mdb2->exec($sql);
 
 585     if (is_a($affected, 'PEAR_Error')) return false;
 
 588     $sql = "delete from tt_groups where id = $group_id";
 
 589     $affected = $mdb2->exec($sql);
 
 590     if (is_a($affected, 'PEAR_Error')) return false;
 
 595   // The deleteTasks deletes all tasks and task binds for an inactive group.
 
 596   static function deleteTasks($group_id) {
 
 597     $mdb2 = getConnection();
 
 598     $sql = "select id from tt_tasks where group_id = $group_id";
 
 599     $res = $mdb2->query($sql);
 
 600     if (is_a($res, 'PEAR_Error')) return false;
 
 602     while ($val = $res->fetchRow()) {
 
 604       // Delete task binds.
 
 605       $task_id = $val['id'];
 
 606       $sql = "delete from tt_project_task_binds where task_id = $task_id";
 
 607       $affected = $mdb2->exec($sql);
 
 608       if (is_a($affected, 'PEAR_Error')) return false;
 
 611       $sql = "delete from tt_tasks where id = $task_id";
 
 612       $affected = $mdb2->exec($sql);
 
 613       if (is_a($affected, 'PEAR_Error')) return false;
 
 619   // The deleteCustomFields cleans up tt_custom_field_log, tt_custom_field_options and tt_custom_fields tables for an inactive group.
 
 620   static function deleteCustomFields($group_id) {
 
 621     $mdb2 = getConnection();
 
 622     $sql = "select id from tt_custom_fields where group_id = $group_id";
 
 623     $res = $mdb2->query($sql);
 
 624     if (is_a($res, 'PEAR_Error')) return false;
 
 626     while ($val = $res->fetchRow()) {
 
 627       $field_id = $val['id'];
 
 629       // Clean up tt_custom_field_log.
 
 630       $sql = "delete from tt_custom_field_log where field_id = $field_id";
 
 631       $affected = $mdb2->exec($sql);
 
 632       if (is_a($affected, 'PEAR_Error')) return false;
 
 634       // Clean up tt_custom_field_options.
 
 635       $sql = "delete from tt_custom_field_options where field_id = $field_id";
 
 636       $affected = $mdb2->exec($sql);
 
 637       if (is_a($affected, 'PEAR_Error')) return false;
 
 639       // Delete custom field.
 
 640       $sql = "delete from tt_custom_fields where id = $field_id";
 
 641       $affected = $mdb2->exec($sql);
 
 642       if (is_a($affected, 'PEAR_Error')) return false;