Source for file timesheet.class.php

Documentation is available at timesheet.class.php


1 <?php
2 /**
3 *
4 * @version $Id: timesheet.class.php,v 1.2 2003/09/25 09:35:57 cybot_tm Exp $
5 * @category phpTimeSheet
6 * @package phpTimeSheet
7 */
8
9 /**
10 * read-only access to time-tables (project-times and worker-times)
11 *
12 * @uses Date
13 * @uses Time
14 * @uses Worktype
15 * @uses Daytype
16 */
17 class Timesheet
18 {
19
20 /**
21 * @var object Date
22 * @since 1.0
23 */
24 var $date_start;
25
26 /**
27 * @var object Date
28 * @since 1.0
29 */
30 var $date_end;
31
32 /**
33 * @var array int worker_id
34 * @since 1.0
35 */
36 var $worker = array();
37
38 /**
39 * @var array object Project
40 * @since 1.0
41 */
42 var $projects = array();
43
44 var $worker_times;
45 var $project_times;
46
47 /**
48 * @return bool success
49 */
50 function Timesheet($date_start, $date_end = null)
51 {
52 $this->SetDate($date_start, $date_end);
53 return TRUE;
54 }
55
56 /**
57 * Sets current date
58 *
59 * @param mixed date object date or string
60 * @param mixed date object date or string
61 * @uses Date
62 * @uses Date::IsNull()
63 * @uses Date::AddDay()
64 * @uses Date::Get()
65 * @uses Date::IsLT()
66 * @uses $date_start
67 * @uses $date_end
68 * @uses $days
69 * @uses __FUNCTION__
70 * @uses __CLASS__
71 * @uses __LINE__
72 * @uses __FILE__
73 */
74 function SetDate($date_start, $date_end = null)
75 {
76 if ( null === $date_end )
77 {
78 $date_end = $date_start;
79 }
80 $this->date_start = new Date($date_start);
81 $this->date_end = new Date($date_end);
82
83 if ( $this->date_start->IsNull() || $this->date_end->IsNull() )
84 {
85 die('<pre>' . __FILE__ . ': ' . __LINE__ . "\n" . __CLASS__ . '::' . __FUNCTION__ . "\nparam 1 or 2 is not a valid Date!");
86 }
87
88 return true;
89 }
90
91 /**
92 * Sets worker_id
93 *
94 * @uses $worker
95 */
96 function SetWorker($worker_id)
97 {
98 $this->worker = array();
99 $this->worker[] = (int) $worker_id;
100 return true;
101 }
102
103 function GetWorkerIdList()
104 {
105
106 }
107
108 /**
109 * @uses $date_start
110 * @uses $date_end
111 * @uses $worker
112 * @uses $days
113 * @uses GetWorkerIdList()
114 * @uses Date
115 * @uses Date::Get()
116 * @uses Time
117 * @uses Time::Sub()
118 * @uses PTS_TBL_WORKTYPE
119 * @uses PTS_TBL_DAYTYPE
120 * @uses PTS_TBL_WORKTIME
121 * @uses PTS_TBL_WORKER
122 * @uses __FILE__
123 * @uses __LINE__
124 * @uses __FUNCTION__
125 * @uses __CLASS__
126 * @uses mysql_query()
127 * @uses mysql_error()
128 * @uses mysql_fetch_assoc()
129 * @uses implode()
130 * @uses date()
131 * @uses count()
132 */
133 function LoadWorkerTimes()
134 {
135 if ( $this->date_start->IsNull() || $this->date_end->IsNull() )
136 {
137 die('<pre>' . __FILE__ . ': ' . __LINE__ . "\n" . __CLASS__ . '::' . __FUNCTION__ . "\n" . __CLASS__ . '::date_end and/or ' . __CLASS__ . '::date_start is not a valid Date!');
138 }
139
140 if ( count($this->worker) === 0 )
141 {
142 die('<pre>' . __FILE__ . ': ' . __LINE__ . "\n" . __CLASS__ . '::' . __FUNCTION__ . "\n" . __CLASS__ . '::worker is empty, use ' . __CLASS__ . '::SetWorker() first!');
143 }
144
145 // first: load all times for this worker and all times for all workers past contract_start and before contract_end
146 $sql = '
147 SELECT `' . PTS_TBL_WORKTIME . '`.`worker`,
148 `' . PTS_TBL_WORKTIME . '`.`day`,
149 `' . PTS_TBL_WORKTIME . '`.`allowed`,
150 SUBSTRING_INDEX(`' . PTS_TBL_WORKTIME . '`.`contracted_hours`, ":", 2) AS `contracted_hours`,
151 SUBSTRING_INDEX(`' . PTS_TBL_WORKTIME . '`.`go`, ":", 2) AS `go`,
152 SUBSTRING_INDEX(`' . PTS_TBL_WORKTIME . '`.`come`, ":", 2) AS `come`,
153 SUBSTRING_INDEX(`' . PTS_TBL_WORKTIME . '`.`workspace`, ":", 2) AS `workspace`,
154 SUBSTRING_INDEX(SEC_TO_TIME(TIME_TO_SEC(`' . PTS_TBL_WORKTIME . '`.`go`) - TIME_TO_SEC(`' . PTS_TBL_WORKTIME . '`.`come`)), ":", 2) AS `attend_time`,
155 SUBSTRING_INDEX(SEC_TO_TIME(TIME_TO_SEC(`' . PTS_TBL_WORKTIME . '`.`go`) - TIME_TO_SEC(`' . PTS_TBL_WORKTIME . '`.`come`) - TIME_TO_SEC(`' . PTS_TBL_WORKTIME . '`.`workspace`)), ":", 2) AS `work_time`,
156 SUBSTRING_INDEX(SEC_TO_TIME(TIME_TO_SEC(`' . PTS_TBL_WORKTIME . '`.`go`) - TIME_TO_SEC(`' . PTS_TBL_WORKTIME . '`.`come`) - TIME_TO_SEC(`' . PTS_TBL_WORKTIME . '`.`workspace`) - TIME_TO_SEC(`' . PTS_TBL_WORKTIME . '`.`contracted_hours`)), ":", 2) AS `overtime`,
157 `' . PTS_TBL_WORKTIME . '`.`worktype`,
158 `' . PTS_TBL_WORKTIME . '`.`daytype`,
159 `' . PTS_TBL_WORKTYPE . '`.`name` AS `worktype_name`,
160 `' . PTS_TBL_DAYTYPE . '`.`name` AS `daytype_name`
161 FROM `' . PTS_TBL_WORKTIME . '`
162 LEFT JOIN `' . PTS_TBL_WORKTYPE . '`
163 ON `' . PTS_TBL_WORKTIME . '`.`worktype` = `' . PTS_TBL_WORKTYPE . '`.`id`
164 LEFT JOIN `' . PTS_TBL_DAYTYPE . '`
165 ON `' . PTS_TBL_WORKTIME . '`.`daytype` = `' . PTS_TBL_DAYTYPE . '`.`id`
166 WHERE `' . PTS_TBL_WORKTIME . '`.`day` BETWEEN "' . $this->date_start->Get() . '" AND "' . $this->date_end->Get() . '"
167 AND `' . PTS_TBL_WORKTIME . '`.`worker` IN (' . implode(',', $this->worker) . ',0)';
168
169 $result = mysql_query($sql) or die('<pre>' . __FILE__ . ': ' . __LINE__ . "\n" . __CLASS__ . '::' . __FUNCTION__ . "\n" . $sql . "\n" . mysql_error());
170
171 while ( $row = mysql_fetch_assoc($result) )
172 {
173 if ( $row['day'] === date('Y-m-d') && $row['come'] !== '00:00' && $row['go'] === '00:00' )
174 {
175 // current row is today and worker is at work, so we have to add some missing information
176 $now = new Time(date('H:i'));
177 $row['go'] = $now->Get();
178 $now->Sub($row['come']);
179 $row['attend_time'] = $now->Get();
180 $now->Sub($row['workspace']);
181 $row['work_time'] = $now->Get();
182 $row['overtime'] = '00:00';
183 }
184
185 // adds time-information to days-array
186 $this->worker_times[$row['worker']][$row['day']] = $row;
187 }
188
189 // fill all days for worker with no entrys with public-times or default values
190 // default values
191 $row = array();
192 $row['go'] = '00:00';
193 $row['come'] = '00:00';
194 $row['workspace'] = '00:00';
195 $row['contracted_hours'] = '00:00';
196 $row['attend_time'] = '00:00';
197 $row['work_time'] = '00:00';
198 $row['overtime'] = '00:00';
199 $row['worktype'] = PTS_WT_STANDARD;
200 $row['worktype_name'] = 'standard';
201 $row['daytype'] = PTS_DT_STANDARD;
202
203 foreach ( $this->worker as $worker_id )
204 {
205 if ( ! isset($this->worker_times[$worker_id]) )
206 {
207 $this->worker_times[$worker_id] = array();
208 }
209 for ( $day = $this->date_start; $day->IsLE($this->date_end); $day->AddDay() )
210 {
211 if ( ! isset($this->worker_times[$worker_id][$day->Get()]) )
212 {
213 if ( isset($this->worker_times[0][$day->Get()]) )
214 {
215 // public times if worker is unset for this day
216 $this->worker_times[$worker_id][$day->Get()] = $this->worker_times[0][$day->Get()];
217 }
218 else
219 {
220 // default values
221 $row['worker'] = $worker_id;
222 $this->worker_times[$worker_id][$day->Get()] = $row;
223 }
224 }
225 }
226 }
227
228
229 return true;
230 }
231
232 /**
233 * @uses $date_start
234 * @uses $date_end
235 * @uses $worker
236 * @uses $days
237 * @uses GetWorkerIdList()
238 * @uses Date
239 * @uses Date::Get()
240 * @uses Time
241 * @uses Time::Sub()
242 * @uses PTS_TBL_WORKTYPE
243 * @uses PTS_TBL_DAYTYPE
244 * @uses PTS_TBL_WORKTIME
245 * @uses PTS_TBL_WORKER
246 * @uses __FILE__
247 * @uses __LINE__
248 * @uses __FUNCTION__
249 * @uses __CLASS__
250 * @uses mysql_query()
251 * @uses mysql_error()
252 * @uses mysql_fetch_assoc()
253 * @uses implode()
254 * @uses date()
255 * @uses count()
256 */
257 function LoadProjectTimes()
258 {
259 if ( $this->date_start->IsNull() || $this->date_end->IsNull() )
260 {
261 die('<pre>' . __FILE__ . ': ' . __LINE__ . "\n" . __CLASS__ . '::' . __FUNCTION__ . "\n" . __CLASS__ . '::date_end and/or ' . __CLASS__ . '::date_start is not a valid Date!');
262 }
263
264 if ( count($this->worker) === 0 )
265 {
266 die('<pre>' . __FILE__ . ': ' . __LINE__ . "\n" . __CLASS__ . '::' . __FUNCTION__ . "\n" . __CLASS__ . '::worker is empty, use ' . __CLASS__ . '::SetWorker() first!');
267 }
268
269
270 $sql = '
271 SELECT `' . PTS_TBL_PROJECT_TIME . '`.`worker`,
272 `' . PTS_TBL_PROJECT_TIME . '`.`subpid`,
273 `' . PTS_TBL_PROJECT_TIME . '`.`day`,
274 SUBSTRING_INDEX(`' . PTS_TBL_PROJECT_TIME . '`.`time`, ":", 2) AS `time`,
275 CONCAT_WS(" - ", `parent`.`name`, `' . PTS_TBL_PROJECT . '`.`name`) AS `name`
276 FROM `' . PTS_TBL_PROJECT_TIME . '`
277 LEFT JOIN `' . PTS_TBL_PROJECT . '`
278 ON `' . PTS_TBL_PROJECT_TIME . '`.`subpid` = `' . PTS_TBL_PROJECT . '`.`id`
279 LEFT JOIN `' . PTS_TBL_PROJECT . '` AS `parent`
280 ON `' . PTS_TBL_PROJECT . '`.`parent` = `parent`.`id`
281 WHERE `' . PTS_TBL_PROJECT_TIME . '`.`day` BETWEEN "' . $this->date_start->Get() . '" AND "' . $this->date_end->Get() . '"
282 AND `' . PTS_TBL_PROJECT_TIME . '`.`worker` IN (' . implode(',', $this->worker) . ')';
283 $result = mysql_query($sql) or die('<pre>' . __FILE__ . ': ' . __LINE__ . "\n" . __CLASS__ . '::' . __FUNCTION__ . "\n" . $sql . "\n" . mysql_error());
284
285 while ( $row = mysql_fetch_assoc($result) )
286 {
287 $this->project_times[$row['subpid']][$row['day']]['time'] = $row['time'];
288 $this->project_times[$row['subpid']]['name'] = $row['name'];
289 }
290
291 return true;
292 }
293
294 /**
295 *
296 * @return bool success
297 */
298 function UpdateWorkType($worktype)
299 {
300 $sql = '
301 UPDATE `' . PTS_TBL_WORKTIME . '`
302 SET `worktype` = ' . $worktype . '
303 WHERE `day` = "' . $this->date->Get() . '"
304 AND `worker` = ' . $this->GetWorkerId();
305 echo $sql;
306 $result = mysql_query($sql) or die('<pre>' . __FILE__ . ': ' . __LINE__ . "\n" . __CLASS__ . '::' . __FUNCTION__ . "\n" . $sql . "\n" . mysql_error());
307
308 return true;
309 }
310
311 function get_next_day() { return date('Y-m-d',strtotime($this->daydate) + 24*60*60); }
312 function get_last_day() { return date('Y-m-d',strtotime($this->daydate) - 24*60*60); }
313
314 function is_pid_in_array($needle, $haystack){
315 return in_array($needle,array_flip($haystack));
316 }
317
318 function update__hours_from_form($post_vars){
319 $i=0;
320 if ( is_array($_REQUEST['pid']) ) {
321 while ( list($pindex, $phours) = each($_REQUEST['pid']) ) {
322 $phours = str_replace(",",".",$phours);
323 $phours = str_replace(":",".",$phours);
324 $this->replacehours[$pindex] = $phours;
325 }
326 }
327
328 // wenn einem neuen projekt stunden zugewiesen werden sollen
329 $_REQUEST['new_pid_hours'] = str_replace(",",".",$_REQUEST['new_pid_hours']);
330 $_REQUEST['new_pid_hours'] = str_replace(":",".",$_REQUEST['new_pid_hours']);
331
332 if ($_REQUEST['new_pid'] != '' && $_REQUEST['new_subpid'] != '' && $_REQUEST['new_pid_hours'] > 0) {
333
334 // falss es die teilleistung noch nicht gibt dann müssen wir sie erst anlegen
335 if ( intval($_REQUEST['new_subpid']) == 0 ) {
336 $sql = '
337 INSERT INTO `pids`
338 SET `pname` = "' . $_REQUEST['new_subpid'] . '",
339 `pstatus` = 1,
340 `ptyp` = "C",
341 `windex` = ' . get_workerid_by_name($_REQUEST['worker_name']) . ',
342 `pparent` = ' . $_REQUEST['new_pid'];
343 $result = mysql_query($sql) or die(" <pre>Workday->update__hours_from_form() BadSQL:\n$sql\n" . mysql_error());
344 $_REQUEST['new_subpid'] = mysql_insert_id();
345 }
346
347 $this->replacehours[$_REQUEST['new_subpid']] = $_REQUEST['new_pid_hours'];
348 }
349 }
350
351 function db_update($worker)
352 {
353 $wid = $worker->get_db_index();
354 $compid = $worker->get_employer();
355
356 if ( count($this->replacehours) ) {
357 while ( list($subpid, $hours) = each($this->replacehours) ) {
358 if ( $hours > 0 ) {
359 $pid = get_parent_for_subpid($subpid);
360 $sql = sprintf("
361 REPLACE %s
362 SET day = '%s',
363 worker = %d,
364 pid = %d,
365 worktype = 0,
366 hours = %f,
367 company = %d,
368 subpid = %d
369 ",
370 PTS_TBL_PROJECT_TIME, $this->daydate, $wid, $pid, hmin_to_db($hours), $compid, $subpid);
371 }
372 else {
373 $sql = sprintf("
374 DELETE FROM %s
375 WHERE day = '%s'
376 AND worker = %d
377 AND worktype = 0
378 AND subpid = %d
379 LIMIT 1",
380 PTS_TBL_PROJECT_TIME, $this->daydate, $wid, $subpid);
381 }
382 $result = mysql_query("$sql")or die(" <pre>WorkDay->db_update(): BadSQL:\n$sql\n".mysql_error());
383 }
384 }
385 }
386
387 function get_day_form($pid_list)
388 {
389
390 $info = "<table width=\"500\" bordercolor=\"#666666\" cellspacing=\"1\" bgcolor=\"#999999\" border=\"1\" noshade=\"noshade\">\n";
391 $info .= "<tr>\n<th>Projekt(e)</th>\n<th>Std.,Min.</th>\n</tr>\n";
392
393 if ( $this->numentries)
394 {
395 while(list($pindex, $pname) = each($this->pidnames)){
396 $info .= "<tr>\n<td align=\"center\"> \n";
397 $info .= sprintf("%s\n</td>\n", $pname);
398 $info .= sprintf("<td align=\"center\"><input type=\"text\" name=\"pid[%d]\" size=\"5\" value=\"%s\"></td>\n</tr>\n",
399 $pindex, min_to_hours(db_to_min($this->hours[$pindex])));
400 }
401 }
402
403 $script .= '
404 <script language="javascript">
405 <!--
406 function chooseMake(strFormName, boolHeadContained)
407 {
408 var arrModelList;
409 var objModelSelection;
410 var objMakeSelection;
411 var intOffSetForAll;
412 var i;
413
414 if (document.forms[strFormName].new_subpid == null)
415 return;
416
417 objModelSelection = document.forms[strFormName].new_subpid;
418 objMakeSelection = document.forms[strFormName].new_pid;
419 objModelSelection.selectedIndex = 0;
420 objModelSelection.options.length = 1;
421
422 if (boolHeadContained)
423 intOffsetForAll = 1;
424 else
425 intOffsetForAll = 0;
426
427
428 if (objMakeSelection.selectedIndex >= intOffsetForAll){
429 arrModelList = (arrModels[objMakeSelection.selectedIndex + 1 - intOffsetForAll]).split(\';\');
430 for (i = 0; i < arrModelList.length; i++){
431 objModelSelection.options.length = i+2;
432 objModelSelection.options[i+1].value = (arrModelList[i]).split(\',\')[0];
433 objModelSelection.options[i+1].text = (arrModelList[i]).split(\',\')[1];
434 }
435 }
436 } // chooseMake
437
438 // inhalt für die zweite selectbox ID,Name[;ID,Name[;ID,Name]...]
439
440 var arrModels = new Array();
441 ';
442
443 $info .= "<tr><td bgcolor=\"#000066\" align=\"center\"> <font color=\"#cccccc\"> <small>Neues Projekt hinzufügen</small></font><br />\n<select name=\"new_pid\" onChange=\"chooseMake('searchform', true);\">\n";
444 $info .= "<option value=\"\">Bitte w&auml;hlen...</option>\n";
445 $i = 1;
446 while(list($key, $val) = each($pid_list)){
447 $subpid_list = list_subpids_for_pid($key);
448 $script_array_ = '';
449 if ( ! empty($subpid_list) ) {
450 foreach ( $subpid_list as $pindex => $pname )
451 $script_array_ .= "$pindex,$pname;";
452 $script_array .= "arrModels[$i] = '" . substr($script_array_,0,-1) . "';\n";
453 $i++;
454 if ($new_pid == $key)
455 $info .= sprintf("<option value=\"%d\" selected=\"selected\">%s</option>\n", $key, $val);
456 else
457 $info .= sprintf("<option value=\"%d\">%s</option>\n", $key, $val);
458 }
459
460 }
461
462 $script .= $script_array . "//--></script>";
463 $info .= "</select>\n";
464 $info .= "<select name=\"new_subpid\">\n";
465 $info .= "<option value=\"\">Bitte w&auml;hlen...</option>\n";
466 $info .= "</select></td>\n";
467 $info .= "<td bgcolor=\"#000066\" align=\"center\"><input type=\"text\" name=\"new_pid_hours\" size=\"5\"></td></tr>\n";
468 $info .= "</table>\n";
469 $info .= $script;
470 return($info);
471 }
472
473 // PATCH LUCKE : BEGIN
474 function get_day_total() { return $this->totalhours; }
475 // PATCH LUCKE : END
476
477 function get_worktime(){
478 $work = substr($this->worktime["Kommt"],0,5)." Uhr<br />";
479 $work .= substr($this->worktime["Geht"],0,5)." Uhr<br />";
480 $work .= $this->worktime["Anz"] . " Std.";
481 return $work;
482 }
483
484 function get_day_info(){
485
486 $info = "<table bordercolor=\"#666666\" cellspacing=\"1\" BGCOLOR=\"#999999\" border=\"1\" noshade>\n<tr>\n";
487 $info .= "<th bgcolor=\"000066\"> <font color=\"CCCCCC\">Projekt</font></th>\n<th bgcolor=\"000066\"> <font color=\"CCCCCC\">Std.</font></th>\n</tr>\n";
488
489 if ($this->daytype[0] == 0){} //normaler Arbeitstag, nichts weiter
490 else
491 {
492 foreach ($this->daytype as $dt)
493 {
494 switch ($dt) {
495 case 0: break;
496 case 1: $info .= "<tr><td bgcolor=#ffcc66 colspan=2>Urlaub beantragt</td></tr>"; break;
497 case 2: $info .= "<tr><td bgcolor=#66cc66 colspan=2>Urlaub</td></tr>"; break;
498 case 3: $info .= "<tr><td bgcolor=#00e0ff colspan=2>Feiertag</td></tr>"; break;
499 case 4: $info .= "<tr><td bgcolor=#669966 colspan=2>Krank</td></tr>"; break;
500 case 5: $info .= "<tr><td bgcolor=#66cc66 colspan=2>halber Urlaubstag</td></tr>"; break;
501 case 6: $info .= "<tr><td bgcolor=#00e0ff colspan=2>halber *Feiertag*</td></tr>"; break;
502 default: break;
503 }
504 }
505 }
506
507 if($this->numentries){
508 while(list($key, $val) = each($this->pidnames)){
509 $info .= "<tr>\n<td> \n";
510 $info .= sprintf(" %s\n</td>\n<td align=\"center\">%s</td>\n</tr>\n",
511 $val, dbhm($this->hours[$key]));
512 }
513 }
514 $info .= "</table>\n";
515 return($info);
516 }
517
518 function set_daytype($wid){
519 $sql = sprintf("SELECT distinct worktype FROM %s WHERE day = '%s' AND (worker = %d OR worker = 0) ORDER BY worktype DESC",
520 PTS_TBL_PROJECT_TIME,$this->daydate, $wid);
521
522 $result = mysql_query("$sql")or die(" WorkDay-daytypeload(): BadSelect: $sql".mysql_error());
523
524 if ($result){
525 while($typ = mysql_fetch_row($result)){
526 $this->daytype[] = $typ[0];
527 }
528 }
529 else $this->daytype[0] = 0;
530 }
531
532
533 /* Sends an email notifing someone when the time is updated*/
534 function mail_notify($address, $fromaddr, $worker){
535
536 $subject = sprintf("Timesheet: hours updated for %s", $worker);
537 $message = sprintf("The worker %s updated their hours for %s",
538 $worker, $this->daydate);
539 mail($address, $subject, $message, "From: $fromaddr\nX-Mailer: PHP/" . phpversion());
540 }/*function mail_notify($address)*/
541 }/* class WorkDay */
542
543 ?>

Documentation generated on Fri, 26 Sep 2003 15:40:00 +0200 by phpDocumentor 1.2.2