5a3dd2fb6782ca18553f965ead31f6a8f769b12b
[timetracker.git] / WEB-INF / lib / ttTeamHelper.class.php
1 <?php
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.
10 // |
11 // | There are only two ways to violate the license:
12 // |
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).
16 // |
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).
20 // |
21 // | This license applies to this document only, not any other software
22 // | that it may be combined with.
23 // |
24 // +----------------------------------------------------------------------+
25 // | Contributors:
26 // | https://www.anuko.com/time_tracker/credits.htm
27 // +----------------------------------------------------------------------+
28
29 import('ttUserHelper');
30 import('DateAndTime');
31 import('ttInvoiceHelper');
32
33 // Class ttTeamHelper - contains helper functions that operate with groups.
34 class ttTeamHelper {
35
36   // The getUsersForClient obtains all active and inactive users in a group that are relevant to a client.
37   static function getUsersForClient() {
38     global $user;
39     $mdb2 = getConnection();
40
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)".
45       " group by u.id".
46       " order by upper(u.name)";
47     $res = $mdb2->query($sql);
48     $user_list = array();
49     if (is_a($res, 'PEAR_Error'))
50       return false;
51     while ($val = $res->fetchRow()) {
52       $user_list[] = $val;
53     }
54     return $user_list;
55   }
56
57   // The getActiveUsers obtains all active users in a given group.
58   static function getActiveUsers($options = null) {
59     global $user;
60     global $i18n;
61     $mdb2 = getConnection();
62
63     $group_id = $user->getGroup();
64     $org_id = $user->org_id;
65
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)";
68     else
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);
71     $user_list = array();
72     if (is_a($res, 'PEAR_Error'))
73       return false;
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');
78       $user_list[] = $val;
79     }
80
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.
89         }
90       }
91     }
92     return $user_list;
93   }
94
95   // The swapRolesWith swaps existing user role with that of another user.
96   static function swapRolesWith($user_id) {
97     global $user;
98     $mdb2 = getConnection();
99
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'))
104       return false;
105     $val = $res->fetchRow();
106     if (!$val['id'] || !$val['role_id'])
107       return false;
108
109     $modified_part = ', modified = now(), modified_ip = '.$mdb2->quote($_SERVER['REMOTE_ADDR']).', modified_by = '.$mdb2->quote($user->id);
110
111     // Promote user.
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;
115
116     // Demote self.
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;
121
122     return true;
123   }
124
125   // The getUsersForSwap obtains all users a current user can swap roles with.
126   static function getUsersForSwap() {
127     global $user;
128     $mdb2 = getConnection();
129
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'))
134       return false;
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.
137       if ($isClient)
138         continue; // Skip adding clients.
139       $user_list[] = $val;
140     }
141
142     return $user_list;
143   }
144
145   // The getUsers obtains all active and inactive (but not deleted) users in a group.
146   static function getUsers() {
147     global $user;
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'))
153       return false;
154     while ($val = $res->fetchRow()) {
155       $user_list[] = $val;
156     }
157     return $user_list;
158   }
159
160   // The getInactiveUsers obtains all inactive users in a group.
161   static function getInactiveUsers($group_id, $all_fields = false) {
162     $mdb2 = getConnection();
163
164     if ($all_fields)
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)";
166     else
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);
169     $result = array();
170     if (!is_a($res, 'PEAR_Error')) {
171       while ($val = $res->fetchRow()) {
172         $result[] = $val;
173       }
174       return $result;
175     }
176     return false;
177   }
178
179   // getActiveProjects - returns an array of active projects for a group.
180   static function getActiveProjects($group_id)
181   {
182     $result = array();
183     $mdb2 = getConnection();
184
185     $sql = "select id, name, description, tasks from tt_projects
186       where group_id = $group_id and status = 1 order by upper(name)";
187     $res = $mdb2->query($sql);
188     $result = array();
189     if (!is_a($res, 'PEAR_Error')) {
190       while ($val = $res->fetchRow()) {
191         $result[] = $val;
192       }
193     }
194     return $result;
195   }
196
197   // getInactiveProjects - returns an array of inactive projects for a group.
198   static function getInactiveProjects($group_id)
199   {
200     $result = array();
201     $mdb2 = getConnection();
202
203     $sql = "select id, name, description, tasks from tt_projects
204       where group_id = $group_id and status = 0 order by upper(name)";
205     $res = $mdb2->query($sql);
206     $result = array();
207     if (!is_a($res, 'PEAR_Error')) {
208       while ($val = $res->fetchRow()) {
209         $result[] = $val;
210       }
211     }
212     return $result;
213   }
214
215   // The getAllProjects obtains all projects in a group.
216   static function getAllProjects($group_id, $all_fields = false) {
217     $mdb2 = getConnection();
218
219     if ($all_fields)
220       $sql = "select * from tt_projects where group_id = $group_id order by status, upper(name)";
221     else
222       $sql = "select id, name from tt_projects where group_id = $group_id order by status, upper(name)";
223     $res = $mdb2->query($sql);
224     $result = array();
225     if (!is_a($res, 'PEAR_Error')) {
226       while ($val = $res->fetchRow()) {
227         $result[] = $val;
228       }
229       return $result;
230     }
231     return false;
232   }
233
234   // getActiveTasks - returns an array of active tasks for a group.
235   static function getActiveTasks($group_id)
236   {
237     $result = array();
238     $mdb2 = getConnection();
239
240     $sql = "select id, name, description from tt_tasks where group_id = $group_id and status = 1 order by upper(name)";
241     $res = $mdb2->query($sql);
242     $result = array();
243     if (!is_a($res, 'PEAR_Error')) {
244       while ($val = $res->fetchRow()) {
245         $result[] = $val;
246       }
247     }
248     return $result;
249   }
250
251   // getInactiveTasks - returns an array of inactive tasks for a group.
252   static function getInactiveTasks($group_id)
253   {
254     $result = array();
255     $mdb2 = getConnection();
256
257     $sql = "select id, name, description from tt_tasks
258       where group_id = $group_id and status = 0 order by upper(name)";
259     $res = $mdb2->query($sql);
260     $result = array();
261     if (!is_a($res, 'PEAR_Error')) {
262       while ($val = $res->fetchRow()) {
263         $result[] = $val;
264       }
265     }
266     return $result;
267   }
268
269   // The getAllTasks obtains all tasks in a group.
270   static function getAllTasks($group_id, $all_fields = false) {
271     $mdb2 = getConnection();
272
273     if ($all_fields)
274       $sql = "select * from tt_tasks where group_id = $group_id order by status, upper(name)";
275     else
276       $sql = "select id, name from tt_tasks where group_id = $group_id order by status, upper(name)";
277     $res = $mdb2->query($sql);
278     $result = array();
279     if (!is_a($res, 'PEAR_Error')) {
280       while ($val = $res->fetchRow()) {
281         $result[] = $val;
282       }
283       return $result;
284     }
285     return false;
286   }
287
288   // getActiveRolesForUser - returns an array of relevant active roles for user with rank less than self.
289   // "Relevant" means that client roles are filtered out if Client plugin is disabled.
290   static function getActiveRolesForUser()
291   {
292     global $user;
293     $result = array();
294     $mdb2 = getConnection();
295
296     $group_id = $user->getGroup();
297     $org_id = $user->org_id;
298
299     // Determine max rank. If we are working in on behalf group
300     // then rank restriction does not apply.
301     $max_rank = $user->behalfGroup ? MAX_RANK : $user->rank;
302
303     $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";
304     $res = $mdb2->query($sql);
305     $result = array();
306     if (!is_a($res, 'PEAR_Error')) {
307       while ($val = $res->fetchRow()) {
308         $val['is_client'] = in_array('track_own_time', explode(',', $val['rights'])) ? 0 : 1; // Clients do not have data entry right.
309         if ($val['is_client'] && !$user->isPluginEnabled('cl'))
310           continue; // Skip adding a client role.
311         $result[] = $val;
312       }
313     }
314     return $result;
315   }
316
317   // getActiveRoles - returns an array of active roles for a group.
318   static function getActiveRoles($group_id)
319   {
320     $result = array();
321     $mdb2 = getConnection();
322
323     $sql = "select id, name, description, rank, rights from tt_roles where group_id = $group_id and status = 1 order by rank";
324     $res = $mdb2->query($sql);
325     $result = array();
326     if (!is_a($res, 'PEAR_Error')) {
327       while ($val = $res->fetchRow()) {
328         $val['is_client'] = in_array('track_own_time', explode(',', $val['rights'])) ? 0 : 1; // Clients do not have track_own_time right.
329         $result[] = $val;
330       }
331     }
332     return $result;
333   }
334
335   // getInactiveRoles - returns an array of inactive roles for a group.
336   static function getInactiveRoles($group_id)
337   {
338     $result = array();
339     $mdb2 = getConnection();
340
341     $sql = "select id, name, rank, description from tt_roles
342       where group_id = $group_id and status = 0 order by rank";
343     $res = $mdb2->query($sql);
344     $result = array();
345     if (!is_a($res, 'PEAR_Error')) {
346       while ($val = $res->fetchRow()) {
347         $result[] = $val;
348       }
349     }
350     return $result;
351   }
352
353   // getInactiveRolesForUser - returns an array of relevant active roles for user with rank less than self.
354   // "Relevant" means that client roles are filtered out if Client plugin is disabled.
355   static function getInactiveRolesForUser()
356   {
357     global $user;
358     $result = array();
359     $mdb2 = getConnection();
360
361     $group_id = $user->getGroup();
362     $org_id = $user->org_id;
363
364     // Determine max rank. If we are working in on behalf group
365     // then rank restriction does not apply.
366     $max_rank = $user->behalfGroup ? MAX_RANK : $user->rank;
367
368     $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";
369     $res = $mdb2->query($sql);
370     $result = array();
371     if (!is_a($res, 'PEAR_Error')) {
372       while ($val = $res->fetchRow()) {
373         $val['is_client'] = in_array('track_own_time', explode(',', $val['rights'])) ? 0 : 1; // Clients do not have data entry right.
374         if ($val['is_client'] && !$user->isPluginEnabled('cl'))
375           continue; // Skip adding a client role.
376         $result[] = $val;
377       }
378     }
379     return $result;
380   }
381
382   // The getActiveClients returns an array of active clients for a group.
383   static function getActiveClients($group_id, $all_fields = false)
384   {
385     $result = array();
386     $mdb2 = getConnection();
387
388     if ($all_fields)
389       $sql = "select * from tt_clients where group_id = $group_id and status = 1 order by upper(name)";
390     else
391       $sql = "select id, name from tt_clients where group_id = $group_id and status = 1 order by upper(name)";
392
393     $res = $mdb2->query($sql);
394     $result = array();
395     if (!is_a($res, 'PEAR_Error')) {
396       while ($val = $res->fetchRow()) {
397         $result[] = $val;
398       }
399     }
400     return $result;
401   }
402
403   // The getInactiveClients returns an array of inactive clients for a group.
404   static function getInactiveClients($group_id, $all_fields = false)
405   {
406     $result = array();
407     $mdb2 = getConnection();
408
409     if ($all_fields)
410       $sql = "select * from tt_clients where group_id = $group_id and status = 0 order by upper(name)";
411     else
412       $sql = "select id, name from tt_clients where group_id = $group_id and status = 0 order by upper(name)";
413
414     $res = $mdb2->query($sql);
415     $result = array();
416     if (!is_a($res, 'PEAR_Error')) {
417       while ($val = $res->fetchRow()) {
418         $result[] = $val;
419       }
420     }
421     return $result;
422   }
423
424   // The getAllClients obtains all clients in a group.
425   static function getAllClients($group_id, $all_fields = false) {
426     $mdb2 = getConnection();
427
428     if ($all_fields)
429       $sql = "select * from tt_clients where group_id = $group_id order by status, upper(name)";
430     else
431       $sql = "select id, name from tt_clients where group_id = $group_id order by status, upper(name)";
432
433     $res = $mdb2->query($sql);
434     $result = array();
435     if (!is_a($res, 'PEAR_Error')) {
436       while ($val = $res->fetchRow()) {
437         $result[] = $val;
438       }
439       return $result;
440     }
441     return false;
442   }
443
444   // The getActiveInvoices returns an array of active invoices for a group.
445   static function getActiveInvoices($localizeDates = true)
446   {
447     global $user;
448     $addPaidStatus = $user->isPluginEnabled('ps');
449
450     $result = array();
451     $mdb2 = getConnection();
452
453     if ($user->isClient())
454       $client_part = " and i.client_id = $user->client_id";
455
456     $sql = "select i.id, i.name, i.date, i.client_id, i.status, c.name as client_name from tt_invoices i
457       left join tt_clients c on (c.id = i.client_id)
458       where i.status = 1 and i.group_id = $user->group_id $client_part order by i.name";
459     $res = $mdb2->query($sql);
460     $result = array();
461     if (!is_a($res, 'PEAR_Error')) {
462       $dt = new DateAndTime(DB_DATEFORMAT);
463       while ($val = $res->fetchRow()) {
464         if ($localizeDates) {
465           $dt->parseVal($val['date']);
466           $val['date'] = $dt->toString($user->date_format);
467         }
468         if ($addPaidStatus)
469           $val['paid'] = ttInvoiceHelper::isPaid($val['id']);
470         $result[] = $val;
471       }
472     }
473     return $result;
474   }
475
476   // The getAllInvoices returns an array of all invoices for a group.
477   static function getAllInvoices()
478   {
479     global $user;
480
481     $result = array();
482     $mdb2 = getConnection();
483
484     $sql = "select * from tt_invoices where group_id = $user->group_id";
485     $res = $mdb2->query($sql);
486     $result = array();
487     if (!is_a($res, 'PEAR_Error')) {
488       $dt = new DateAndTime(DB_DATEFORMAT);
489       while ($val = $res->fetchRow()) {
490         $result[] = $val;
491       }
492     }
493     return $result;
494   }
495
496   // The getRecentInvoices returns an array of recent invoices (max 3) for a client.
497   static function getRecentInvoices($group_id, $client_id)
498   {
499     global $user;
500
501     $result = array();
502     $mdb2 = getConnection();
503
504     $sql = "select i.id, i.name from tt_invoices i
505       left join tt_clients c on (c.id = i.client_id)
506       where i.group_id = $group_id and i.status = 1 and c.id = $client_id
507       order by i.id desc limit 3";
508     $res = $mdb2->query($sql);
509     $result = array();
510     if (!is_a($res, 'PEAR_Error')) {
511       $dt = new DateAndTime(DB_DATEFORMAT);
512       while ($val = $res->fetchRow()) {
513         $result[] = $val;
514       }
515     }
516     return $result;
517   }
518
519   // getUserToProjectBinds - obtains all user to project binds for a group.
520   static function getUserToProjectBinds($group_id) {
521     $mdb2 = getConnection();
522
523     $result = array();
524     $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";
525     $res = $mdb2->query($sql);
526     $result = array();
527     if (!is_a($res, 'PEAR_Error')) {
528       while ($val = $res->fetchRow()) {
529         $result[] = $val;
530       }
531       return $result;
532     }
533     return false;
534   }
535
536   // The getAllCustomFields obtains all custom fields in a group.
537   static function getAllCustomFields($group_id) {
538     $mdb2 = getConnection();
539
540     $sql = "select * from tt_custom_fields where group_id = $group_id order by status";
541
542     $res = $mdb2->query($sql);
543     $result = array();
544     if (!is_a($res, 'PEAR_Error')) {
545       while ($val = $res->fetchRow()) {
546         $result[] = $val;
547       }
548       return $result;
549     }
550     return false;
551   }
552
553   // The getAllCustomFieldOptions obtains all custom field options in a group.
554   static function getAllCustomFieldOptions($group_id) {
555     $mdb2 = getConnection();
556
557     $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";
558
559     $res = $mdb2->query($sql);
560     $result = array();
561     if (!is_a($res, 'PEAR_Error')) {
562       while ($val = $res->fetchRow()) {
563         $result[] = $val;
564       }
565       return $result;
566     }
567     return false;
568   }
569
570   // The getCustomFieldLog obtains all custom field log entries for a group.
571   static function getCustomFieldLog($group_id) {
572     $mdb2 = getConnection();
573
574     $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";
575
576     $res = $mdb2->query($sql);
577     $result = array();
578     if (!is_a($res, 'PEAR_Error')) {
579       while ($val = $res->fetchRow()) {
580         $result[] = $val;
581       }
582       return $result;
583     }
584     return false;
585   }
586
587   // getFavReports - obtains all favorite reports for all users in a group.
588   static function getFavReports($group_id) {
589     $mdb2 = getConnection();
590
591     $result = array();
592     $sql = "select * from tt_fav_reports where user_id in (select id from tt_users where group_id = $group_id)";
593     $res = $mdb2->query($sql);
594     $result = array();
595     if (!is_a($res, 'PEAR_Error')) {
596       while ($val = $res->fetchRow()) {
597         $result[] = $val;
598       }
599       return $result;
600     }
601     return false;
602   }
603
604   // getExpenseItems - obtains all expense items for all users in a group.
605   static function getExpenseItems($group_id) {
606     $mdb2 = getConnection();
607
608     $result = array();
609     $sql = "select * from tt_expense_items where user_id in (select id from tt_users where group_id = $group_id)";
610     $res = $mdb2->query($sql);
611     $result = array();
612     if (!is_a($res, 'PEAR_Error')) {
613       while ($val = $res->fetchRow()) {
614         $result[] = $val;
615       }
616       return $result;
617     }
618     return false;
619   }
620
621   // getPredefinedExpenses - obtains predefined expenses for a group.
622   static function getPredefinedExpenses($group_id) {
623     global $user;
624     $replaceDecimalMark = ('.' != $user->decimal_mark);
625
626     $mdb2 = getConnection();
627
628     $result = array();
629     $sql = "select id, name, cost from tt_predefined_expenses where group_id = $group_id";
630     $res = $mdb2->query($sql);
631     $result = array();
632     if (!is_a($res, 'PEAR_Error')) {
633       while ($val = $res->fetchRow()) {
634         if ($replaceDecimalMark)
635           $val['cost'] = str_replace('.', $user->decimal_mark, $val['cost']);
636         $result[] = $val;
637       }
638       return $result;
639     }
640     return false;
641   }
642
643   // getNotifications - obtains notification descriptions for a group.
644   static function getNotifications($group_id) {
645     $mdb2 = getConnection();
646
647     $result = array();
648     $sql = "select c.id, c.cron_spec, c.email, c.report_condition, fr.name from tt_cron c
649       left join tt_fav_reports fr on (fr.id = c.report_id)
650       where c.group_id = $group_id and c.status = 1 and fr.status = 1";
651     $res = $mdb2->query($sql);
652     $result = array();
653     if (!is_a($res, 'PEAR_Error')) {
654       while ($val = $res->fetchRow()) {
655         $result[] = $val;
656       }
657       return $result;
658     }
659     return false;
660   }
661
662   // getMonthlyQuotas - obtains monthly quotas for a group.
663   static function getMonthlyQuotas($group_id) {
664     $mdb2 = getConnection();
665
666     $result = array();
667     $sql = "select year, month, minutes from tt_monthly_quotas where group_id = $group_id";
668     $res = $mdb2->query($sql);
669     $result = array();
670     if (!is_a($res, 'PEAR_Error')) {
671       while ($val = $res->fetchRow()) {
672         $result[] = $val;
673       }
674       return $result;
675     }
676     return false;
677   }
678
679   // The delete function permanently deletes all data for a group.
680   static function delete($group_id) {
681     $mdb2 = getConnection();
682
683     // Delete users.
684     $sql = "select id from tt_users where group_id = $group_id";
685     $res = $mdb2->query($sql);
686     if (is_a($res, 'PEAR_Error')) return false;
687     while ($val = $res->fetchRow()) {
688       $user_id = $val['id'];
689       if (!ttUserHelper::delete($user_id)) return false;
690     }
691
692     // Delete tasks.
693     if (!ttTeamHelper::deleteTasks($group_id)) return false;
694
695     // Delete client to project binds.
696     $sql = "delete from tt_client_project_binds where client_id in (select id from tt_clients where group_id = $group_id)";
697     $affected = $mdb2->exec($sql);
698     if (is_a($affected, 'PEAR_Error')) return false;
699
700     // Delete projects.
701     $sql = "delete from tt_projects where group_id = $group_id";
702     $affected = $mdb2->exec($sql);
703     if (is_a($affected, 'PEAR_Error')) return false;
704
705     // Delete clients.
706     $sql = "delete from tt_clients where group_id = $group_id";
707     $affected = $mdb2->exec($sql);
708     if (is_a($affected, 'PEAR_Error')) return false;
709
710     // Delete invoices.
711     $sql = "delete from tt_invoices where group_id = $group_id";
712     $affected = $mdb2->exec($sql);
713     if (is_a($affected, 'PEAR_Error')) return false;
714
715     // Delete custom fields.
716     if (!ttTeamHelper::deleteCustomFields($group_id)) return false;
717
718     // Delete roles.
719     $sql = "delete from tt_roles where group_id = $group_id";
720     $affected = $mdb2->exec($sql);
721     if (is_a($affected, 'PEAR_Error')) return false;
722
723     // Delete cron entries.
724     $sql = "delete from tt_cron where group_id = $group_id";
725     $affected = $mdb2->exec($sql);
726     if (is_a($affected, 'PEAR_Error')) return false;
727
728     // Delete predefined expenses.
729     $sql = "delete from tt_predefined_expenses where group_id = $group_id";
730     $affected = $mdb2->exec($sql);
731     if (is_a($affected, 'PEAR_Error')) return false;
732
733     // Delete monthly quotas.
734     $sql = "delete from tt_monthly_quotas where group_id = $group_id";
735     $affected = $mdb2->exec($sql);
736     if (is_a($affected, 'PEAR_Error')) return false;
737
738     // Delete group.
739     $sql = "delete from tt_groups where id = $group_id";
740     $affected = $mdb2->exec($sql);
741     if (is_a($affected, 'PEAR_Error')) return false;
742
743     return true;
744   }
745
746   // The deleteTasks deletes all tasks and task binds for an inactive group.
747   static function deleteTasks($group_id) {
748     $mdb2 = getConnection();
749     $sql = "select id from tt_tasks where group_id = $group_id";
750     $res = $mdb2->query($sql);
751     if (is_a($res, 'PEAR_Error')) return false;
752
753     while ($val = $res->fetchRow()) {
754
755       // Delete task binds.
756       $task_id = $val['id'];
757       $sql = "delete from tt_project_task_binds where task_id = $task_id";
758       $affected = $mdb2->exec($sql);
759       if (is_a($affected, 'PEAR_Error')) return false;
760
761       // Delete task.
762       $sql = "delete from tt_tasks where id = $task_id";
763       $affected = $mdb2->exec($sql);
764       if (is_a($affected, 'PEAR_Error')) return false;
765     }
766
767     return true;
768   }
769
770   // The deleteCustomFields cleans up tt_custom_field_log, tt_custom_field_options and tt_custom_fields tables for an inactive group.
771   static function deleteCustomFields($group_id) {
772     $mdb2 = getConnection();
773     $sql = "select id from tt_custom_fields where group_id = $group_id";
774     $res = $mdb2->query($sql);
775     if (is_a($res, 'PEAR_Error')) return false;
776
777     while ($val = $res->fetchRow()) {
778       $field_id = $val['id'];
779
780       // Clean up tt_custom_field_log.
781       $sql = "delete from tt_custom_field_log where field_id = $field_id";
782       $affected = $mdb2->exec($sql);
783       if (is_a($affected, 'PEAR_Error')) return false;
784
785       // Clean up tt_custom_field_options.
786       $sql = "delete from tt_custom_field_options where field_id = $field_id";
787       $affected = $mdb2->exec($sql);
788       if (is_a($affected, 'PEAR_Error')) return false;
789
790       // Delete custom field.
791       $sql = "delete from tt_custom_fields where id = $field_id";
792       $affected = $mdb2->exec($sql);
793       if (is_a($affected, 'PEAR_Error')) return false;
794     }
795
796     return true;
797   }
798 }