Work on timesheet module
This commit is contained in:
parent
fddbca50b1
commit
107a16ed75
176
htdocs/core/js/timesheet.js
Normal file
176
htdocs/core/js/timesheet.js
Normal file
@ -0,0 +1,176 @@
|
||||
//FIXME total not working
|
||||
/* Copyright (C) 2014 delcroip <delcroip@gmail.com>
|
||||
* Laurent Destailleur 2015 <eldy@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
/* Parse en input data for time entry into timesheet */
|
||||
function regexEvent(objet,evt,type)
|
||||
{
|
||||
console.log('regexEvent type='+type);
|
||||
switch(type)
|
||||
{
|
||||
case 'days':
|
||||
var regex= /^[0-9]{1}([.,]{1}[0-9]{1})?$/;
|
||||
|
||||
if(regex.test(objet.value) )
|
||||
{
|
||||
var tmp=objet.value.replace(',','.');
|
||||
if(tmp<=1.5){
|
||||
var tmpint=parseInt(tmp);
|
||||
if(tmp-tmpint>=0.5){
|
||||
objet.value= tmpint+0.5;
|
||||
}else{
|
||||
objet.value= tmpint;
|
||||
}
|
||||
}else{
|
||||
objet.value= '1.5';
|
||||
}
|
||||
}else{
|
||||
objet.value= '0';
|
||||
}
|
||||
break;
|
||||
case 'hours':
|
||||
var regex= /^[0-9]{1,2}:[0-9]{2}$/;
|
||||
var regex2=/^[0-9]{1,2}$/;
|
||||
if(!regex.test(objet.value))
|
||||
{
|
||||
if(regex2.test(objet.value))
|
||||
objet.value=objet.value+':00';
|
||||
else
|
||||
objet.value='';
|
||||
}
|
||||
/* alert(jQuery("#"+id).val()); */
|
||||
break;
|
||||
case 'timeChar':
|
||||
//var regex= /^[0-9:]{1}$/;
|
||||
//alert(event.charCode);
|
||||
var charCode = (evt.which) ? evt.which : event.keyCode;
|
||||
|
||||
if(((charCode >= 48) && (charCode <= 57)) || //num
|
||||
(charCode===46) || (charCode===8)||// comma & periode
|
||||
(charCode === 58) || (charCode==44) )// : & all charcode
|
||||
{
|
||||
// ((charCode>=96) && (charCode<=105)) || //numpad
|
||||
return true;
|
||||
|
||||
}else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function pad(n) {
|
||||
return (n < 10) ? ("0" + n) : n;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* function from http://www.timlabonne.com/2013/07/parsing-a-time-string-with-javascript/ */
|
||||
function parseTime(timeStr, dt)
|
||||
{
|
||||
if (!dt) {
|
||||
dt = new Date();
|
||||
}
|
||||
|
||||
var time = timeStr.match(/(\d+)(?::(\d\d))?\s*(p?)/i);
|
||||
if (!time) {
|
||||
return -1;
|
||||
}
|
||||
var hours = parseInt(time[1], 10);
|
||||
if (hours == 12 && !time[3]) {
|
||||
hours = 0;
|
||||
}
|
||||
else {
|
||||
hours += (hours < 12 && time[3]) ? 12 : 0;
|
||||
}
|
||||
|
||||
dt.setHours(hours);
|
||||
dt.setMinutes(parseInt(time[2], 10) || 0);
|
||||
dt.setSeconds(0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Update total. days = column nb staring from 0 */
|
||||
function updateTotal(days,mode)
|
||||
{
|
||||
console.log('updateTotal days='+days+' mode='+mode);
|
||||
if(mode=="hours")
|
||||
{
|
||||
var total = new Date(0);
|
||||
total.setHours(0);
|
||||
total.setMinutes(0);
|
||||
var nbline = document.getElementById('numberOfLines').value;
|
||||
for (var i=0;i<nbline;i++)
|
||||
{
|
||||
var id='task['+i+']['+days+']';
|
||||
var taskTime= new Date(0);
|
||||
var element=document.getElementById(id);
|
||||
if(element)
|
||||
{
|
||||
/* alert(element.value);*/
|
||||
if (element.value)
|
||||
{
|
||||
result=parseTime(element.value,taskTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
result=parseTime(element.innerHTML,taskTime);
|
||||
}
|
||||
if (result >= 0)
|
||||
{
|
||||
total.setHours(total.getHours()+taskTime.getHours());
|
||||
total.setMinutes(total.getMinutes()+taskTime.getMinutes());
|
||||
}
|
||||
}
|
||||
}
|
||||
document.getElementById('totalDay['+days+']').innerHTML = pad(total.getHours())+':'+pad(total.getMinutes());
|
||||
//addText(,total.getHours()+':'+total.getMinutes());
|
||||
}
|
||||
else
|
||||
{
|
||||
var total =0;
|
||||
var nbline = document.getElementById('numberOfLines').value;
|
||||
for (var i=0;i<nbline;i++)
|
||||
{
|
||||
var id='task['+i+']['+days+']';
|
||||
var taskTime= new Date(0);
|
||||
var element=document.getElementById(id);
|
||||
if(element)
|
||||
{
|
||||
if (element.value)
|
||||
{
|
||||
total+=parseInt(element.value);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
total+=parseInt(element.innerHTML);
|
||||
}
|
||||
}
|
||||
}
|
||||
document.getElementById('totalDay['+days+']').innerHTML = total;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -71,9 +71,9 @@ function print_actions_filter($form, $canedit, $status, $year, $month, $day, $sh
|
||||
if ($canedit)
|
||||
{
|
||||
print '<tr>';
|
||||
print '<td class="nowrap">';
|
||||
print '<td class="nowrap" style="padding-bottom: 2px;">';
|
||||
print $langs->trans("ActionsToDoBy").' ';
|
||||
print '</td><td class="nowrap maxwidthonsmartphone">';
|
||||
print '</td><td class="nowrap maxwidthonsmartphone" style="padding-bottom: 2px;">';
|
||||
print $form->select_dolusers($filtert, 'usertodo', 1, '', ! $canedit);
|
||||
if (empty($conf->dol_optimize_smallscreen)) print ' '.$langs->trans("or") . ' '.$langs->trans("Group").' ';
|
||||
print $form->select_dolgroups($usergroupid, 'usergroup', 1, '', ! $canedit);
|
||||
@ -83,16 +83,16 @@ function print_actions_filter($form, $canedit, $status, $year, $month, $day, $sh
|
||||
$formactions=new FormActions($db);
|
||||
|
||||
print '<tr>';
|
||||
print '<td class="nowrap">';
|
||||
print '<td class="nowrap" style="padding-bottom: 2px;">';
|
||||
print $langs->trans("Type");
|
||||
print ' </td><td class="nowrap maxwidthonsmartphone">';
|
||||
print ' </td><td class="nowrap maxwidthonsmartphone" style="padding-bottom: 2px;">';
|
||||
print $formactions->select_type_actions($actioncode, "actioncode", '', (empty($conf->global->AGENDA_USE_EVENT_TYPE) ? 1 : 0));
|
||||
print '</td></tr>';
|
||||
|
||||
print '<tr>';
|
||||
print '<td class="nowrap">';
|
||||
print '<td class="nowrap" style="padding-bottom: 2px;">';
|
||||
print $langs->trans("Status");
|
||||
print ' </td><td class="nowrap maxwidthonsmartphone">';
|
||||
print ' </td><td class="nowrap maxwidthonsmartphone" style="padding-bottom: 2px;">';
|
||||
$formactions->form_select_status_action('formaction',$status,1,'status',1,2);
|
||||
print '</td></tr>';
|
||||
}
|
||||
@ -100,9 +100,9 @@ function print_actions_filter($form, $canedit, $status, $year, $month, $day, $sh
|
||||
if (! empty($conf->societe->enabled) && $user->rights->societe->lire)
|
||||
{
|
||||
print '<tr>';
|
||||
print '<td class="nowrap">';
|
||||
print '<td class="nowrap" style="padding-bottom: 2px;">';
|
||||
print $langs->trans("ThirdParty").' ';
|
||||
print '</td><td class="nowrap maxwidthonsmartphone">';
|
||||
print '</td><td class="nowrap maxwidthonsmartphone" style="padding-bottom: 2px;">';
|
||||
print $form->select_thirdparty($socid, 'socid');
|
||||
print '</td></tr>';
|
||||
}
|
||||
@ -113,9 +113,9 @@ function print_actions_filter($form, $canedit, $status, $year, $month, $day, $sh
|
||||
$formproject=new FormProjets($db);
|
||||
|
||||
print '<tr>';
|
||||
print '<td class="nowrap">';
|
||||
print '<td class="nowrap" style="padding-bottom: 2px;">';
|
||||
print $langs->trans("Project").' ';
|
||||
print '</td><td class="nowrap maxwidthonsmartphone">';
|
||||
print '</td><td class="nowrap maxwidthonsmartphone" style="padding-bottom: 2px;">';
|
||||
$formproject->select_projects($socid?$socid:-1, $pid, 'projectid', 0);
|
||||
print '</td></tr>';
|
||||
}
|
||||
@ -124,7 +124,7 @@ function print_actions_filter($form, $canedit, $status, $year, $month, $day, $sh
|
||||
{
|
||||
// Filter on hours
|
||||
print '<tr>';
|
||||
print '<td class="nowrap">'.$langs->trans("WorkingTimeRange").'</td>';
|
||||
print '<td class="nowrap" style="padding-bottom: 2px;">'.$langs->trans("WorkingTimeRange").'</td>';
|
||||
print "<td class='nowrap maxwidthonsmartphone'>";
|
||||
print '<input type="number" class="short" name="begin_h" value="'.$begin_h.'" min="0" max="23">';
|
||||
if (empty($conf->dol_use_jmobile)) print ' - ';
|
||||
@ -140,10 +140,6 @@ function print_actions_filter($form, $canedit, $status, $year, $month, $day, $sh
|
||||
if (empty($conf->dol_use_jmobile)) print ' - ';
|
||||
print '<input type="number" class="short" name="end_d" value="'.$end_d.'" min="1" max="7">';
|
||||
print '</td></tr>';
|
||||
|
||||
print '<tr><td>'.$langs->trans("AgendaShowBirthdayEvents").' <input type="checkbox" id="check_birthday" name="check_birthday"></td></tr>';
|
||||
print '</table>';
|
||||
print '</td>';
|
||||
}
|
||||
|
||||
// Hooks
|
||||
|
||||
@ -550,7 +550,7 @@ function projectLinesPerTime(&$inc, $parent, $lines, &$level, &$projectsrole, &$
|
||||
print $taskstatic->getNomUrl(0);
|
||||
print "<br>";
|
||||
for ($k = 0 ; $k < $level ; $k++) print " ";
|
||||
print get_date_range($lines[$i]->date_start,$lines[$i]->date_end);
|
||||
print get_date_range($lines[$i]->date_start,$lines[$i]->date_end,'',$langs,0);
|
||||
print "</td>\n";
|
||||
|
||||
// Planned Workload
|
||||
@ -665,6 +665,9 @@ function projectLinesPerDay(&$inc, $parent, $lines, &$level, &$projectsrole, &$t
|
||||
{
|
||||
$var = !$var;
|
||||
$lastprojectid=$lines[$i]->fk_project;
|
||||
|
||||
$projectstatic->id = $lines[$i]->fk_project;
|
||||
$projectstatic->loadTimeSpent($datestart, $lines[$i]->id, $fuser->id);
|
||||
}
|
||||
|
||||
// If we want all or we have a role on task, we show it
|
||||
@ -673,7 +676,7 @@ function projectLinesPerDay(&$inc, $parent, $lines, &$level, &$projectsrole, &$t
|
||||
print "<tr ".$bc[$var].">\n";
|
||||
|
||||
// Project
|
||||
print "<td>";
|
||||
print '<td class="nowrap">';
|
||||
$projectstatic->id=$lines[$i]->fk_project;
|
||||
$projectstatic->ref=$lines[$i]->projectref;
|
||||
$projectstatic->public=$lines[$i]->public;
|
||||
@ -682,7 +685,7 @@ function projectLinesPerDay(&$inc, $parent, $lines, &$level, &$projectsrole, &$t
|
||||
print "</td>";
|
||||
|
||||
// Ref
|
||||
print '<td>';
|
||||
print '<td class="nowrap">';
|
||||
$taskstatic->id=$lines[$i]->id;
|
||||
$taskstatic->ref=($lines[$i]->ref?$lines[$i]->ref:$lines[$i]->id);
|
||||
print $taskstatic->getNomUrl(1);
|
||||
@ -696,7 +699,7 @@ function projectLinesPerDay(&$inc, $parent, $lines, &$level, &$projectsrole, &$t
|
||||
print $taskstatic->getNomUrl(0);
|
||||
print "<br>";
|
||||
for ($k = 0 ; $k < $level ; $k++) print " ";
|
||||
print get_date_range($lines[$i]->date_start,$lines[$i]->date_end);
|
||||
print get_date_range($lines[$i]->date_start,$lines[$i]->date_end,'',$langs,0);
|
||||
print "</td>\n";
|
||||
|
||||
// Planned Workload
|
||||
@ -711,6 +714,7 @@ function projectLinesPerDay(&$inc, $parent, $lines, &$level, &$projectsrole, &$t
|
||||
print '</td>';
|
||||
|
||||
// Time spent
|
||||
/*
|
||||
print '<td align="right">';
|
||||
if ($lines[$i]->duration)
|
||||
{
|
||||
@ -720,6 +724,7 @@ function projectLinesPerDay(&$inc, $parent, $lines, &$level, &$projectsrole, &$t
|
||||
}
|
||||
else print '--:--';
|
||||
print "</td>\n";
|
||||
*/
|
||||
|
||||
$disabledproject=1;$disabledtask=1;
|
||||
//print "x".$lines[$i]->fk_project;
|
||||
@ -737,27 +742,22 @@ function projectLinesPerDay(&$inc, $parent, $lines, &$level, &$projectsrole, &$t
|
||||
$disabledtask=1;
|
||||
}
|
||||
|
||||
// Fields to add new time
|
||||
print '<td align="right">';
|
||||
print $langs->trans("FeatureNotYetAvailable");
|
||||
/*
|
||||
print '<td class="nowrap" align="right">';
|
||||
$s='';
|
||||
$s.=$form->select_date('',$lines[$i]->id,0,0,2,"addtime",1,0,1,$disabledtask);
|
||||
$s.=' ';
|
||||
$s.=$form->select_duration($lines[$i]->id,'',$disabledtask,'text',0,1);
|
||||
$s.=' <input type="submit" class="button"'.($disabledtask?' disabled="disabled"':'').' value="'.$langs->trans("Add").'">';
|
||||
print $s;
|
||||
print '</td>';
|
||||
//var_dump($projectstatic->weekWorkLoad);
|
||||
|
||||
print '<td align="right">';
|
||||
if ((! $lines[$i]->public) && $disabledproject) print $form->textwithpicto('',$langs->trans("YouAreNotContactOfProject"));
|
||||
else if ($disabledtask) print $form->textwithpicto('',$langs->trans("TaskIsNotAffectedToYou"));
|
||||
print '</td>';
|
||||
*/
|
||||
|
||||
print '</td>';
|
||||
print "</tr>\n";
|
||||
// Fields to show current time
|
||||
$tableCell=''; $modeinput='hours';
|
||||
for ($idw = 0; $idw < 7; $idw++)
|
||||
{
|
||||
$dayWorkLoad = 0;
|
||||
$tableCell ='<td align="center">';
|
||||
$tableCell.='<input type="text" class="center" size="2" disabled="disabled" value="'.convertSecondToTime($dayWorkLoad,'allhourmin').'">+';
|
||||
$tableCell.='<input type="text" class="center" size="2" id="task['.$inc.']['.$idw.']" name="task['.$lines[$i]->id.']['.$idw.']" value="" cols="2" maxlength="5"';
|
||||
$tableCell.=' onkeypress="return regexEvent(this,event,\'timeChar\')"';
|
||||
$tableCell.= 'onblur="regexEvent(this,event,\''.$modeinput.'\');updateTotal('.$idw.',\''.$modeinput.'\')" />';
|
||||
$tableCell.='</td>';
|
||||
print $tableCell;
|
||||
}
|
||||
print "</tr>\n";
|
||||
}
|
||||
|
||||
$inc++;
|
||||
|
||||
@ -62,7 +62,7 @@ LastProspectContactDone=Contact done
|
||||
DateActionPlanned=Date event planned for
|
||||
DateActionDone=Date event done
|
||||
ActionAskedBy=Event reported by
|
||||
ActionAffectedTo=Event owned by
|
||||
ActionAffectedTo=Event assigned to
|
||||
ActionDoneBy=Event done by
|
||||
ActionUserAsk=Reported by
|
||||
ErrorStatusCantBeZeroIfStarted=If field '<b>Date done</b>' is filled, action is started (or finished), so field '<b>Status</b>' can't be 0%%.
|
||||
|
||||
@ -48,6 +48,8 @@ $socid=0;
|
||||
if ($user->societe_id > 0) $socid=$user->societe_id;
|
||||
$result = restrictedArea($user, 'projet', $projectid);
|
||||
|
||||
$now=dol_now();
|
||||
|
||||
|
||||
/*
|
||||
* Actions
|
||||
@ -94,7 +96,7 @@ $tasksrole=$taskstatic->getUserRolesForProjectsOrTasks(0,$user,($project->id?$pr
|
||||
//var_dump($taskrole);
|
||||
|
||||
|
||||
llxHeader("",$title,"");
|
||||
llxHeader("",$title,"",'','','',array('/core/js/timesheet.js'));
|
||||
|
||||
print_barre_liste($title, $page, $_SERVER["PHP_SELF"], "", $sortfield, $sortorder, "", $num);
|
||||
|
||||
@ -143,8 +145,17 @@ print '<td>'.$langs->trans("RefTask").'</td>';
|
||||
print '<td>'.$langs->trans("LabelTask").'</td>';
|
||||
print '<td align="right">'.$langs->trans("PlannedWorkload").'</td>';
|
||||
print '<td align="right">'.$langs->trans("ProgressDeclared").'</td>';
|
||||
print '<td align="right">'.$langs->trans("TimeSpent").'</td>';
|
||||
print '<td colspan="2" align="right">'.$langs->trans("xxx").'</td>';
|
||||
//print '<td align="right">'.$langs->trans("TimeSpent").'</td>';
|
||||
|
||||
$tmp=dol_getdate($now);
|
||||
$startdayarray=dol_get_first_day_week($tmp['mday'], $tmp['mon'], $tmp['year']);
|
||||
$startday=dol_mktime(12, 0, 0, $startdayarray['first_month'], $startdayarray['first_day'], $startdayarray['first_year']);
|
||||
|
||||
for($i=0;$i<7;$i++)
|
||||
{
|
||||
print '<td width="7%" align="center">'.dol_print_date($startday + ($i * 3600 * 24), '%a').'<br>'.dol_print_date($startday + ($i * 3600 * 24), 'day').'</td>';
|
||||
}
|
||||
|
||||
print "</tr>\n";
|
||||
|
||||
// By default, we can edit only tasks we are assigned to
|
||||
@ -154,6 +165,17 @@ if (count($tasksarray) > 0)
|
||||
{
|
||||
$j=0;
|
||||
projectLinesPerDay($j, 0, $tasksarray, $level, $projectsrole, $tasksrole, $mine, $restricteditformytask);
|
||||
|
||||
print '<tr class="liste_total">
|
||||
<td class="liste_total" colspan="5" align="right">'.$langs->trans("Total").'</td>
|
||||
<td class="liste_total" width="7%" align="center"><div id="totalDay[0]"> </div></td>
|
||||
<td class="liste_total" width="7%" align="center"><div id="totalDay[1]"> </div></td>
|
||||
<td class="liste_total" width="7%" align="center"><div id="totalDay[2]"> </div></td>
|
||||
<td class="liste_total" width="7%" align="center"><div id="totalDay[3]"> </div></td>
|
||||
<td class="liste_total" width="7%" align="center"><div id="totalDay[4]"> </div></td>
|
||||
<td class="liste_total" width="7%" align="center"><div id="totalDay[5]"> </div></td>
|
||||
<td class="liste_total" width="7%" align="center"><div id="totalDay[6]"> </div></td>
|
||||
</tr>';
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -161,8 +183,15 @@ else
|
||||
}
|
||||
print "</table>";
|
||||
|
||||
print '<input type="hidden" name="timestamp" value="1425423513"/>'."\n";
|
||||
print '<input type="hidden" id="numberOfLines" name="numberOfLines" value="'.count($tasksarray).'"/>'."\n";
|
||||
|
||||
dol_fiche_end();
|
||||
|
||||
print '<div class="center">';
|
||||
print '<input type="button" class="button" name="save" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
|
||||
print '</div>';
|
||||
|
||||
print '</form>';
|
||||
|
||||
|
||||
|
||||
@ -1432,5 +1432,51 @@ class Project extends CommonObject
|
||||
return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* load time spent into this->weekWorkLoad for all day of a week and task id
|
||||
*
|
||||
* @param int $datestart First day of week (use dol_get_first_day to find this date)
|
||||
* @param int $userid Time consumed per a particular user
|
||||
* @return int <0 if OK, >0 if KO
|
||||
*/
|
||||
public function loadTimeSpent($datestart,$taskid,$userid=0)
|
||||
{
|
||||
$error=0;
|
||||
|
||||
$sql = "SELECT ptt.rowid, ptt.task_duration, ptt.task_date";
|
||||
$sql.= " FROM ".MAIN_DB_PREFIX."projet_task_time AS ptt";
|
||||
$sql.= " WHERE ptt.fk_task='".$taskid."'";
|
||||
$sql.= " AND ptt.fk_user='".$userid."'";
|
||||
$sql .= "AND (ptt.task_date >= '".$this->db->idate($datestart)."' ";
|
||||
$sql .= "AND (ptt.task_date < '".$this->db->idate($datestart + 7 * 24 * 3600)."' ";
|
||||
$resql=$this->db->query($sql);
|
||||
if ($resql)
|
||||
{
|
||||
|
||||
$num = $this->db->num_rows($resql);
|
||||
$i = 0;
|
||||
// Loop on each record found, so each couple (project id, task id)
|
||||
while ($i < $num)
|
||||
{
|
||||
$obj=$this->db->fetch_object($resql);
|
||||
$day=$this->db->jdate($obj->task_date);
|
||||
//$day=(intval(date('w',strtotime($obj->task_date)))+1)%6;
|
||||
// if several tasktime in one day then only the last is used
|
||||
$this->weekWorkLoad[$day] += $obj->task_duration;
|
||||
$this->taskTimeId[$day]= ($obj->rowid)?($obj->rowid):0;
|
||||
$i++;
|
||||
}
|
||||
$this->db->free($resql);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->error="Error ".$this->db->lasterror();
|
||||
dol_syslog(get_class($this)."::fetch ".$this->error, LOG_ERR);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user