timetracksum = 0; $q = "SELECT SUM(volume) as XX FROM ". $obj->dbconn->prefix .$table['timetrack'][name]; $pre = " WHERE "; if ( $obj->getType() == "address" ) { $q .= $pre . " adr_id =". $obj->id ; } else if ( $obj->getType() == "user" ) { $q .= $pre . " adr_id =". $obj->id ; } else if ( $obj->getType() == "team" ) { $q .= $pre . " adr_id =". $obj->id ; } else { $q .= $pre . " link_id =". $obj->id ; } $r = $obj->dbconn->Exec($q); $n = $r->numrows(); if ( $n == 0 ) { return; } $obj->timetracksum = $r->get(0,"XX"); $r->free(); return; } /** * Compute the amount of work done by $address on $task * * FIXME : add some time schedule restriction */ function computeWorkedHours(&$address, &$task) { global $table; $sum = 0; $q = "SELECT SUM(volume) as XX FROM ". $task->dbconn->prefix .$table['timetrack'][name]. " WHERE adr_id = ". $address->id. " AND link_id = ". $task->id; $r = $task->dbconn->Exec($q); $n = $r->numrows(); if ( $n == 0 ) { return $sum; } $sum = $r->get(0,"XX"); $r->free(); return $sum == "" ? 0 : $sum; } /** * A fraction of a timetrack * @package timetrack */ class timetrack extends tutos_base { /* --------------------------------------------------------------------------- */ function timetrack(&$dbconn) { global $tutos,$current_user,$table; $this->init($dbconn); $this->wid = $current_user->id; $this->worker = $current_user; $this->link_id = -1; $this->ref = -1; $this->desc = ""; $this->volume = 0.0; $this->volume_todo = -1; $this->wday = new DateTime(); $this->creation = new DateTime(); $this->t_start = new DateTime(0); $this->t_end = new DateTime(0); # number of invoice $this->invoice = -1; $this->currency = $tutos[currencies][0]; # Costs per hour ("" == default) $this->cph = 0.0; # State (-1 == unknown , 1 == checke 2 == billed) $this->state = -1; $this->inv_id = -1; $this->tablename = $this->dbconn->prefix .$table['timetrack'][name]; } /** * read a resultset */ function read_result (&$r, $pos ) { global $g_hash; $this->id = $r->get($pos, "id"); $this->wid = $r->get($pos, "adr_id"); $this->worker = getObject($this->dbconn,$this->wid); $this->link_id = $r->get($pos, "link_id"); $this->ref = getObject($this->dbconn,$this->link_id); $this->desc = $r->get($pos, "description"); $this->volume = $r->get($pos, "volume"); $this->volume_todo = $r->get($pos, "volume_todo"); $this->state = (integer)$r->get($pos, "state"); $this->cph = $r->get($pos, "cph"); $this->currency = $r->get($pos, "currency"); $this->inv_id = $r->get($pos, "invoice"); $this->creation->setDateTime($r->get($pos, "creation")); $this->wday->setDateTime($r->get($pos, "vtime")); $this->t_start->setDateTime($r->get($pos, "t_start")); $this->t_end->setDateTime($r->get($pos, "t_end")); if ( $this->inv_id == "" ) { $this->inv_id = -1; $this->invoice = -1; } if ( $this->state == "" ) { $this->state = -1; } if ( $this->cph == "" ) { $this->cph = 0.00; } $this->creator = getObject($this->dbconn,$r->get($pos, "creator")); parent::read_result($r,$pos); return; } /** * get a list of possible new parents */ function read_relations ( ) { global $lang,$current_user; $this->plist = array(); if ($this->ref != -1) { # Read possible new parents $this->plist = $this->ref->getNeighbours(); } # a timetrack object could be attached to all projects and tasks where we play a role if ( $current_user->feature_ok(useprojects,PERM_SEE) ) { $q = "SELECT p.* from ". $this->dbconn->prefix."products p,". $this->dbconn->prefix ."projectroles r "; $pre = " WHERE "; if ($this->worker->id > 0) { $q .= $pre ." r.adr_id in(". $this->worker->id; $q .= " ) "; $pre = " AND "; } $q .= $pre ." r.pro_id = p.id"; $q .= " AND p.state != ".PROD_STATE_CANCEL; $q .= " AND p.state != ".PROD_STATE_QCANCEL; $q .= " order by p.name"; $result = $this->dbconn->Exec($q); $n = $result->numrows(); $a = 0; # echo $n." ".$q; while ( $a < $n ) { $p = new product($this->dbconn); $p->read_result($result,$a); $a++; if ( $p->use_ok()) { $this->plist[$p->id] = &$p; } unset($p); } $result->free(); } if ( $current_user->feature_ok(usetaskmanagement,PERM_SEE) ) { $q = "SELECT t.* from ". $this->dbconn->prefix."tasks t,". $this->dbconn->prefix ."taskworker w "; $pre = " WHERE "; if ($this->worker->id > 0) { $q .= $pre ." w.w_id in(". $this->worker->id; $q .= " ) "; $pre = " AND "; } $q .= $pre ." w.t_id = t.id"; $q .= " AND t.status != ".TASK_FINISH; $q .= " order by t.name"; $result = $this->dbconn->Exec($q); $n = $result->numrows(); $a = 0; # echo $n." ".$q; while ( $a < $n ) { $p = new task($this->dbconn); $p->read_result($result,$a); $a++; if ( $p->use_ok()) { $this->plist[$p->id] = &$p; } unset($p); } $result->free(); } } /** * set the Description */ function setDescription($value) { $this->setStrField("desc",$value,"Description"); return; } /** * set the Worker */ function setWorker($name) { $i = new tutos_address($this->dbconn); $i = $i->read($name,$i); if ( ($this->worker->id != $name) && ($i->id != -1) ) { $this->modified[] = array ( "field" => "TimetrackWorker", "old" => $this->worker->id , "new" => $name ); $this->worker = $i; } return; } /** * set the workday */ function setWorkday(&$value) { $this->setDateField("wday",$value,"Date"); return; } /** * set the Start */ function setStart(&$value) { $this->setDateTimeField("t_start",$value,"AppStart"); return; } /** * set the End */ function setEnd(&$value) { $this->setDateTimeField("t_end",$value,"AppEnd"); return; } /** * set the Currency */ function setCurrency($value) { $this->setStrField("currency",$value,"Currency"); return; } /** * set the costs per hour */ function setCph($value) { $this->setFloatField("cph",$value,"TTcph"); return; } /** * set the volume */ function setVolume($value) { $this->setFloatField("volume",$value,"TaskVolumeDone"); return; } /** * set the volume todo */ function setVolumeTodo($value) { $this->setFloatField("volume_todo",$value,"TaskVolumeTodo"); return; } /** * set the state */ function setState($value) { $this->setIntField("state",$value,"TTState"); return; } /** * set the Invoice */ function setInvoice($value) { $this->setIntField("inv_id",$value,"Invoice"); return; } /** * set the Invoice */ function setReference($value) { $this->setIntField("link_id",$value,"TimetrackRef"); return; } /** * Save Time Fraction to DB * * The norec parameter allows to create a timetrack from task.pink * without re entrance problems that may occur when timetrack tries * to save the ref task... */ function save($norec=0) { global $table,$tutos, $lang, $current_user; // We may have to compute the volume todo of this timetrack entry // This is the same as the task volume todo if( $this->volume_todo == -1 ) { if (isset($this->ref->volume_todo) && ($this->ref->volume_todo != -1) ) { $ref_todo = $this->ref->volume_todo; } elseif (isset($this->ref->volume) && ($this->ref->volume != -1) ) { // If no volume_todo has been set for the task, we consider // the planned volume as the volume_todo $ref_todo = $this->ref->volume; } else { // the diff will be zero $ref_todo = $this->volume; } // And the calculated volume_todo is the volume todo before this // timetrack entry, minus this timetrack entry volume... $volume_todo = $ref_todo - $this->volume; } else { // If a volume has been entered, we then just take it $volume_todo = $this->volume_todo; } $msg = ""; $q = new query($this->dbconn); $q->setTable($this->tablename); $q->addFV("link_id",$this->link_id,""); $q->addFV("adr_id",$this->worker->id,""); $q->addFV("volume",$this->volume,"FLOAT"); $q->addFV("volume_todo",$volume_todo,"FLOAT"); $q->addFV("description",$this->desc,"STRING",$table['timetrack']['description'][size]); $q->addFV("vtime",$this->wday,"DATETIME"); $q->addFV("state",$this->state,""); $q->addFV("invoice",$this->inv_id,""); $q->addFV("cph",$this->cph,"FLOAT"); $q->addFV("currency",$this->currency,"STRING",4); $q->addFV("t_start",$this->t_start,"DATETIME"); $q->addFV("t_end",$this->t_end,"DATETIME"); $this->save_custom_fields($q); if ( $this->id < 0 ) { $this->modified = array(); if ( isset($this->newid) ) { $this->id = $this->newid; $q->addFV("id",$this->id,""); } else { $this->id = $q->addFV("id",-1,"NEXTID"); acl_default($this,$current_user); # Prepare the history $this->modified[] = array ( "field" => "TimetrackCreate" , "old" => "" , "new" => $this->volume, "obj_id" => $this->link_id ); $this->modified[] = array ( "field" => "created" , "old" => $this->getType() , "new" => $this->id, "obj_id" => $this->id ); } $q->addFV("creation",$this->creation,"DATETIME"); $q->addFV("creator",$this->creator,"OBJ"); $query = $q->getInsert(); } else { $q->addWC("id",$this->id,""); $query = $q->getUpdate(); } $this->dbconn->Exec($query); if ( $norec == 0 && ($this->ref != -1) && ($this->ref->getType() == "task") ) { if ( $this->ref->r_start->notime == 1 ) { $this->ref->setRStart(new Datetime()); } // Task has to be considered running if( $this->ref->state == TASK_PRE ) { $this->ref->state = TASK_RUNNING; } // The volume todo has to be set on the task $this->ref->setVolumeTodo($volume_todo); $this->ref->save(); } $msg .= parent::save(); return $msg; } /** * delete timetrack entries for a object */ Function obj_delete(&$user,&$obj) { global $table; $msg = ""; # FIXME (mybe we should rebook the efforts to the user himself) !! $q = "DELETE FROM ". $obj->dbconn->prefix .$table['timetrack'][name]." WHERE link_id = ". $obj->id; $obj->dbconn->Exec($q); return $msg; } /** * Delete Timetrack fraction from DB */ function delete() { $msg = ""; $q = "DELETE FROM ". $this->tablename ." WHERE id = ". $this->id; $this->dbconn->Exec($q); $this->modified[] = array ( "field" => "TimetrackDel" , "old" => $this->volume , "new" => "0", "obj_id" => $this->link_id ); $msg .= parent::delete(); return $msg; } /** * Checks if the current user is allowed to delete this timetrack */ function del_ok () { if ( $this->ref != -1 ) { return $this->ref->del_ok(); } else { return 0; } } /** * */ function see_ok() { if ( $this->ref != -1 ) { return $this->ref->see_ok(); } else { return 0; } } /** * */ function mod_ok() { if ( $this->ref != -1 ) { return $this->ref->mod_ok(); } else { return 0; } } /** * Return a url that displays this timetrack fraction */ function getURL() { return "timetrack_overview.php?id=". $this->id; } /** * Return a url that allows modification of this timetrack fraction */ function getModURL() { return "timetrack_new.php?id=". $this->id; } /** * Return a url that deletes this timetrack fraction */ function getDelURL() { return "timetrack_del.php?id=". $this->id; } /** * Return a url that displays this timetrack fraction */ function getFullName() { return $this->volume ."@" . $this->wday->getDate(); } /** * Return a link to this timefragement */ function getLink($text = "") { global $lang; if ( empty($text) ) { $text = $this->getFullName(); } if ( $this->see_ok() ) { return makelink($this->getURL() , myentities($text) ,sprintf($lang['timetrack'] ." %s",$this->getFullName())); } else { return myentities($text); } } /** * Data of XML export */ function exportXML_body () { $r = parent::exportXML_body(); $r .= "". utf8_encode(htmlspecialchars($this->worker->id)) ."\n"; if ( $this->worker->id != null ) { $r .= "". utf8_encode(htmlspecialchars($this->worker->getFullName())) ."\n"; } $r .= "". utf8_encode(htmlspecialchars($this->ref->id)) ."\n"; if ( $this->ref->id != null ) { $r .= "". utf8_encode(htmlspecialchars($this->ref->getFullName())) ."\n"; } $r .= "". utf8_encode(htmlspecialchars($this->volume)) ."\n"; $r .= "". utf8_encode(htmlspecialchars($this->volume_todo)) ."\n"; if ( $this->t_start->notime != 1 ) { $r .= "". $this->t_start->exportXML_body() ."\n"; } if ( $this->t_end->notime != 1 ) { $r .= "". $this->t_end->exportXML_body() ."\n"; } $r .= "". utf8_encode(htmlspecialchars($this->desc)) ."\n"; $r .= "". utf8_encode(htmlspecialchars($this->invoice)) ."\n"; $r .= "". utf8_encode(htmlspecialchars($this->state)) ."\n"; $r .= "". utf8_encode(htmlspecialchars($this->cph)) ."\n"; $r .= "". utf8_encode(htmlspecialchars($this->cph * $this->volume)) ."\n"; $r .= "". utf8_encode(htmlspecialchars($this->currency)) ."\n"; if ( $this->wday->notime != 1 ) { $r .= "". $this->wday->exportXML_body() ."\n"; } return $r; } /** * Return a data as comma seperated values string */ function exportCSV() { global $lang; if ( $this->ref->id > 0 ) { $r = $this->ref->getFullName(); } else { $r = $lang['HistoryDeleted']; } if ( $this->worker->id > 0 ) { $w = $this->worker->getFullName(); } else { $w = $lang['HistoryDeleted']; } return $this->id .",\"". $w ."\",\"". $r ."\",\"". $this->desc ."\",". $this->volume .",". $this->cph .",\"". $this->currency ."\",". $this->state .",". $this->wday->getYYYYMMDD() ."\n"; } /** * Transfer reference ids according to given table */ function transfer_ids (&$trans) { if (isset($trans[$this->worker->id])) { $this->worker->id = $trans[$this->worker->id]; } if (isset($trans[$this->inv_id])) { $this->inv_id = $trans[$this->inv_id]; } if (isset($trans[$this->link_id])) { $this->link_id = $trans[$this->link_id]; } return; } /** * get the type of object */ function gettype () { return "timetrack"; } /** * get the type id of object */ function gettypeid () { return usetimetrack; } /* --------------------------------------------------------------------------- * The following methods are abstract factory functions for groups * which handle the membership list of an object * --------------------------------------------------------------------------- */ /** * Read a list of all timetrack elements */ function obj_read (&$obj) { global $table; if ( ! isset($obj->id) ) return; $obj->ttlist = array(); $q = "SELECT * from ". $obj->dbconn->prefix .$table['timetrack'][name]." where link_id = ". $obj->id ." order by vtime desc"; $r = $obj->dbconn->Exec($q); $n = $r->numrows(); $a = 0; while ($a < $n) { $tt = new timetrack($obj->dbconn); $tt->read_result($r,$a); if ( $tt->see_ok() ) { $obj->ttlist[$tt->id] = &$tt; } $a++; unset($tt); } $r->free(); return; } /** * create a link where a timetrack for work on the given object could be added */ function getaddlink (&$user,&$obj,$text = "") { global $lang; if ( $obj == -1 ) return; if (! is_object($obj) ) return; if ( $obj->id == -1 ) return; if (! $user->feature_ok(usetimetrack,PERM_NEW) ) return ""; if (! $obj->use_ok() ) return ""; if ($obj->gettype() == "product") { if ($obj->state == PROD_STATE_CANCEL) return ""; if ($obj->state == PROD_STATE_QCANCEL) return ""; } if ($obj->gettype() == "task") { if ($obj->state == TASK_FINISH) return ""; } if ($user->id == $obj->id ) { $x = array( url => "timetrack_new.php?mode=1&lid=". $obj->id, confirm => false, text => ($text == "" ? $lang['TTRecord']:$text), info => $lang['TTRecord'], category => array("timetrack","new","module") ); } else { $x = array( url => "timetrack_new.php?lid=". $obj->id, confirm => false, text => ($text == "" ? $lang['TimetrackCreate']:$text), info => sprintf($lang['TimetrackCreateI'], $obj->getFullName()), category => array("timetrack","new","module") ); } return $x; } /** * create a link to a overview page */ function getSelectLink (&$user,$text = "") { global $lang,$tutos; if ( ! $user->feature_ok(usetimetrack,PERM_SEL) ) { return; } return array( url => "timetrack_select.php", image => timetrack::getHtmlIcon(), text => ($text == "" ? $lang['Search']: $text), info => $lang['SearchForTT'], category => array("search","timetrack","obj") ); } } ?>