diff --git a/htdocs/admin/delais.php b/htdocs/admin/delais.php index 7239ee89a4b70b2ebb2e32d5ce5f563dd44e3517..6614b686fff713e3710c6706fa38ba0aae13e87d 100644 --- a/htdocs/admin/delais.php +++ b/htdocs/admin/delais.php @@ -39,7 +39,13 @@ $modules=array( 'img' => 'action' ) ), - 'propal' => array( + 'projet' => array( + array( + 'code' => 'MAIN_DELAY_TASKS_TODO', + 'img' => 'task' + ) + ), + 'propal' => array( array( 'code' => 'MAIN_DELAY_PROPALS_TO_CLOSE', 'img' => 'propal' diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index 68eb6994e5a40f1b840c3a2195a7198e2a1a20ac..0a44d660944766b6541557d8a55c09f20b930cf2 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -882,7 +882,7 @@ class ActionComm extends CommonObject */ function load_board($user) { - global $conf, $user, $langs; + global $conf, $langs; $sql = "SELECT a.id, a.datep as dp"; $sql.= " FROM (".MAIN_DB_PREFIX."actioncomm as a"; diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index cda28c80b376264125d7fa05fdb0290aa8c02319..b530b011d81d007a393bb2cc041564767df8235e 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -2465,7 +2465,7 @@ class Propal extends CommonObject */ function load_board($user,$mode) { - global $conf, $user, $langs; + global $conf, $langs; $clause = " WHERE"; diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 3417419f892d66a373ec37736eb6392487735e29..b1e4651eacea4ba8c98c2a3f258bbfe9e07779d0 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -2826,7 +2826,7 @@ class Commande extends CommonOrder */ function load_board($user) { - global $conf, $user, $langs; + global $conf, $langs; $clause = " WHERE"; diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index a37fbf78ed5d80586cae52e03d85e0d4be166bc0..91221118f2a6603ee0b6d7bd2e4cf146c0518916 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -3328,7 +3328,7 @@ class Facture extends CommonInvoice */ function load_board($user) { - global $conf, $user, $langs; + global $conf, $langs; $clause = " WHERE"; diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 91f96aabf5deec471d8a9836bbde10b659b85003..905c9fa08a2dc0bdfe50bcdabea682000470e5ea 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -1889,7 +1889,7 @@ class Contrat extends CommonObject */ function load_board($user,$mode) { - global $conf, $user, $langs; + global $conf, $langs; $this->from = " FROM ".MAIN_DB_PREFIX."contrat as c"; $this->from.= ", ".MAIN_DB_PREFIX."contratdet as cd"; diff --git a/htdocs/core/class/conf.class.php b/htdocs/core/class/conf.class.php index 35b22b1a14c26d0bfacf0d82e72cedca09fe4b11..0c1b5eb017935273ac9e362b88b64d9ad635b55b 100644 --- a/htdocs/core/class/conf.class.php +++ b/htdocs/core/class/conf.class.php @@ -497,7 +497,14 @@ class Conf $this->adherent->cotisation = new stdClass(); $this->adherent->cotisation->warning_delay=(isset($this->global->MAIN_DELAY_MEMBERS)?$this->global->MAIN_DELAY_MEMBERS:0)*24*60*60; } - if (isset($this->agenda)) $this->agenda->warning_delay=(isset($this->global->MAIN_DELAY_ACTIONS_TODO)?$this->global->MAIN_DELAY_ACTIONS_TODO:7)*24*60*60; + if (isset($this->agenda)) $this->agenda->warning_delay=(isset($this->global->MAIN_DELAY_ACTIONS_TODO)?$this->global->MAIN_DELAY_ACTIONS_TODO:7)*24*60*60; + if (isset($this->projet)) + { + $this->projet->warning_delay=(isset($this->global->MAIN_DELAY_PROJECT_TO_CLOSE)?$this->global->MAIN_DELAY_PROJECT_TO_CLOSE:7)*24*60*60; + $this->projet->task = new StdClass(); + $this->projet->task->warning_delay=(isset($this->global->MAIN_DELAY_TASKS_TODO)?$this->global->MAIN_DELAY_ACTIONS_TODO:7)*24*60*60; + } + if (isset($this->commande)) { $this->commande->client = new stdClass(); $this->commande->fournisseur = new stdClass(); diff --git a/htdocs/core/class/html.formother.class.php b/htdocs/core/class/html.formother.class.php index ce49b8ccd177d2cb932b3d23b6191c14e0aea0a0..c89844a91db814204eb4549b32772c6975f4e06f 100644 --- a/htdocs/core/class/html.formother.class.php +++ b/htdocs/core/class/html.formother.class.php @@ -1012,7 +1012,7 @@ class FormOther $selectboxlist.='<input type="hidden" name="userid" value="'.$user->id.'">'; $selectboxlist.='<input type="hidden" name="areacode" value="'.$areacode.'">'; $selectboxlist.='<input type="hidden" name="boxorder" value="'.$boxorder.'">'; - $selectboxlist.=Form::selectarray('boxcombo', $arrayboxtoactivatelabel, '', $langs->trans("ChooseBoxToAdd").'...', 0, 0, '', 0, 0, 0, 'ASC', '', 0, ' disabled hidden selected'); + $selectboxlist.=Form::selectarray('boxcombo', $arrayboxtoactivatelabel, '', $langs->trans("ChooseBoxToAdd").'...', 0, 0, '', 0, 0, 0, 'ASC', 'maxwidth200onsmartphone', 0, ' disabled hidden selected'); if (empty($conf->use_javascript_ajax)) $selectboxlist.=' <input type="submit" class="button" value="'.$langs->trans("AddBox").'">'; $selectboxlist.='</form>'; } diff --git a/htdocs/core/lib/project.lib.php b/htdocs/core/lib/project.lib.php index efbaa78557ea6cef02ea8c7a55560b565d1ee686..dcf838fbcf9a5ddab4890a45a9cbaca86ec382b9 100644 --- a/htdocs/core/lib/project.lib.php +++ b/htdocs/core/lib/project.lib.php @@ -395,7 +395,12 @@ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$t // Date end print '<td align="center">'; - print dol_print_date($lines[$i]->date_end,'dayhour'); + $taskstatic->projectstatus = $lines[$i]->projectstatus; + $taskstatic->progress = $lines[$i]->progress; + $taskstatic->fk_statut = $lines[$i]->status; + $taskstatic->datee = $lines[$i]->date_end; + print dol_print_date($lines[$i]->date_end,'dayhour'); + if ($taskstatic->hasDelay()) print img_warning($langs->trans("Late")); print '</td>'; $plannedworkloadoutputformat='allhourmin'; @@ -416,14 +421,6 @@ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$t //else print '--:--'; print '</td>'; - // Progress declared - print '<td align="right">'; - if ($lines[$i]->progress != '') - { - print $lines[$i]->progress.' %'; - } - print '</td>'; - // Time spent print '<td align="right">'; if ($showlineingray) print '<i>'; @@ -443,6 +440,14 @@ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$t } print '</td>'; + // Progress declared + print '<td align="right">'; + if ($lines[$i]->progress != '') + { + print $lines[$i]->progress.' %'; + } + print '</td>'; + // Tick to drag and drop if ($addordertick) { @@ -478,13 +483,13 @@ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$t print '<td align="right" class="nowrap liste_total">'; print convertSecondToTime($total_projectlinesa_planned, 'allhourmin'); print '</td>'; - print '<td></td>'; print '<td align="right" class="nowrap liste_total">'; print convertSecondToTime($total_projectlinesa_spent, 'allhourmin'); print '</td>'; print '<td align="right" class="nowrap liste_total">'; if ($total_projectlinesa_planned) print round(100 * $total_projectlinesa_spent / $total_projectlinesa_planned,2).' %'; print '</td>'; + print '<td></td>'; if ($addordertick) print '<td class="hideonsmartphone"></td>'; print '</tr>'; } @@ -963,12 +968,13 @@ function print_projecttasks_array($db, $form, $socid, $projectsListId, $mytasks= // Get list of project with calculation on tasks $sql2 = "SELECT p.rowid as projectid, p.ref, p.title, p.fk_soc, s.nom as socname, p.fk_user_creat, p.public, p.fk_statut as status, p.fk_opp_status as opp_status, p.opp_amount,"; + $sql2.= " p.dateo, p.datee,"; $sql2.= " COUNT(t.rowid) as nb, SUM(t.planned_workload) as planned_workload, SUM(t.planned_workload * t.progress / 100) as declared_progess_workload"; $sql2.= " FROM ".MAIN_DB_PREFIX."projet as p"; $sql2.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = p.fk_soc"; $sql2.= " LEFT JOIN ".MAIN_DB_PREFIX."projet_task as t ON p.rowid = t.fk_projet"; $sql2.= " WHERE p.rowid IN (".join(',',$arrayidofprojects).")"; - $sql2.= " GROUP BY p.rowid, p.ref, p.title, p.fk_soc, p.fk_user_creat, p.public, p.fk_statut, p.fk_opp_status, p.opp_amount"; + $sql2.= " GROUP BY p.rowid, p.ref, p.title, p.fk_soc, p.fk_user_creat, p.public, p.fk_statut, p.fk_opp_status, p.opp_amount, p.dateo, p.datee"; $sql2.= " ORDER BY p.title, p.ref"; $var=true; @@ -1011,12 +1017,17 @@ function print_projecttasks_array($db, $form, $socid, $projectsListId, $mytasks= $userAccess = $projectstatic->restrictedProjectArea($user); if ($userAccess >= 0) { + $projectstatic->ref=$objp->ref; + $projectstatic->statut = $objp->status; + $projectstatic->title = $objp->title; + $projectstatic->datee = $db->jdate($objp->datee); + $projectstatic->dateo = $db->jdate($objp->dateo); + $var=!$var; print "<tr ".$bc[$var].">"; print '<td>'; - $projectstatic->ref=$objp->ref; print $projectstatic->getNomUrl(1); - if (! in_array('projectlabel', $hiddenfields)) print ' - '.dol_trunc($objp->title,24); + if (! in_array('projectlabel', $hiddenfields)) print '<br>'.dol_trunc($objp->title,24); print '</td>'; print '<td>'; if ($objp->fk_soc > 0) @@ -1037,7 +1048,6 @@ function print_projecttasks_array($db, $form, $socid, $projectsListId, $mytasks= if ($code) print $langs->trans("OppStatus".$code); print '</td>'; } - $projectstatic->statut = $objp->status; if (empty($conf->global->PROJECT_HIDE_TASKS)) { print '<td align="right">'.$objp->nb.'</td>'; diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index a0184662065a2ab70a8464fa3e0f61baad59f2bd..2461acebfc26a2d830bf8cdd14370db471e97603 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -2347,7 +2347,7 @@ class CommandeFournisseur extends CommonOrder */ function load_board($user) { - global $conf, $user, $langs; + global $conf, $langs; $clause = " WHERE"; diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php index 64c988e74e1187b67603a546e8ee077e63f8cf1b..52c35040d2bcb64cfe157f4233afc5d61c3fc49a 100644 --- a/htdocs/fourn/class/fournisseur.facture.class.php +++ b/htdocs/fourn/class/fournisseur.facture.class.php @@ -1417,7 +1417,7 @@ class FactureFournisseur extends CommonInvoice */ function load_board($user) { - global $conf, $user, $langs; + global $conf, $langs; $sql = 'SELECT ff.rowid, ff.date_lim_reglement as datefin, ff.fk_statut'; $sql.= ' FROM '.MAIN_DB_PREFIX.'facture_fourn as ff'; diff --git a/htdocs/index.php b/htdocs/index.php index 1161848e0efe644a17903149c287be1b06cbb7bf..04e91b5110dafdd16fe3b583916257cb51ef11f1 100644 --- a/htdocs/index.php +++ b/htdocs/index.php @@ -36,6 +36,7 @@ $action=GETPOST('action'); $hookmanager->initHooks(array('index')); + /* * Actions */ @@ -342,22 +343,22 @@ if (! empty($conf->agenda->enabled) && $user->rights->agenda->myactions->read) $dashboardlines[] = $board->load_board($user); } -// Number of customer orders a deal -if (! empty($conf->commande->enabled) && $user->rights->commande->lire) +// Number of project opened +if (! empty($conf->projet->enabled) && $user->rights->projet->lire) { - include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; - $board=new Commande($db); + include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; + $board=new Project($db); - $dashboardlines[] = $board->load_board($user); + $dashboardlines[] = $board->load_board($user); } -// Number of suppliers orders a deal -if (! empty($conf->supplier_order->enabled) && $user->rights->fournisseur->commande->lire) +// Number of tasks to do (late) +if (! empty($conf->projet->enabled) && empty($conf->global->PROJECT_HIDE_TASKS) && $user->rights->projet->lire) { - include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php'; - $board=new CommandeFournisseur($db); + include_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php'; + $board=new Task($db); - $dashboardlines[] = $board->load_board($user); + $dashboardlines[] = $board->load_board($user); } // Number of commercial proposals opened (expired) @@ -371,6 +372,24 @@ if (! empty($conf->propal->enabled) && $user->rights->propale->lire) $dashboardlines[] = $board->load_board($user,"signed"); } +// Number of customer orders a deal +if (! empty($conf->commande->enabled) && $user->rights->commande->lire) +{ + include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; + $board=new Commande($db); + + $dashboardlines[] = $board->load_board($user); +} + +// Number of suppliers orders a deal +if (! empty($conf->supplier_order->enabled) && $user->rights->fournisseur->commande->lire) +{ + include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php'; + $board=new CommandeFournisseur($db); + + $dashboardlines[] = $board->load_board($user); +} + // Number of services enabled (delayed) if (! empty($conf->contrat->enabled) && $user->rights->contrat->lire) { @@ -482,6 +501,7 @@ foreach($valid_dashboardlines as $board) /*print '<td class="nowrap" align="right">'; print ' (>'.ceil($board->warning_delay).' '.$langs->trans("days").')'; print '</td>';*/ + if ($showweather) { print '<td class="nohover hideonsmartphone" rowspan="'.$rowspan.'" width="80" style="border-left: 1px solid #DDDDDD" align="center">'; diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index ccf11407bc3673e627e1d23a8531467f611d2d7e..13368cbfc06e471b8cabc7a1fac6b5ed0eb83009 100755 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -964,6 +964,7 @@ DelaysBeforeWarning=Delays before warning DelaysOfToleranceBeforeWarning=Tolerance delays before warning DelaysOfToleranceDesc=This screen allows you to define the tolerated delays before an alert is reported on screen with picto %s for each late element. Delays_MAIN_DELAY_ACTIONS_TODO=Delay tolerance (in days) before alert on planned events not yet realised +Delays_MAIN_DELAY_TASKS_TODO=Delay tolerance (in days) before alert on planned tasks not yet realised Delays_MAIN_DELAY_ORDERS_TO_PROCESS=Delay tolerance (in days) before alert on orders not yet processed Delays_MAIN_DELAY_SUPPLIER_ORDERS_TO_PROCESS=Delay tolerance (in days) before alert on suppliers orders not yet processed Delays_MAIN_DELAY_PROPALS_TO_CLOSE=Delay tolerance (in days) before alert on proposals to close diff --git a/htdocs/langs/en_US/projects.lang b/htdocs/langs/en_US/projects.lang index 4bb6a52af8bf5a72e6cab481c08c1acb7e6cc805..b60624df05af62ef343fd4828921ae988af843f6 100644 --- a/htdocs/langs/en_US/projects.lang +++ b/htdocs/langs/en_US/projects.lang @@ -29,6 +29,7 @@ OfficerProject=Officer project LastProjects=Last %s projects AllProjects=All projects OpenedProjects=Opened projects +OpenedTasks=Opened tasks OpportunitiesStatusForOpenedProjects=Opportunities amount of opened projects by status ProjectsList=List of projects ShowProject=Show project diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index 219736a62a7cbe48f09a94785094dd4adb8047d2..2c67d41549d8ea8e9780595ebd32fc806f6ddbf0 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -891,6 +891,10 @@ class Project extends CommonObject $label .= ($label?'<br>':'').'<b>' . $langs->trans('Ref') . ': </b>' . $this->ref; // The space must be after the : to not being explode when showing the title in img_picto if (! empty($this->title)) $label .= ($label?'<br>':'').'<b>' . $langs->trans('Label') . ': </b>' . $this->title; // The space must be after the : to not being explode when showing the title in img_picto + if (! empty($this->dateo)) + $label .= ($label?'<br>':'').'<b>' . $langs->trans('DateStart') . ': </b>' . dol_print_date($this->dateo, 'day'); // The space must be after the : to not being explode when showing the title in img_picto + if (! empty($this->datee)) + $label .= ($label?'<br>':'').'<b>' . $langs->trans('DateEnd') . ': </b>' . dol_print_date($this->datee, 'day'); // The space must be after the : to not being explode when showing the title in img_picto if ($moreinpopup) $label.='<br>'.$moreinpopup; $linkclose = '" title="'.dol_escape_htmltag($label, 1).'" class="classfortooltip">'; @@ -1558,6 +1562,70 @@ class Project extends CommonObject } } + + /** + * Load indicators for dashboard (this->nbtodo and this->nbtodolate) + * + * @param User $user Objet user + * @return WorkboardResponse|int <0 if KO, WorkboardResponse if OK + */ + function load_board($user) + { + global $conf, $langs; + + $mine=0; $socid=$user->societe_id; + + $projectsListId = $this->getProjectsAuthorizedForUser($user,$mine?$mine:($user->rights->projet->all->lire?2:0),1,$socid); + + $sql = "SELECT p.rowid, p.fk_statut as status, p.fk_opp_status, p.datee as datee"; + $sql.= " FROM (".MAIN_DB_PREFIX."projet as p"; + $sql.= ")"; + $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on p.fk_soc = s.rowid"; + if (! $user->rights->societe->client->voir && ! $socid) $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON sc.fk_soc = s.rowid"; + $sql.= " WHERE p.fk_statut = 1"; + $sql.= " AND p.entity IN (".getEntity('project').')'; + if ($mine || ! $user->rights->projet->all->lire) $sql.= " AND p.rowid IN (".$projectsListId.")"; + // No need to check company, as filtering of projects must be done by getProjectsAuthorizedForUser + //if ($socid || ! $user->rights->societe->client->voir) $sql.= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".$socid.")"; + if ($socid) $sql.= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".$socid.")"; + if (! $user->rights->societe->client->voir && ! $socid) $sql.= " AND ((s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id.") OR (s.rowid IS NULL))"; + + $resql=$this->db->query($sql); + if ($resql) + { + $project_static = new Project($this->db); + + $response = new WorkboardResponse(); + $response->warning_delay = $conf->projet->warning_delay/60/60/24; + $response->label = $langs->trans("OpenedProjects"); + if ($user->rights->projet->all->lire) $response->url = DOL_URL_ROOT.'/projet/index.php?search_status=1&mainmenu=project'; + else $response->url = DOL_URL_ROOT.'/projet/index.php?mode=mine&search_status=1&mainmenu=project'; + $response->img = img_object($langs->trans("Projects"),"project"); + + // This assignment in condition is not a bug. It allows walking the results. + while ($obj=$this->db->fetch_object($resql)) + { + $response->nbtodo++; + + $project_static->statut = $obj->status; + $project_static->opp_status = $obj->opp_status; + $project_static->datee = $this->db->jdate($obj->datee); + + if ($project_static->hasDelay()) { + $response->nbtodolate++; + } + } + + return $response; + } + else + { + $this->error=$this->db->error(); + return -1; + } + } + + /** * Function used to replace a thirdparty id with another one. * @@ -1574,6 +1642,24 @@ class Project extends CommonObject return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables); } + + /** + * Is the action delayed? + * + * @return bool + */ + public function hasDelay() + { + global $conf; + + if (! ($this->statut == 1)) { + return false; + } + + $now = dol_now(); + + return $this->datee < ($now - $conf->projet->warning_delay); + } } diff --git a/htdocs/projet/class/task.class.php b/htdocs/projet/class/task.class.php index ca8ed73e10de6ef0a3abdad7c6e049078d93a5fb..ab85f4a9ce6ebac7db4e55d80c70e2cd68df8b56 100644 --- a/htdocs/projet/class/task.class.php +++ b/htdocs/projet/class/task.class.php @@ -43,6 +43,7 @@ class Task extends CommonObject var $date_start; var $date_end; var $progress; + var $fk_statut; var $priority; var $fk_user_creat; var $fk_user_valid; @@ -535,13 +536,14 @@ class Task extends CommonObject $this->id=0; $this->fk_projet=''; - $this->ref=''; + $this->ref='TK01'; $this->fk_task_parent=''; - $this->title=''; + $this->title='Specimen task TK01'; $this->duration_effective=''; $this->fk_user_creat=''; - $this->statut=''; - $this->note=''; + $this->progress='25'; + $this->fk_statut=''; + $this->note='This is a specimen task not'; } /** @@ -569,8 +571,8 @@ class Task extends CommonObject //print $usert.'-'.$userp.'-'.$projectid.'-'.$socid.'-'.$mode.'<br>'; // List of tasks (does not care about permissions. Filtering will be done later) - $sql = "SELECT p.rowid as projectid, p.ref, p.title as plabel, p.public, p.fk_statut,"; - $sql.= " t.rowid as taskid, t.ref as taskref, t.label, t.description, t.fk_task_parent, t.duration_effective, t.progress,"; + $sql = "SELECT p.rowid as projectid, p.ref, p.title as plabel, p.public, p.fk_statut as projectstatus,"; + $sql.= " t.rowid as taskid, t.ref as taskref, t.label, t.description, t.fk_task_parent, t.duration_effective, t.progress, t.fk_statut as status,"; $sql.= " t.dateo as date_start, t.datee as date_end, t.planned_workload, t.rang"; if ($mode == 0) { @@ -674,13 +676,14 @@ class Task extends CommonObject $tasks[$i]->fk_project = $obj->projectid; $tasks[$i]->projectref = $obj->ref; $tasks[$i]->projectlabel = $obj->plabel; - $tasks[$i]->projectstatus = $obj->fk_statut; + $tasks[$i]->projectstatus = $obj->projectstatus; $tasks[$i]->label = $obj->label; $tasks[$i]->description = $obj->description; $tasks[$i]->fk_parent = $obj->fk_task_parent; $tasks[$i]->duration = $obj->duration_effective; $tasks[$i]->planned_workload= $obj->planned_workload; $tasks[$i]->progress = $obj->progress; + $tasks[$i]->fk_statut = $obj->status; $tasks[$i]->public = $obj->public; $tasks[$i]->date_start = $this->db->jdate($obj->date_start); $tasks[$i]->date_end = $this->db->jdate($obj->date_end); @@ -1542,4 +1545,91 @@ class Task extends CommonObject return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref); } + + /** + * Load indicators for dashboard (this->nbtodo and this->nbtodolate) + * + * @param User $user Objet user + * @return WorkboardResponse|int <0 if KO, WorkboardResponse if OK + */ + function load_board($user) + { + global $conf, $langs; + + $mine=0; $socid=$user->societe_id; + + $projectstatic = new Project($this->db); + $projectsListId = $projectstatic->getProjectsAuthorizedForUser($user,$mine,1,$socid); + + // List of tasks (does not care about permissions. Filtering will be done later) + $sql = "SELECT p.rowid as projectid, p.fk_statut as projectstatus,"; + $sql.= " t.rowid as taskid, t.progress as progress, t.fk_statut as status,"; + $sql.= " t.dateo as date_start, t.datee as datee"; + $sql.= " FROM ".MAIN_DB_PREFIX."projet as p"; + $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on p.fk_soc = s.rowid"; + if (! $user->rights->societe->client->voir && ! $socid) $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON sc.fk_soc = s.rowid"; + $sql.= ", ".MAIN_DB_PREFIX."projet_task as t"; + $sql.= " WHERE p.entity IN (".getEntity('project').')'; + $sql.= " AND p.fk_statut = 1"; + $sql.= " AND t.fk_projet = p.rowid"; + $sql.= " AND t.progress < 100"; // tasks to do + if ($mine || ! $user->rights->projet->all->lire) $sql.= " AND p.rowid IN (".$projectsListId.")"; + // No need to check company, as filtering of projects must be done by getProjectsAuthorizedForUser + //if ($socid || ! $user->rights->societe->client->voir) $sql.= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".$socid.")"; + if ($socid) $sql.= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".$socid.")"; + if (! $user->rights->societe->client->voir && ! $socid) $sql.= " AND ((s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id.") OR (s.rowid IS NULL))"; + //print $sql; + $resql=$this->db->query($sql); + if ($resql) + { + $task_static = new Task($this->db); + + $response = new WorkboardResponse(); + $response->warning_delay = $conf->projet->task->warning_delay/60/60/24; + $response->label = $langs->trans("OpenedTasks"); + if ($user->rights->projet->all->lire) $response->url = DOL_URL_ROOT.'/projet/tasks/list.php?mainmenu=project'; + else $response->url = DOL_URL_ROOT.'/projet/tasks/list.php?mode=mine&mainmenu=project'; + $response->img = img_object($langs->trans("Tasks"),"task"); + + // This assignment in condition is not a bug. It allows walking the results. + while ($obj=$this->db->fetch_object($resql)) + { + $response->nbtodo++; + + $task_static->projectstatus = $obj->projectstatus; + $task_static->progress = $obj->progress; + $task_static->fk_statut = $obj->status; + $task_static->datee = $this->db->jdate($obj->datee); + + if ($task_static->hasDelay()) { + $response->nbtodolate++; + } + } + + return $response; + } + else + { + $this->error=$this->db->error(); + return -1; + } + } + + /** + * Is the action delayed? + * + * @return bool + */ + public function hasDelay() + { + global $conf; + + if (! ($this->progress >= 0 && $this->progress < 100)) { + return false; + } + + $now = dol_now(); + + return ($this->datee > 0 && $this->datee < ($now - $conf->projet->task->warning_delay)); + } } diff --git a/htdocs/projet/index.php b/htdocs/projet/index.php index e1bc581453d4dc1136f3069f1c7bf67fed13cb2d..23d6df9be2b9dacb5ce699b896d3da53d340940e 100644 --- a/htdocs/projet/index.php +++ b/htdocs/projet/index.php @@ -197,7 +197,7 @@ print "</table>"; print '<br>'; -print_projecttasks_array($db,$form,$socid,$projectsListId,0,1,$listofoppstatus); +print_projecttasks_array($db, $form, $socid, $projectsListId, 0, 1, $listofoppstatus, array()); diff --git a/htdocs/projet/list.php b/htdocs/projet/list.php index d0a1ac2c5994ee46b665045f1c837c2fa1086756..5c9f102f772d188be487fdc863cccec83c7c4479 100644 --- a/htdocs/projet/list.php +++ b/htdocs/projet/list.php @@ -198,7 +198,7 @@ if ($search_user > 0) $sql.=", ".MAIN_DB_PREFIX."c_type_contact as tc"; } -$sql.= " WHERE p.entity = ".$conf->entity; +$sql.= " WHERE p.entity IN (".getEntity('project').')'; if ($mine || ! $user->rights->projet->all->lire) $sql.= " AND p.rowid IN (".$projectsListId.")"; // No need to check company, as filtering of projects must be done by getProjectsAuthorizedForUser //if ($socid || ! $user->rights->societe->client->voir) $sql.= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".$socid.")"; diff --git a/htdocs/projet/tasks.php b/htdocs/projet/tasks.php index eb95fd336241aedc1246aaadd9f03a0a96bdc03e..4abb9122eb2d849a500ef3b677633b86844eab83 100644 --- a/htdocs/projet/tasks.php +++ b/htdocs/projet/tasks.php @@ -431,9 +431,9 @@ else if ($id > 0 || ! empty($ref)) print '<td align="center">'.$langs->trans("DateStart").'</td>'; print '<td align="center">'.$langs->trans("DateEnd").'</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 align="right">'.$langs->trans("ProgressCalculated").'</td>'; + print '<td align="right">'.$langs->trans("ProgressDeclared").'</td>'; print '<td> </td>'; print "</tr>\n"; if (count($tasksarray) > 0) diff --git a/htdocs/projet/tasks/list.php b/htdocs/projet/tasks/list.php index d23617192b3a9970482c477c60f5eebbcb4e6731..fb2fcad6a382c034997788eda7d11d191fbd2f50 100644 --- a/htdocs/projet/tasks/list.php +++ b/htdocs/projet/tasks/list.php @@ -36,8 +36,8 @@ $id=GETPOST('id','int'); $search_all=GETPOST('search_all'); $search_project=GETPOST('search_project'); -if (! isset($_GET['search_status']) && ! isset($_POST['search_status'])) $search_status=1; -else $search_status=GETPOST('search_status'); +if (! isset($_GET['search_projectstatus']) && ! isset($_POST['search_projectstatus'])) $search_projectstatus=1; +else $search_projectstatus=GETPOST('search_projectstatus'); $search_task_ref=GETPOST('search_task_ref'); $search_task_label=GETPOST('search_task_label'); $search_project_user=GETPOST('search_project_user'); @@ -62,13 +62,13 @@ if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETP { $search_all=""; $search_project=""; - $search_status=""; + $search_projectstatus=""; $search_task_ref=""; $search_task_label=""; $search_task_user=-1; $search_project_user=-1; } -if (empty($search_status) && $search_status == '') $search_status=1; +if (empty($search_projectstatus) && $search_projectstatus == '') $search_projectstatus=1; // List of fields to search into when doing a "search in all" $fieldstosearchall = array( @@ -128,8 +128,8 @@ if ($search_all) $morewherefilter.=natural_search(array_keys($fieldstosea if ($search_task_ref) $morewherefilter.=natural_search('t.ref', $search_task_ref); if ($search_task_label) $morewherefilter.=natural_search('t.label', $search_task_label); -$tasksarray=$taskstatic->getTasksArray(0, 0, $projectstatic->id, $socid, 0, $search_project, $search_status, $morewherefilter, $search_project_user, 0); // We don't use filter on task user. Because sometimes a task is assigned but not the parent one and we want to show also parent, so filtering is done during output -$tasksrole=$taskstatic->getUserRolesForProjectsOrTasks(0, ($tuser->id?$tuser:null), $projectstatic->id, 0, $search_status); // We load also tasks limited to a particular user +$tasksarray=$taskstatic->getTasksArray(0, 0, $projectstatic->id, $socid, 0, $search_project, $search_projectstatus, $morewherefilter, $search_project_user, 0); // We don't use filter on task user. Because sometimes a task is assigned but not the parent one and we want to show also parent, so filtering is done during output +$tasksrole=$taskstatic->getUserRolesForProjectsOrTasks(0, ($tuser->id?$tuser:null), $projectstatic->id, 0, $search_projectstatus); // We load also tasks limited to a particular user print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">'; if ($optioncss != '') print '<input type="hidden" name="optioncss" value="'.$optioncss.'">'; @@ -185,9 +185,9 @@ print '<td align="right">'.$langs->trans("PlannedWorkload"); // TODO Replace 86400 and 7 to take account working hours per day and working day per weeks //print '<br>('.$langs->trans("DelayWorkHour").')'; print '</td>'; -print '<td align="right">'.$langs->trans("ProgressDeclared").'</td>'; print '<td align="right">'.$langs->trans("TimeSpent").'</td>'; print '<td align="right">'.$langs->trans("ProgressCalculated").'</td>'; +print '<td align="right">'.$langs->trans("ProgressDeclared").'</td>'; print "</tr>\n"; print '<tr class="liste_titre">'; @@ -197,7 +197,7 @@ print '</td>'; print '<td class="liste_titre">'; $listofstatus=array(-1=>' '); foreach($projectstatic->statuts_short as $key => $val) $listofstatus[$key]=$langs->trans($val); -print $form->selectarray('search_status', $listofstatus, $search_status); +print $form->selectarray('search_projectstatus', $listofstatus, $search_projectstatus); print '</td>'; print '<td class="liste_titre">'; print '<input type="text" class="flat" name="search_task_ref" value="'.dol_escape_htmltag($search_task_ref).'" size="4">'; diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 730b94db899b4d0cdba99654e05ba21a8a319da9..29f2294bd541afba0dda940a5455ae69e1e064bf 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -2382,7 +2382,13 @@ span.dashboardlineindicator, span.dashboardlineindicatorlate { font-size: 120%; font-weight: bold; } - +span.dashboardlineok { + color: #008800; +} +span.dashboardlineko { + color: #880000; + font-weight: bold; +} .boxtable { -moz-box-shadow: 3px 3px 4px #f4f4f4;