Merge branch 'master' of https://github.com/anuko/timetracker
[timetracker.git] / WEB-INF / lib / ttClientHelper.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 // Class ttClientHelper is used to help with client related tasks.
30 class ttClientHelper {
31
32   // The getClient looks up a client by id.
33   static function getClient($client_id, $all_fields = false) {
34     global $user;
35     $mdb2 = getConnection();
36
37     $group_id = $user->getGroup();
38     $org_id = $user->org_id;
39
40     $sql = 'select ';
41     if ($all_fields)
42       $sql .= '* ';
43     else
44       $sql .= 'name ';
45
46     $sql .= "from tt_clients where group_id = $group_id and org_id = $org_id".
47       " and id = $client_id and (status = 1 or status = 0)";
48     $res = $mdb2->query($sql);
49     if (!is_a($res, 'PEAR_Error')) {
50       $val = $res->fetchRow();
51       return $val;
52     }
53     return false;
54   }
55
56   // getClients - returns an array of active and inactive clients in a group.
57   static function getClients() {
58     global $user;
59     $mdb2 = getConnection();
60
61     $group_id = $user->getGroup();
62     $org_id = $user->org_id;
63
64     $result = array();
65
66     $sql = "select id, name, projects from tt_clients where group_id = $group_id and org_id = $org_id and (status = 0 or status = 1) order by upper(name)";
67     $res = $mdb2->query($sql);
68     if (!is_a($res, 'PEAR_Error')) {
69       while ($val = $res->fetchRow()) {
70         $result[] = $val;
71       }
72     }
73     return $result;
74   }
75
76   // The getClientByName looks up a client by name.
77   static function getClientByName($client_name) {
78     global $user;
79     $mdb2 = getConnection();
80
81     $group_id = $user->getGroup();
82     $org_id = $user->org_id;
83
84     $sql = "select id from tt_clients where group_id = $group_id and org_id = $org_id".
85       " and name = ".$mdb2->quote($client_name)." and (status = 1 or status = 0)";
86     $res = $mdb2->query($sql);
87     if (!is_a($res, 'PEAR_Error')) {
88       $val = $res->fetchRow();
89       if ($val['id']) {
90         return $val;
91       }
92     }
93     return false;
94   }
95
96   // The getDeletedClient looks up a deleted client by id.
97   static function getDeletedClient($client_id) {
98     global $user;
99     $mdb2 = getConnection();
100
101     $group_id = $user->getGroup();
102     $org_id = $user->org_id;
103
104     $sql = "select name, address from tt_clients where group_id = $group_id and org_id = $org_id".
105       " and id = $client_id and status is NULL";
106     $res = $mdb2->query($sql);
107     if (!is_a($res, 'PEAR_Error')) {
108       $val = $res->fetchRow();
109       return $val;
110     }
111     return false;
112   }
113
114   // The delete function marks client as deleded.
115   static function delete($id, $delete_client_entries) {
116     global $user;
117     $mdb2 = getConnection();
118
119     $group_id = $user->getGroup();
120     $org_id = $user->org_id;
121
122     // Handle custom field log records.
123     if ($delete_client_entries) {
124       $sql = "update tt_custom_field_log set status = null".
125         " where log_id in (select id from tt_log where client_id = $id and status = 1) and group_id = $group_id and org_id = $org_id";
126       $affected = $mdb2->exec($sql);
127       if (is_a($affected, 'PEAR_Error'))
128         return false;
129     }
130
131     // Handle time records.
132     $modified_part = ', modified = now(), modified_ip = '.$mdb2->quote($_SERVER['REMOTE_ADDR']).', modified_by = '.$user->id;
133     if ($delete_client_entries) {
134       $sql = 'update tt_log set status = null'.$modified_part.
135         " where client_id = $id and group_id = $group_id and org_id = $org_id";
136       $affected = $mdb2->exec($sql);
137       if (is_a($affected, 'PEAR_Error'))
138         return false;
139     }
140
141     // Handle expense items.
142     if ($delete_client_entries) {
143       $sql = 'update tt_expense_items set status = null'.$modified_part.
144         " where client_id = $id and group_id = $group_id and org_id = $org_id";
145       $affected = $mdb2->exec($sql);
146       if (is_a($affected, 'PEAR_Error'))
147         return false;
148     }
149
150     // Handle invoices.
151     if ($delete_client_entries) {
152       $sql = "update tt_invoices set status = null".
153         " where client_id = $id and group_id = $group_id and org_id = $org_id";
154       $affected = $mdb2->exec($sql);
155       if (is_a($affected, 'PEAR_Error'))
156         return false;
157     }
158
159     // Delete project binds to this client.
160     $sql = "delete from tt_client_project_binds".
161       " where client_id = $id and group_id = $group_id and org_id = $org_id";
162     $affected = $mdb2->exec($sql);
163     if (is_a($affected, 'PEAR_Error'))
164       return false;
165
166     // Handle users for client.
167     $sql = 'update tt_users set status = null'.$modified_part.
168       " where client_id = $id and group_id = $group_id and org_id = $org_id";
169     $affected = $mdb2->exec($sql);
170     if (is_a($affected, 'PEAR_Error'))
171       return false;
172
173     // Mark client deleted.
174     $sql = "update tt_clients set status = null".
175       " where id = $id and group_id = $group_id and org_id = $org_id";
176     $affected = $mdb2->exec($sql);
177     return (!is_a($affected, 'PEAR_Error'));
178   }
179
180   // The insert function inserts a new client record into the clients table.
181   static function insert($fields)
182   {
183     global $user;
184     $mdb2 = getConnection();
185
186     $group_id = $user->getGroup();
187     $org_id = $user->org_id;
188
189     $name = $fields['name'];
190     $address = $fields['address'];
191     $tax = $fields['tax'];
192     $projects = $fields['projects'];
193     if ($projects)
194       $comma_separated = implode(',', $projects); // This is a comma-separated list of associated projects ids.
195     $status = $fields['status'];
196
197     $tax = str_replace(',', '.', $tax);
198     if ($tax == '') $tax = 0;
199
200     $sql = "insert into tt_clients (group_id, org_id, name, address, tax, projects, status)".
201       " values ($group_id, $org_id, ".$mdb2->quote($name).", ".$mdb2->quote($address).", $tax, ".$mdb2->quote($comma_separated).", ".$mdb2->quote($status).")";
202
203     $affected = $mdb2->exec($sql);
204     if (is_a($affected, 'PEAR_Error'))
205       return false;
206
207     $last_id = $mdb2->lastInsertID('tt_clients', 'id');
208     if (count($projects) > 0)
209       foreach ($projects as $p_id) {
210         $sql = "insert into tt_client_project_binds (client_id, project_id, group_id, org_id) values($last_id, $p_id, $group_id, $org_id)";
211         $affected = $mdb2->exec($sql);
212         if (is_a($affected, 'PEAR_Error'))
213           return false;
214       }
215
216     return $last_id;
217   }
218
219   // The update function updates a client record in tt_clients table.  
220   static function update($fields)
221   {
222     global $user;
223     $mdb2 = getConnection();
224
225     $group_id = $user->getGroup();
226     $org_id = $user->org_id;
227
228     $id = $fields['id'];
229     $name = $fields['name'];
230     $address = $fields['address'];
231     $tax = $fields['tax'];
232     $status = $fields['status'];
233     $projects = $fields['projects'];
234
235     $tax = str_replace(',', '.', $tax);
236     if ($tax == '') $tax = 0;
237
238     // Insert client to project binds into tt_client_project_binds table.
239     $sql = "delete from tt_client_project_binds".
240       " where client_id = $id and group_id = $group_id and org_id = $org_id";
241     $affected = $mdb2->exec($sql);
242     if (is_a($affected, 'PEAR_Error'))
243       die($affected->getMessage());
244     if (count($projects) > 0)
245       foreach ($projects as $p_id) {
246         $sql = "insert into tt_client_project_binds (client_id, project_id, group_id, org_id) values($id, $p_id, $group_id, $org_id)";
247         $affected = $mdb2->exec($sql);
248         if (is_a($affected, 'PEAR_Error'))
249           return false;
250       }
251
252     // Update client properties in tt_clients table.
253     $comma_separated = implode(",", $projects); // This is a comma-separated list of associated project ids.
254     $sql = "update tt_clients set name = ".$mdb2->quote($name).", address = ".$mdb2->quote($address).
255       ", tax = $tax, projects = ".$mdb2->quote($comma_separated).", status = $status".
256       " where id = $id and group_id = $group_id and org_id = $org_id";
257     $affected = $mdb2->exec($sql);
258     return (!is_a($affected, 'PEAR_Error'));
259   }
260
261   // The fillBean function fills the ActionForm object with client data.
262   static function fillBean($client_id, &$bean) {
263     $client = ttClientHelper::getClient($client_id, true);
264     $bean->setAttribute('name', $client['name']);
265     $bean->setAttribute('address', $client['address']);
266     $bean->setAttribute('tax', $client['tax']);
267   }
268
269   // getAssignedProjects - returns an array of projects associatied with a client.
270   static function getAssignedProjects($client_id)
271   {
272     global $user;
273     $mdb2 = getConnection();
274
275     $group_id = $user->getGroup();
276     $org_id = $user->org_id;
277
278     $result = array();
279
280     // Do a query with inner join to get assigned projects.
281     $sql = "select p.id, p.name from tt_projects p".
282       " inner join tt_client_project_binds cpb on (cpb.client_id = $client_id and cpb.project_id = p.id)".
283       " where p.group_id = $group_id and p.org_id = $org_id and p.status = 1 order by p.name";
284     $res = $mdb2->query($sql);
285     if (!is_a($res, 'PEAR_Error')) {
286       while ($val = $res->fetchRow()) {
287         $result[] = $val;
288       }
289     }
290     return $result;
291   }
292
293   // getClientsForUser - returns an array of clients that are relevant to a user via assigned projects. 
294   static function getClientsForUser()
295   {
296     global $user;
297     $mdb2 = getConnection();
298
299     $user_id = $user->getUser();
300     $group_id = $user->getGroup();
301     $org_id = $user->org_id;
302
303     $result = array();
304
305     $sql = "select distinct c.id, c.name, c.projects from tt_user_project_binds upb".
306       " inner join tt_client_project_binds cpb on (cpb.project_id = upb.project_id)".
307       " inner join tt_clients c on (c.id = cpb.client_id and c.status = 1)".
308       " where upb.user_id = $user_id and upb.group_id = $group_id and upb.org_id = $org_id".
309       " and upb.status = 1 order by upper(c.name)";
310
311     $res = $mdb2->query($sql);
312     if (!is_a($res, 'PEAR_Error')) {
313       while ($val = $res->fetchRow()) {
314         $result[] = $val;
315       }
316     }
317     return $result;
318   }
319
320   // deleteProject - deletes a project from the projects field it tt_clients table
321   // for all clients in a group.
322   static function deleteProject($project_id) {
323     global $user;
324     $mdb2 = getConnection();
325
326     $group_id = $user->getGroup();
327     $org_id = $user->org_id;
328
329     $sql = "select id from tt_clients".
330       " where projects like '%$project_id%'".
331       " and group_id = $group_id and org_id = $org_id";
332     $res = $mdb2->query($sql);
333     if (!is_a($res, 'PEAR_Error')) {
334       while ($val = $res->fetchRow()) {
335         if (!ttClientHelper::deleteProjectFromClient($project_id, $val['id']))
336           return false;
337       }
338     }
339     return true;
340   }
341
342   // deleteProjectFromClient - deletes a project from the projects field in tt_clients table
343   // for a single client in a group.
344   static function deleteProjectFromClient($project_id, $client_id) {
345     global $user;
346     $mdb2 = getConnection();
347
348     $group_id = $user->getGroup();
349     $org_id = $user->org_id;
350
351     $sql = "select projects from tt_clients".
352       " where id = $client_id and group_id = $group_id and org_id = $org_id";
353     $res = $mdb2->query($sql);
354     if (is_a($res, 'PEAR_Error')) return false;
355     $val = $res->fetchRow();
356     $projects = explode(',', $val['projects']);
357     if (($key = array_search($project_id, $projects)) !== false) {
358       unset($projects[$key]);
359     }
360     $comma_separated = implode(',', $projects);
361     $sql = "update tt_clients set projects = ".$mdb2->quote($comma_separated).
362       " where id = $client_id and group_id = $group_id and org_id = $org_id";
363     $affected = $mdb2->exec($sql);
364     return (!is_a($affected, 'PEAR_Error'));
365   }
366 }