golden hour
/home/phakp/public_html/erp/core/lib
⬆️ Go Up
Upload
File/Folder
Size
Actions
accounting.lib.php
9.12 KB
Del
OK
admin.lib.php
66.42 KB
Del
OK
agenda.lib.php
18.22 KB
Del
OK
ajax.lib.php
31.31 KB
Del
OK
asset.lib.php
4.8 KB
Del
OK
bank.lib.php
12.94 KB
Del
OK
barcode.lib.php
15.26 KB
Del
OK
categories.lib.php
3.43 KB
Del
OK
company.lib.php
79.8 KB
Del
OK
contact.lib.php
4.51 KB
Del
OK
contract.lib.php
4.77 KB
Del
OK
cron.lib.php
4.69 KB
Del
OK
date.lib.php
37.78 KB
Del
OK
doc.lib.php
6.73 KB
Del
OK
doleditor.lib.php
3.93 KB
Del
OK
donation.lib.php
3.61 KB
Del
OK
ecm.lib.php
5.12 KB
Del
OK
emailing.lib.php
2.25 KB
Del
OK
eventorganization.lib.php
2.21 KB
Del
OK
expedition.lib.php
3.9 KB
Del
OK
expensereport.lib.php
5.6 KB
Del
OK
fichinter.lib.php
6.45 KB
Del
OK
files.lib.php
122.46 KB
Del
OK
fiscalyear.lib.php
1.86 KB
Del
OK
format_cards.lib.php
2.8 KB
Del
OK
fourn.lib.php
10.09 KB
Del
OK
functions.lib.php
429.39 KB
Del
OK
functions2.lib.php
91.31 KB
Del
OK
functions_ch.lib.php
3.66 KB
Del
OK
functionsnumtoword.lib.php
9.96 KB
Del
OK
geturl.lib.php
14.68 KB
Del
OK
holiday.lib.php
3.43 KB
Del
OK
hrm.lib.php
3.21 KB
Del
OK
images.lib.php
24.95 KB
Del
OK
import.lib.php
1.89 KB
Del
OK
intracommreport.lib.php
2.59 KB
Del
OK
invoice.lib.php
50.52 KB
Del
OK
invoice2.lib.php
9.16 KB
Del
OK
json.lib.php
10.92 KB
Del
OK
ldap.lib.php
5.37 KB
Del
OK
loan.lib.php
5.24 KB
Del
OK
mailmanspip.lib.php
1.24 KB
Del
OK
member.lib.php
10.23 KB
Del
OK
memory.lib.php
9.5 KB
Del
OK
modulebuilder.lib.php
13.56 KB
Del
OK
multicurrency.lib.php
2.07 KB
Del
OK
oauth.lib.php
5.73 KB
Del
OK
order.lib.php
9.82 KB
Del
OK
parsemd.lib.php
2.54 KB
Del
OK
payments.lib.php
17.44 KB
Del
OK
pdf.lib.php
104 KB
Del
OK
phpsessionindb.lib.php
8.28 KB
Del
OK
prelevement.lib.php
3.23 KB
Del
OK
price.lib.php
21.38 KB
Del
OK
product.lib.php
24.78 KB
Del
OK
project.lib.php
111.69 KB
Del
OK
propal.lib.php
9.38 KB
Del
OK
receiptprinter.lib.php
2.19 KB
Del
OK
reception.lib.php
4.69 KB
Del
OK
report.lib.php
3.84 KB
Del
OK
resource.lib.php
4.7 KB
Del
OK
salaries.lib.php
3.54 KB
Del
OK
security.lib.php
38.24 KB
Del
OK
security2.lib.php
18.07 KB
Del
OK
sendings.lib.php
16.55 KB
Del
OK
signature.lib.php
4.08 KB
Del
OK
stock.lib.php
3.6 KB
Del
OK
supplier_proposal.lib.php
4.82 KB
Del
OK
takepos.lib.php
2.18 KB
Del
OK
tax.lib.php
56.03 KB
Del
OK
ticket.lib.php
36.72 KB
Del
OK
treeview.lib.php
9.23 KB
Del
OK
trip.lib.php
1.98 KB
Del
OK
usergroups.lib.php
42.7 KB
Del
OK
vat.lib.php
2.6 KB
Del
OK
website.lib.php
53.39 KB
Del
OK
website2.lib.php
24.95 KB
Del
OK
ws.lib.php
3.34 KB
Del
OK
xcal.lib.php
16.9 KB
Del
OK
Edit: project.lib.php
<?php /* Copyright (C) 2006-2015 Laurent Destailleur <eldy@users.sourceforge.net> * Copyright (C) 2010 Regis Houssin <regis.houssin@inodbox.com> * Copyright (C) 2011 Juanjo Menent <jmenent@2byte.es> * Copyright (C) 2018-2021 Frédéric France <frederic.france@netlogic.fr> * * 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 <https://www.gnu.org/licenses/>. * or see https://www.gnu.org/ */ /** * \file htdocs/core/lib/project.lib.php * \brief Functions used by project module * \ingroup project */ require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; /** * Prepare array with list of tabs * * @param Project $project Object related to tabs * @param string $moreparam More param on url * @return array Array of tabs to show */ function project_prepare_head(Project $project, $moreparam = '') { global $db, $langs, $conf, $user; $h = 0; $head = array(); $head[$h][0] = DOL_URL_ROOT.'/projet/card.php?id='.((int) $project->id).($moreparam ? '&'.$moreparam : ''); $head[$h][1] = $langs->trans("Project"); $head[$h][2] = 'project'; $h++; $nbContacts = 0; // Enable caching of project count Contacts require_once DOL_DOCUMENT_ROOT.'/core/lib/memory.lib.php'; $cachekey = 'count_contacts_project_'.$project->id; $dataretrieved = dol_getcache($cachekey); if (!is_null($dataretrieved)) { $nbContacts = $dataretrieved; } else { $nbContacts = count($project->liste_contact(-1, 'internal')) + count($project->liste_contact(-1, 'external')); dol_setcache($cachekey, $nbContacts, 120); // If setting cache fails, this is not a problem, so we do not test result. } $head[$h][0] = DOL_URL_ROOT.'/projet/contact.php?id='.((int) $project->id).($moreparam ? '&'.$moreparam : ''); $head[$h][1] = $langs->trans("ProjectContact"); if ($nbContacts > 0) { $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbContacts.'</span>'; } $head[$h][2] = 'contact'; $h++; if (empty($conf->global->PROJECT_HIDE_TASKS)) { // Then tab for sub level of projet, i mean tasks $nbTasks = 0; // Enable caching of project count Tasks require_once DOL_DOCUMENT_ROOT.'/core/lib/memory.lib.php'; $cachekey = 'count_tasks_project_'.$project->id; $dataretrieved = dol_getcache($cachekey); if (!is_null($dataretrieved)) { $nbTasks = $dataretrieved; } else { require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php'; $taskstatic = new Task($db); $nbTasks = count($taskstatic->getTasksArray(0, 0, $project->id, 0, 0)); dol_setcache($cachekey, $nbTasks, 120); // If setting cache fails, this is not a problem, so we do not test result. } $head[$h][0] = DOL_URL_ROOT.'/projet/tasks.php?id='.((int) $project->id).($moreparam ? '&'.$moreparam : ''); $head[$h][1] = $langs->trans("Tasks"); if ($nbTasks > 0) { $head[$h][1] .= '<span class="badge marginleftonlyshort">'.($nbTasks).'</span>'; } $head[$h][2] = 'tasks'; $h++; $nbTimeSpent = 0; // Enable caching of project count Timespent $cachekey = 'count_timespent_project_'.$project->id; $dataretrieved = dol_getcache($cachekey); if (!is_null($dataretrieved)) { $nbTimeSpent = $dataretrieved; } else { $sql = "SELECT t.rowid"; //$sql .= " FROM ".MAIN_DB_PREFIX."projet_task_time as t, ".MAIN_DB_PREFIX."projet_task as pt, ".MAIN_DB_PREFIX."user as u"; //$sql .= " WHERE t.fk_user = u.rowid AND t.fk_task = pt.rowid"; $sql .= " FROM ".MAIN_DB_PREFIX."projet_task_time as t, ".MAIN_DB_PREFIX."projet_task as pt"; $sql .= " WHERE t.fk_task = pt.rowid"; $sql .= " AND pt.fk_projet =".((int) $project->id); $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); if ($obj) { $nbTimeSpent = 1; dol_setcache($cachekey, $nbTimeSpent, 120); // If setting cache fails, this is not a problem, so we do not test result. } } else { dol_print_error($db); } } $head[$h][0] = DOL_URL_ROOT.'/projet/tasks/time.php?withproject=1&projectid='.((int) $project->id).($moreparam ? '&'.$moreparam : ''); $head[$h][1] = $langs->trans("TimeSpent"); if ($nbTimeSpent > 0) { $head[$h][1] .= '<span class="badge marginleftonlyshort">...</span>'; } $head[$h][2] = 'timespent'; $h++; } if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) || !empty($conf->propal->enabled) || !empty($conf->commande->enabled) || !empty($conf->facture->enabled) || !empty($conf->contrat->enabled) || !empty($conf->ficheinter->enabled) || !empty($conf->agenda->enabled) || !empty($conf->deplacement->enabled) || !empty($conf->stock->enabled)) { $nbElements = 0; // Enable caching of thirdrparty count Contacts $cachekey = 'count_elements_project_'.$project->id; $dataretrieved = dol_getcache($cachekey); if (!is_null($dataretrieved)) { $nbElements = $dataretrieved; } else { if (!empty($conf->stock->enabled)) { $nbElements += $project->getElementCount('stock', 'entrepot', 'fk_project'); } if (!empty($conf->propal->enabled)) { $nbElements += $project->getElementCount('propal', 'propal'); } if (!empty($conf->commande->enabled)) { $nbElements += $project->getElementCount('order', 'commande'); } if (!empty($conf->facture->enabled)) { $nbElements += $project->getElementCount('invoice', 'facture'); } if (!empty($conf->facture->enabled)) { $nbElements += $project->getElementCount('invoice_predefined', 'facture_rec'); } if (!empty($conf->supplier_proposal->enabled)) { $nbElements += $project->getElementCount('proposal_supplier', 'supplier_proposal'); } if (!empty($conf->supplier_order->enabled)) { $nbElements += $project->getElementCount('order_supplier', 'commande_fournisseur'); } if (!empty($conf->supplier_invoice->enabled)) { $nbElements += $project->getElementCount('invoice_supplier', 'facture_fourn'); } if (!empty($conf->contrat->enabled)) { $nbElements += $project->getElementCount('contract', 'contrat'); } if (!empty($conf->ficheinter->enabled)) { $nbElements += $project->getElementCount('intervention', 'fichinter'); } if (!empty($conf->expedition->enabled)) { $nbElements += $project->getElementCount('shipping', 'expedition'); } if (!empty($conf->mrp->enabled)) { $nbElements += $project->getElementCount('mrp', 'mrp_mo', 'fk_project'); } if (!empty($conf->deplacement->enabled)) { $nbElements += $project->getElementCount('trip', 'deplacement'); } if (!empty($conf->expensereport->enabled)) { $nbElements += $project->getElementCount('expensereport', 'expensereport'); } if (!empty($conf->don->enabled)) { $nbElements += $project->getElementCount('donation', 'don'); } if (!empty($conf->loan->enabled)) { $nbElements += $project->getElementCount('loan', 'loan'); } if (!empty($conf->tax->enabled)) { $nbElements += $project->getElementCount('chargesociales', 'chargesociales'); } if (!empty($conf->projet->enabled)) { $nbElements += $project->getElementCount('project_task', 'projet_task'); } if (!empty($conf->stock->enabled)) { $nbElements += $project->getElementCount('stock_mouvement', 'stock'); } if (!empty($conf->salaries->enabled)) { $nbElements += $project->getElementCount('salaries', 'payment_salary'); } if (!empty($conf->banque->enabled)) { $nbElements += $project->getElementCount('variouspayment', 'payment_various'); } dol_setcache($cachekey, $nbElements, 120); // If setting cache fails, this is not a problem, so we do not test result. } $head[$h][0] = DOL_URL_ROOT.'/projet/element.php?id='.$project->id; $head[$h][1] = $langs->trans("ProjectOverview"); if ($nbElements > 0) { $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbElements.'</span>'; } $head[$h][2] = 'element'; $h++; } if ($conf->eventorganization->enabled && !empty($project->usage_organize_event)) { $langs->load('eventorganization'); $head[$h][0] = DOL_URL_ROOT . '/eventorganization/conferenceorbooth_list.php?projectid=' . $project->id; $head[$h][1] = $langs->trans("EventOrganization"); // Enable caching of conf or booth count $nbConfOrBooth = 0; require_once DOL_DOCUMENT_ROOT.'/core/lib/memory.lib.php'; $cachekey = 'count_conferenceorbooth_'.$project->id; $dataretrieved = dol_getcache($cachekey); if (!is_null($dataretrieved)) { $nbConfOrBooth = $dataretrieved; } else { require_once DOL_DOCUMENT_ROOT.'/eventorganization/class/conferenceorbooth.class.php'; $conforbooth=new ConferenceOrBooth($db); $result = $conforbooth->fetchAll('', '', 0, 0, array('t.fk_project'=>$project->id)); //, if (!is_array($result) && $result<0) { setEventMessages($conforbooth->error, $conforbooth->errors, 'errors'); } else { $nbConfOrBooth = count($result); } dol_setcache($cachekey, $nbConfOrBooth, 120); // If setting cache fails, this is not a problem, so we do not test result. } if ($nbConfOrBooth > 0) { $head[$h][1] .= '<span class="badge marginleftonlyshort">' . $nbConfOrBooth . '</span>'; } $head[$h][2] = 'eventorganisation'; $h++; } // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf, $langs, $project, $head, $h, 'project'); if (empty($conf->global->MAIN_DISABLE_NOTES_TAB)) { $nbNote = 0; if (!empty($project->note_private)) { $nbNote++; } if (!empty($project->note_public)) { $nbNote++; } $head[$h][0] = DOL_URL_ROOT.'/projet/note.php?id='.$project->id; $head[$h][1] = $langs->trans('Notes'); if ($nbNote > 0) { $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbNote.'</span>'; } $head[$h][2] = 'notes'; $h++; } // Attached files and Links $totalAttached = 0; // Enable caching of thirdrparty count attached files and links require_once DOL_DOCUMENT_ROOT.'/core/lib/memory.lib.php'; $cachekey = 'count_attached_project_'.$project->id; $dataretrieved = dol_getcache($cachekey); if (!is_null($dataretrieved)) { $totalAttached = $dataretrieved; } else { require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php'; $upload_dir = $conf->projet->dir_output."/".dol_sanitizeFileName($project->ref); $nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$')); $nbLinks = Link::count($db, $project->element, $project->id); $totalAttached = $nbFiles + $nbLinks; dol_setcache($cachekey, $totalAttached, 120); // If setting cache fails, this is not a problem, so we do not test result. } $head[$h][0] = DOL_URL_ROOT.'/projet/document.php?id='.$project->id; $head[$h][1] = $langs->trans('Documents'); if (($totalAttached) > 0) { $head[$h][1] .= '<span class="badge marginleftonlyshort">'.($totalAttached).'</span>'; } $head[$h][2] = 'document'; $h++; // Manage discussion if (!empty($conf->global->PROJECT_ALLOW_COMMENT_ON_PROJECT)) { $nbComments = 0; // Enable caching of thirdrparty count attached files and links require_once DOL_DOCUMENT_ROOT.'/core/lib/memory.lib.php'; $cachekey = 'count_attached_project_'.$project->id; $dataretrieved = dol_getcache($cachekey); if (!is_null($dataretrieved)) { $nbComments = $dataretrieved; } else { $nbComments = $project->getNbComments(); dol_setcache($cachekey, $nbComments, 120); // If setting cache fails, this is not a problem, so we do not test result. } $head[$h][0] = DOL_URL_ROOT.'/projet/comment.php?id='.$project->id; $head[$h][1] = $langs->trans("CommentLink"); if ($nbComments > 0) { $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbComments.'</span>'; } $head[$h][2] = 'project_comment'; $h++; } $head[$h][0] = DOL_URL_ROOT.'/projet/info.php?id='.$project->id; $head[$h][1] = $langs->trans("Events"); if (!empty($conf->agenda->enabled) && (!empty($user->rights->agenda->myactions->read) || !empty($user->rights->agenda->allactions->read))) { $head[$h][1] .= '/'; $head[$h][1] .= $langs->trans("Agenda"); } $head[$h][2] = 'agenda'; $h++; complete_head_from_modules($conf, $langs, $project, $head, $h, 'project', 'remove'); return $head; } /** * Prepare array with list of tabs * * @param Object $object Object related to tabs * @return array Array of tabs to show */ function task_prepare_head($object) { global $db, $langs, $conf, $user; $h = 0; $head = array(); $head[$h][0] = DOL_URL_ROOT.'/projet/tasks/task.php?id='.$object->id.(GETPOST('withproject') ? '&withproject=1' : ''); $head[$h][1] = $langs->trans("Task"); $head[$h][2] = 'task_task'; $h++; $nbContact = count($object->liste_contact(-1, 'internal')) + count($object->liste_contact(-1, 'external')); $head[$h][0] = DOL_URL_ROOT.'/projet/tasks/contact.php?id='.$object->id.(GETPOST('withproject') ? '&withproject=1' : ''); $head[$h][1] = $langs->trans("TaskRessourceLinks"); if ($nbContact > 0) { $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbContact.'</span>'; } $head[$h][2] = 'task_contact'; $h++; // Is there timespent ? $nbTimeSpent = 0; $sql = "SELECT t.rowid"; //$sql .= " FROM ".MAIN_DB_PREFIX."projet_task_time as t, ".MAIN_DB_PREFIX."projet_task as pt, ".MAIN_DB_PREFIX."user as u"; //$sql .= " WHERE t.fk_user = u.rowid AND t.fk_task = pt.rowid"; $sql .= " FROM ".MAIN_DB_PREFIX."projet_task_time as t"; $sql .= " WHERE t.fk_task = ".((int) $object->id); $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); if ($obj) { $nbTimeSpent = 1; } } else { dol_print_error($db); } $head[$h][0] = DOL_URL_ROOT.'/projet/tasks/time.php?id='.urlencode($object->id).(GETPOST('withproject') ? '&withproject=1' : ''); $head[$h][1] = $langs->trans("TimeSpent"); if ($nbTimeSpent > 0) { $head[$h][1] .= '<span class="badge marginleftonlyshort">...</span>'; } $head[$h][2] = 'task_time'; $h++; // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf, $langs, $object, $head, $h, 'task'); if (empty($conf->global->MAIN_DISABLE_NOTES_TAB)) { $nbNote = 0; if (!empty($object->note_private)) { $nbNote++; } if (!empty($object->note_public)) { $nbNote++; } $head[$h][0] = DOL_URL_ROOT.'/projet/tasks/note.php?id='.urlencode($object->id).(GETPOST('withproject') ? '&withproject=1' : ''); $head[$h][1] = $langs->trans('Notes'); if ($nbNote > 0) { $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbNote.'</span>'; } $head[$h][2] = 'task_notes'; $h++; } $head[$h][0] = DOL_URL_ROOT.'/projet/tasks/document.php?id='.$object->id.(GETPOST('withproject') ? '&withproject=1' : ''); $filesdir = $conf->projet->dir_output."/".dol_sanitizeFileName($object->project->ref).'/'.dol_sanitizeFileName($object->ref); include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; include_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php'; $nbFiles = count(dol_dir_list($filesdir, 'files', 0, '', '(\.meta|_preview.*\.png)$')); $nbLinks = Link::count($db, $object->element, $object->id); $head[$h][1] = $langs->trans('Documents'); if (($nbFiles + $nbLinks) > 0) { $head[$h][1] .= '<span class="badge marginleftonlyshort">'.($nbFiles + $nbLinks).'</span>'; } $head[$h][2] = 'task_document'; $h++; // Manage discussion if (!empty($conf->global->PROJECT_ALLOW_COMMENT_ON_TASK)) { $nbComments = $object->getNbComments(); $head[$h][0] = DOL_URL_ROOT.'/projet/tasks/comment.php?id='.$object->id.(GETPOST('withproject') ? '&withproject=1' : ''); $head[$h][1] = $langs->trans("CommentLink"); if ($nbComments > 0) { $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbComments.'</span>'; } $head[$h][2] = 'task_comment'; $h++; } complete_head_from_modules($conf, $langs, $object, $head, $h, 'task', 'remove'); return $head; } /** * Prepare array with list of tabs * * @param string $mode Mode * @param string $fuser Filter on user * @return array Array of tabs to show */ function project_timesheet_prepare_head($mode, $fuser = null) { global $langs, $conf, $user; $h = 0; $head = array(); $h = 0; $param = ''; $param .= ($mode ? '&mode='.$mode : ''); if (is_object($fuser) && $fuser->id > 0 && $fuser->id != $user->id) { $param .= '&search_usertoprocessid='.$fuser->id; } if (empty($conf->global->PROJECT_DISABLE_TIMESHEET_PERMONTH)) { $head[$h][0] = DOL_URL_ROOT."/projet/activity/permonth.php".($param ? '?'.$param : ''); $head[$h][1] = $langs->trans("InputPerMonth"); $head[$h][2] = 'inputpermonth'; $h++; } if (empty($conf->global->PROJECT_DISABLE_TIMESHEET_PERWEEK)) { $head[$h][0] = DOL_URL_ROOT."/projet/activity/perweek.php".($param ? '?'.$param : ''); $head[$h][1] = $langs->trans("InputPerWeek"); $head[$h][2] = 'inputperweek'; $h++; } if (empty($conf->global->PROJECT_DISABLE_TIMESHEET_PERTIME)) { $head[$h][0] = DOL_URL_ROOT."/projet/activity/perday.php".($param ? '?'.$param : ''); $head[$h][1] = $langs->trans("InputPerDay"); $head[$h][2] = 'inputperday'; $h++; } complete_head_from_modules($conf, $langs, null, $head, $h, 'project_timesheet'); complete_head_from_modules($conf, $langs, null, $head, $h, 'project_timesheet', 'remove'); return $head; } /** * Prepare array with list of tabs * * @return array Array of tabs to show */ function project_admin_prepare_head() { global $langs, $conf, $user; $h = 0; $head = array(); $h = 0; $head[$h][0] = DOL_URL_ROOT."/projet/admin/project.php"; $head[$h][1] = $langs->trans("Projects"); $head[$h][2] = 'project'; $h++; complete_head_from_modules($conf, $langs, null, $head, $h, 'project_admin'); $head[$h][0] = DOL_URL_ROOT."/projet/admin/project_extrafields.php"; $head[$h][1] = $langs->trans("ExtraFieldsProject"); $head[$h][2] = 'attributes'; $h++; $head[$h][0] = DOL_URL_ROOT.'/projet/admin/project_task_extrafields.php'; $head[$h][1] = $langs->trans("ExtraFieldsProjectTask"); $head[$h][2] = 'attributes_task'; $h++; if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) { $langs->load("members"); $head[$h][0] = DOL_URL_ROOT.'/projet/admin/website.php'; $head[$h][1] = $langs->trans("BlankSubscriptionForm"); $head[$h][2] = 'website'; $h++; } complete_head_from_modules($conf, $langs, null, $head, $h, 'project_admin', 'remove'); return $head; } /** * Show task lines with a particular parent * * @param string $inc Line number (start to 0, then increased by recursive call) * @param string $parent Id of parent project to show (0 to show all) * @param Task[] $lines Array of lines * @param int $level Level (start to 0, then increased/decrease by recursive call), or -1 to show all level in order of $lines without the recursive groupment feature. * @param string $var Color * @param int $showproject Show project columns * @param int $taskrole Array of roles of user for each tasks * @param int $projectsListId List of id of project allowed to user (string separated with comma) * @param int $addordertick Add a tick to move task * @param int $projectidfortotallink 0 or Id of project to use on total line (link to see all time consumed for project) * @param string $filterprogresscalc filter text * @param string $showbilltime Add the column 'TimeToBill' and 'TimeBilled' * @param array $arrayfields Array with displayed coloumn information * @return int Nb of tasks shown */ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$taskrole, $projectsListId = '', $addordertick = 0, $projectidfortotallink = 0, $filterprogresscalc = '', $showbilltime = 0, $arrayfields = array()) { global $user, $langs, $conf, $db, $hookmanager; global $projectstatic, $taskstatic, $extrafields; $lastprojectid = 0; $projectsArrayId = explode(',', $projectsListId); if ($filterprogresscalc !== '') { foreach ($lines as $key => $line) { if (!empty($line->planned_workload) && !empty($line->duration)) { $filterprogresscalc = str_replace(' = ', ' == ', $filterprogresscalc); if (!eval($filterprogresscalc)) { unset($lines[$key]); } } } $lines = array_values($lines); } $numlines = count($lines); // We declare counter as global because we want to edit them into recursive call global $total_projectlinesa_spent, $total_projectlinesa_planned, $total_projectlinesa_spent_if_planned, $total_projectlinesa_declared_if_planned, $total_projectlinesa_tobill, $total_projectlinesa_billed, $total_budget_amount; if ($level == 0) { $total_projectlinesa_spent = 0; $total_projectlinesa_planned = 0; $total_projectlinesa_spent_if_planned = 0; $total_projectlinesa_declared_if_planned = 0; $total_projectlinesa_tobill = 0; $total_projectlinesa_billed = 0; $total_budget_amount = 0; } for ($i = 0; $i < $numlines; $i++) { if ($parent == 0 && $level >= 0) { $level = 0; // if $level = -1, we dont' use sublevel recursion, we show all lines } // Process line // print "i:".$i."-".$lines[$i]->fk_project.'<br>'; if ($lines[$i]->fk_parent == $parent || $level < 0) { // if $level = -1, we dont' use sublevel recursion, we show all lines // Show task line. $showline = 1; $showlineingray = 0; // If there is filters to use if (is_array($taskrole)) { // If task not legitimate to show, search if a legitimate task exists later in tree if (!isset($taskrole[$lines[$i]->id]) && $lines[$i]->id != $lines[$i]->fk_parent) { // So search if task has a subtask legitimate to show $foundtaskforuserdeeper = 0; searchTaskInChild($foundtaskforuserdeeper, $lines[$i]->id, $lines, $taskrole); //print '$foundtaskforuserpeeper='.$foundtaskforuserdeeper.'<br>'; if ($foundtaskforuserdeeper > 0) { $showlineingray = 1; // We will show line but in gray } else { $showline = 0; // No reason to show line } } } else { // Caller did not ask to filter on tasks of a specific user (this probably means he want also tasks of all users, into public project // or into all other projects if user has permission to). if (empty($user->rights->projet->all->lire)) { // User is not allowed on this project and project is not public, so we hide line if (!in_array($lines[$i]->fk_project, $projectsArrayId)) { // Note that having a user assigned to a task into a project user has no permission on, should not be possible // because assignement on task can be done only on contact of project. // If assignement was done and after, was removed from contact of project, then we can hide the line. $showline = 0; } } } if ($showline) { // Break on a new project if ($parent == 0 && $lines[$i]->fk_project != $lastprojectid) { $var = !$var; $lastprojectid = $lines[$i]->fk_project; } print '<tr class="oddeven" id="row-'.$lines[$i]->id.'">'."\n"; $projectstatic->id = $lines[$i]->fk_project; $projectstatic->ref = $lines[$i]->projectref; $projectstatic->public = $lines[$i]->public; $projectstatic->title = $lines[$i]->projectlabel; $projectstatic->usage_bill_time = $lines[$i]->usage_bill_time; $projectstatic->status = $lines[$i]->projectstatus; $taskstatic->id = $lines[$i]->id; $taskstatic->ref = $lines[$i]->ref; $taskstatic->label = ($taskrole[$lines[$i]->id] ? $langs->trans("YourRole").': '.$taskrole[$lines[$i]->id] : ''); $taskstatic->projectstatus = $lines[$i]->projectstatus; $taskstatic->progress = $lines[$i]->progress; $taskstatic->fk_statut = $lines[$i]->status; $taskstatic->date_start = $lines[$i]->date_start; $taskstatic->date_end = $lines[$i]->date_end; $taskstatic->datee = $lines[$i]->date_end; // deprecated $taskstatic->planned_workload = $lines[$i]->planned_workload; $taskstatic->duration_effective = $lines[$i]->duration; $taskstatic->budget_amount = $lines[$i]->budget_amount; if ($showproject) { // Project ref print "<td>"; //if ($showlineingray) print '<i>'; if ($lines[$i]->public || in_array($lines[$i]->fk_project, $projectsArrayId) || !empty($user->rights->projet->all->lire)) { print $projectstatic->getNomUrl(1); } else { print $projectstatic->getNomUrl(1, 'nolink'); } //if ($showlineingray) print '</i>'; print "</td>"; // Project status print '<td>'; $projectstatic->statut = $lines[$i]->projectstatus; print $projectstatic->getLibStatut(2); print "</td>"; } // Ref of task if (count($arrayfields) > 0 && !empty($arrayfields['t.ref']['checked'])) { print '<td class="nowraponall">'; if ($showlineingray) { print '<i>'.img_object('', 'projecttask').' '.$lines[$i]->ref.'</i>'; } else { print $taskstatic->getNomUrl(1, 'withproject'); } print '</td>'; } // Title of task if (count($arrayfields) > 0 && !empty($arrayfields['t.label']['checked'])) { $labeltoshow = ''; if ($showlineingray) { $labeltoshow .= '<i>'; } //else print '<a href="'.DOL_URL_ROOT.'/projet/tasks/task.php?id='.$lines[$i]->id.'&withproject=1">'; for ($k = 0; $k < $level; $k++) { $labeltoshow .= '<div class="marginleftonly">'; } $labeltoshow .= dol_escape_htmltag($lines[$i]->label); for ($k = 0; $k < $level; $k++) { $labeltoshow .= '</div>'; } if ($showlineingray) { $labeltoshow .= '</i>'; } print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($labeltoshow).'">'; print $labeltoshow; print "</td>\n"; } if (count($arrayfields) > 0 && !empty($arrayfields['t.description']['checked'])) { print "<td>"; print $lines[$i]->description; print "</td>\n"; } // Date start if (count($arrayfields) > 0 && !empty($arrayfields['t.dateo']['checked'])) { print '<td class="center">'; print dol_print_date($lines[$i]->date_start, 'dayhour'); print '</td>'; } // Date end if (count($arrayfields) > 0 && !empty($arrayfields['t.datee']['checked'])) { print '<td class="center">'; print dol_print_date($lines[$i]->date_end, 'dayhour'); if ($taskstatic->hasDelay()) { print img_warning($langs->trans("Late")); } print '</td>'; } $plannedworkloadoutputformat = 'allhourmin'; $timespentoutputformat = 'allhourmin'; if (!empty($conf->global->PROJECT_PLANNED_WORKLOAD_FORMAT)) { $plannedworkloadoutputformat = $conf->global->PROJECT_PLANNED_WORKLOAD_FORMAT; } if (!empty($conf->global->PROJECT_TIMES_SPENT_FORMAT)) { $timespentoutputformat = $conf->global->PROJECT_TIME_SPENT_FORMAT; } // Planned Workload (in working hours) if (count($arrayfields) > 0 && !empty($arrayfields['t.planned_workload']['checked'])) { print '<td class="right">'; $fullhour = convertSecondToTime($lines[$i]->planned_workload, $plannedworkloadoutputformat); $workingdelay = convertSecondToTime($lines[$i]->planned_workload, 'all', 86400, 7); // TODO Replace 86400 and 7 to take account working hours per day and working day per weeks if ($lines[$i]->planned_workload != '') { print $fullhour; // TODO Add delay taking account of working hours per day and working day per week //if ($workingdelay != $fullhour) print '<br>('.$workingdelay.')'; } //else print '--:--'; print '</td>'; } // Time spent if (count($arrayfields) > 0 && !empty($arrayfields['t.duration_effective']['checked'])) { print '<td class="right">'; if ($showlineingray) { print '<i>'; } else { print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?id='.$lines[$i]->id.($showproject ? '' : '&withproject=1').'">'; } if ($lines[$i]->duration) { print convertSecondToTime($lines[$i]->duration, $timespentoutputformat); } else { print '--:--'; } if ($showlineingray) { print '</i>'; } else { print '</a>'; } print '</td>'; } // Progress calculated (Note: ->duration is time spent) if (count($arrayfields) > 0 && !empty($arrayfields['t.progress_calculated']['checked'])) { print '<td class="right">'; if ($lines[$i]->planned_workload || $lines[$i]->duration) { if ($lines[$i]->planned_workload) { print round(100 * $lines[$i]->duration / $lines[$i]->planned_workload, 2).' %'; } else { print '<span class="opacitymedium">'.$langs->trans('WorkloadNotDefined').'</span>'; } } print '</td>'; } // Progress declared if (count($arrayfields) > 0 && !empty($arrayfields['t.progress']['checked'])) { print '<td class="right">'; if ($lines[$i]->progress != '') { print getTaskProgressBadge($taskstatic); } print '</td>'; } // resume if (count($arrayfields) > 0 && !empty($arrayfields['t.progress_summary']['checked'])) { print '<td class="right">'; if ($lines[$i]->progress != '' && $lines[$i]->duration) { print getTaskProgressView($taskstatic, false, false); } print '</td>'; } if ($showbilltime) { // Time not billed if (count($arrayfields) > 0 && !empty($arrayfields['t.tobill']['checked'])) { print '<td class="right">'; if ($lines[$i]->usage_bill_time) { print convertSecondToTime($lines[$i]->tobill, 'allhourmin'); $total_projectlinesa_tobill += $lines[$i]->tobill; } else { print '<span class="opacitymedium">'.$langs->trans("NA").'</span>'; } print '</td>'; } // Time billed if (count($arrayfields) > 0 && !empty($arrayfields['t.billed']['checked'])) { print '<td class="right">'; if ($lines[$i]->usage_bill_time) { print convertSecondToTime($lines[$i]->billed, 'allhourmin'); $total_projectlinesa_billed += $lines[$i]->billed; } else { print '<span class="opacitymedium">'.$langs->trans("NA").'</span>'; } print '</td>'; } } if (count($arrayfields) > 0 && !empty($arrayfields['t.budget_amount']['checked'])) { print '<td class="center">'; print price($lines[$i]->budget_amount, 0, $langs, 1, 0, 0, $conf->currency); $total_budget_amount += $lines[$i]->budget_amount; print '</td>'; } // Contacts of task if (count($arrayfields) > 0 && !empty($arrayfields['c.assigned']['checked'])) { print '<td class="center">'; $ifisrt = 1; foreach (array('internal', 'external') as $source) { $tab = $lines[$i]->liste_contact(-1, $source); $numcontact = count($tab); if (!empty($numcontact)) { foreach ($tab as $contacttask) { //var_dump($contacttask); if ($source == 'internal') { $c = new User($db); } else { $c = new Contact($db); } $c->fetch($contacttask['id']); if (!empty($c->photo)) { if (get_class($c) == 'User') { print $c->getNomUrl(-2, '', 0, 0, 24, 1, '', ($ifisrt ? '' : 'notfirst')); } else { print $c->getNomUrl(-2, '', 0, '', -1, 0, ($ifisrt ? '' : 'notfirst')); } } else { if (get_class($c) == 'User') { print $c->getNomUrl(2, '', 0, 0, 24, 1, '', ($ifisrt ? '' : 'notfirst')); } else { print $c->getNomUrl(2, '', 0, '', -1, 0, ($ifisrt ? '' : 'notfirst')); } } $ifisrt = 0; } } } print '</td>'; } // Extra fields $extrafieldsobjectkey = $taskstatic->table_element; $obj = $lines[$i]; include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; // Fields from hook $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$lines[$i]); $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; // Tick to drag and drop print '<td class="tdlineupdown center"></td>'; print "</tr>\n"; if (!$showlineingray) { $inc++; } if ($level >= 0) { // Call sublevels $level++; if ($lines[$i]->id) { projectLinesa($inc, $lines[$i]->id, $lines, $level, $var, $showproject, $taskrole, $projectsListId, $addordertick, $projectidfortotallink, $filterprogresscalc, $showbilltime, $arrayfields); } $level--; } $total_projectlinesa_spent += $lines[$i]->duration; $total_projectlinesa_planned += $lines[$i]->planned_workload; if ($lines[$i]->planned_workload) { $total_projectlinesa_spent_if_planned += $lines[$i]->duration; } if ($lines[$i]->planned_workload) { $total_projectlinesa_declared_if_planned += $lines[$i]->planned_workload * $lines[$i]->progress / 100; } } } else { //$level--; } } if (($total_projectlinesa_planned > 0 || $total_projectlinesa_spent > 0 || $total_projectlinesa_tobill > 0 || $total_projectlinesa_billed > 0 || $total_budget_amount > 0) && $level <= 0) { print '<tr class="liste_total nodrag nodrop">'; print '<td class="liste_total">'.$langs->trans("Total").'</td>'; if ($showproject) { print '<td></td><td></td>'; } if (count($arrayfields) > 0 && !empty($arrayfields['t.label']['checked'])) { print '<td></td>'; } if (count($arrayfields) > 0 && !empty($arrayfields['t.dateo']['checked'])) { print '<td></td>'; } if (count($arrayfields) > 0 && !empty($arrayfields['t.datee']['checked'])) { print '<td></td>'; } if (count($arrayfields) > 0 && !empty($arrayfields['t.planned_workload']['checked'])) { print '<td class="nowrap liste_total right">'; print convertSecondToTime($total_projectlinesa_planned, 'allhourmin'); print '</td>'; } if (count($arrayfields) > 0 && !empty($arrayfields['t.duration_effective']['checked'])) { print '<td class="nowrap liste_total right">'; if ($projectidfortotallink > 0) { print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?projectid='.$projectidfortotallink.($showproject ? '' : '&withproject=1').'">'; } print convertSecondToTime($total_projectlinesa_spent, 'allhourmin'); if ($projectidfortotallink > 0) { print '</a>'; } print '</td>'; } if ($total_projectlinesa_planned) { $totalAverageDeclaredProgress = round(100 * $total_projectlinesa_declared_if_planned / $total_projectlinesa_planned, 2); $totalCalculatedProgress = round(100 * $total_projectlinesa_spent / $total_projectlinesa_planned, 2); // this conf is actually hidden, by default we use 10% for "be carefull or warning" $warningRatio = !empty($conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT) ? (1 + $conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT / 100) : 1.10; // define progress color according to time spend vs workload $progressBarClass = 'progress-bar-info'; $badgeClass = 'badge '; if ($totalCalculatedProgress > $totalAverageDeclaredProgress) { $progressBarClass = 'progress-bar-danger'; $badgeClass .= 'badge-danger'; } elseif ($totalCalculatedProgress * $warningRatio >= $totalAverageDeclaredProgress) { // warning if close at 1% $progressBarClass = 'progress-bar-warning'; $badgeClass .= 'badge-warning'; } else { $progressBarClass = 'progress-bar-success'; $badgeClass .= 'badge-success'; } } // Computed progress if (count($arrayfields) > 0 && !empty($arrayfields['t.progress_calculated']['checked'])) { print '<td class="nowrap liste_total right">'; if ($total_projectlinesa_planned) { print $totalCalculatedProgress.' %'; } print '</td>'; } // Declared progress if (count($arrayfields) > 0 && !empty($arrayfields['t.progress']['checked'])) { print '<td class="nowrap liste_total right">'; if ($total_projectlinesa_planned) { print '<span class="'.$badgeClass.'" >'.$totalAverageDeclaredProgress.' %</span>'; } print '</td>'; } // resume if (count($arrayfields) > 0 && !empty($arrayfields['t.progress_summary']['checked'])) { print '<td class="right">'; if ($total_projectlinesa_planned) { print '</span>'; print ' <div class="progress sm" title="'.$totalAverageDeclaredProgress.'%" >'; print ' <div class="progress-bar '.$progressBarClass.'" style="width: '.$totalAverageDeclaredProgress.'%"></div>'; print ' </div>'; print '</div>'; } print '</td>'; } if ($showbilltime) { if (count($arrayfields) > 0 && !empty($arrayfields['t.tobill']['checked'])) { print '<td class="nowrap liste_total right">'; print convertSecondToTime($total_projectlinesa_tobill, 'allhourmin'); print '</td>'; } if (count($arrayfields) > 0 && !empty($arrayfields['t.billed']['checked'])) { print '<td class="nowrap liste_total right">'; print convertSecondToTime($total_projectlinesa_billed, 'allhourmin'); print '</td>'; } } if (count($arrayfields) > 0 && !empty($arrayfields['t.budget_amount']['checked'])) { print '<td class="nowrap liste_total center">'; print price($total_budget_amount, 0, $langs, 1, 0, 0, $conf->currency); print '</td>'; } // Contacts of task for backward compatibility, if (!empty($conf->global->PROJECT_SHOW_CONTACTS_IN_LIST)) { print '<td></td>'; } // Contacts of task if (count($arrayfields) > 0 && !empty($arrayfields['c.assigned']['checked'])) { print '<td></td>'; } print '<td class=""></td>'; print '</tr>'; } return $inc; } /** * Output a task line into a pertime intput mode * * @param string $inc Line number (start to 0, then increased by recursive call) * @param string $parent Id of parent task to show (0 to show all) * @param User|null $fuser Restrict list to user if defined * @param Task[] $lines Array of lines * @param int $level Level (start to 0, then increased/decrease by recursive call) * @param string $projectsrole Array of roles user has on project * @param string $tasksrole Array of roles user has on task * @param string $mine Show only task lines I am assigned to * @param int $restricteditformytask 0=No restriction, 1=Enable add time only if task is a task i am affected to * @param int $preselectedday Preselected day * @param array $isavailable Array with data that say if user is available for several days for morning and afternoon * @param int $oldprojectforbreak Old project id of last project break * @return array Array with time spent for $fuser for each day of week on tasks in $lines and substasks */ function projectLinesPerAction(&$inc, $parent, $fuser, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, $preselectedday, &$isavailable, $oldprojectforbreak = 0) { global $conf, $db, $user, $langs; global $form, $formother, $projectstatic, $taskstatic, $thirdpartystatic; $lastprojectid = 0; $totalforeachline = array(); $workloadforid = array(); $lineswithoutlevel0 = array(); $numlines = count($lines); // Create a smaller array with sublevels only to be used later. This increase dramatically performances. if ($parent == 0) { // Always and only if at first level for ($i = 0; $i < $numlines; $i++) { if ($lines[$i]->fk_task_parent) { $lineswithoutlevel0[] = $lines[$i]; } } } if (empty($oldprojectforbreak)) { $oldprojectforbreak = (empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT) ? 0 : -1); // 0 to start break , -1 no break } //dol_syslog('projectLinesPerDay inc='.$inc.' preselectedday='.$preselectedday.' task parent id='.$parent.' level='.$level." count(lines)=".$numlines." count(lineswithoutlevel0)=".count($lineswithoutlevel0)); for ($i = 0; $i < $numlines; $i++) { if ($parent == 0) { $level = 0; } //if ($lines[$i]->fk_task_parent == $parent) //{ // If we want all or we have a role on task, we show it if (empty($mine) || !empty($tasksrole[$lines[$i]->id])) { //dol_syslog("projectLinesPerWeek Found line ".$i.", a qualified task (i have role or want to show all tasks) with id=".$lines[$i]->id." project id=".$lines[$i]->fk_project); // Break on a new project if ($parent == 0 && $lines[$i]->fk_project != $lastprojectid) { $lastprojectid = $lines[$i]->fk_project; if ($preselectedday) { $projectstatic->id = $lines[$i]->fk_project; } } if (empty($workloadforid[$projectstatic->id])) { if ($preselectedday) { $projectstatic->loadTimeSpent($preselectedday, 0, $fuser->id); // Load time spent from table projet_task_time for the project into this->weekWorkLoad and this->weekWorkLoadPerTask for all days of a week $workloadforid[$projectstatic->id] = 1; } } $projectstatic->id = $lines[$i]->fk_project; $projectstatic->ref = $lines[$i]->project_ref; $projectstatic->title = $lines[$i]->project_label; $projectstatic->public = $lines[$i]->public; $projectstatic->status = $lines[$i]->project_status; $taskstatic->id = $lines[$i]->task_id; $taskstatic->ref = ($lines[$i]->task_ref ? $lines[$i]->task_ref : $lines[$i]->task_id); $taskstatic->label = $lines[$i]->task_label; $taskstatic->date_start = $lines[$i]->date_start; $taskstatic->date_end = $lines[$i]->date_end; $thirdpartystatic->id = $lines[$i]->socid; $thirdpartystatic->name = $lines[$i]->thirdparty_name; $thirdpartystatic->email = $lines[$i]->thirdparty_email; if (empty($oldprojectforbreak) || ($oldprojectforbreak != -1 && $oldprojectforbreak != $projectstatic->id)) { print '<tr class="oddeven trforbreak nobold">'."\n"; print '<td colspan="11">'; print $projectstatic->getNomUrl(1, '', 0, $langs->transnoentitiesnoconv("YourRole").': '.$projectsrole[$lines[$i]->fk_project]); if ($projectstatic->title) { print ' - '; print $projectstatic->title; } print '</td>'; print '</tr>'; } if ($oldprojectforbreak != -1) { $oldprojectforbreak = $projectstatic->id; } print '<tr class="oddeven">'."\n"; // User /* print '<td class="nowrap">'; print $fuser->getNomUrl(1, 'withproject', 'time'); print '</td>'; */ // Project print "<td>"; if ($oldprojectforbreak == -1) { print $projectstatic->getNomUrl(1, '', 0, $langs->transnoentitiesnoconv("YourRole").': '.$projectsrole[$lines[$i]->fk_project]); print '<br>'.$projectstatic->title; } print "</td>"; // Thirdparty print '<td class="tdoverflowmax100">'; if ($thirdpartystatic->id > 0) { print $thirdpartystatic->getNomUrl(1, 'project', 10); } print '</td>'; // Ref print '<td>'; print '<!-- Task id = '.$lines[$i]->id.' -->'; for ($k = 0; $k < $level; $k++) { print " "; } print $taskstatic->getNomUrl(1, 'withproject', 'time'); // Label task print '<br>'; for ($k = 0; $k < $level; $k++) { print " "; } print $taskstatic->label; //print "<br>"; //for ($k = 0 ; $k < $level ; $k++) print " "; //print get_date_range($lines[$i]->date_start,$lines[$i]->date_end,'',$langs,0); print "</td>\n"; // Date print '<td class="center">'; print dol_print_date($lines[$i]->timespent_datehour, 'day'); print '</td>'; $disabledproject = 1; $disabledtask = 1; //print "x".$lines[$i]->fk_project; //var_dump($lines[$i]); //var_dump($projectsrole[$lines[$i]->fk_project]); // If at least one role for project if ($lines[$i]->public || !empty($projectsrole[$lines[$i]->fk_project]) || $user->rights->projet->all->creer) { $disabledproject = 0; $disabledtask = 0; } // If $restricteditformytask is on and I have no role on task, i disable edit if ($restricteditformytask && empty($tasksrole[$lines[$i]->id])) { $disabledtask = 1; } // Hour print '<td class="nowrap center">'; print dol_print_date($lines[$i]->timespent_datehour, 'hour'); print '</td>'; $cssonholiday = ''; if (!$isavailable[$preselectedday]['morning'] && !$isavailable[$preselectedday]['afternoon']) { $cssonholiday .= 'onholidayallday '; } elseif (!$isavailable[$preselectedday]['morning']) { $cssonholiday .= 'onholidaymorning '; } elseif (!$isavailable[$preselectedday]['afternoon']) { $cssonholiday .= 'onholidayafternoon '; } // Duration print '<td class="duration'.($cssonholiday ? ' '.$cssonholiday : '').' center">'; $dayWorkLoad = $lines[$i]->timespent_duration; $totalforeachline[$preselectedday] += $lines[$i]->timespent_duration; $alreadyspent = ''; if ($dayWorkLoad > 0) { $alreadyspent = convertSecondToTime($lines[$i]->timespent_duration, 'allhourmin'); } print convertSecondToTime($lines[$i]->timespent_duration, 'allhourmin'); $modeinput = 'hours'; print '<script type="text/javascript">'; print "jQuery(document).ready(function () {\n"; print " jQuery('.inputhour, .inputminute').bind('keyup', function(e) { updateTotal(0, '".$modeinput."') });"; print "})\n"; print '</script>'; print '</td>'; // Note print '<td class="center">'; print '<textarea name="'.$lines[$i]->id.'note" rows="'.ROWS_2.'" id="'.$lines[$i]->id.'note"'.($disabledtask ? ' disabled="disabled"' : '').'>'; print $lines[$i]->timespent_note; print '</textarea>'; print '</td>'; // Warning print '<td class="right">'; /*if ((! $lines[$i]->public) && $disabledproject) print $form->textwithpicto('',$langs->trans("UserIsNotContactOfProject")); elseif ($disabledtask) { $titleassigntask = $langs->trans("AssignTaskToMe"); if ($fuser->id != $user->id) $titleassigntask = $langs->trans("AssignTaskToUser", '...'); print $form->textwithpicto('',$langs->trans("TaskIsNotAssignedToUser", $titleassigntask)); }*/ print '</td>'; print "</tr>\n"; } //} //else //{ //$level--; //} } return $totalforeachline; } /** * Output a task line into a pertime intput mode * * @param string $inc Line number (start to 0, then increased by recursive call) * @param string $parent Id of parent task to show (0 to show all) * @param User|null $fuser Restrict list to user if defined * @param Task[] $lines Array of lines * @param int $level Level (start to 0, then increased/decrease by recursive call) * @param string $projectsrole Array of roles user has on project * @param string $tasksrole Array of roles user has on task * @param string $mine Show only task lines I am assigned to * @param int $restricteditformytask 0=No restriction, 1=Enable add time only if task is assigned to me, 2=Enable add time only if tasks is assigned to me and hide others * @param int $preselectedday Preselected day * @param array $isavailable Array with data that say if user is available for several days for morning and afternoon * @param int $oldprojectforbreak Old project id of last project break * @param array $arrayfields Array of additional column * @param Extrafields $extrafields Object extrafields * @return array Array with time spent for $fuser for each day of week on tasks in $lines and substasks */ function projectLinesPerDay(&$inc, $parent, $fuser, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, $preselectedday, &$isavailable, $oldprojectforbreak = 0, $arrayfields = array(), $extrafields = null) { global $conf, $db, $user, $langs; global $form, $formother, $projectstatic, $taskstatic, $thirdpartystatic; $lastprojectid = 0; $totalforeachday = array(); $workloadforid = array(); $lineswithoutlevel0 = array(); $numlines = count($lines); // Create a smaller array with sublevels only to be used later. This increase dramatically performances. if ($parent == 0) { // Always and only if at first level for ($i = 0; $i < $numlines; $i++) { if ($lines[$i]->fk_task_parent) { $lineswithoutlevel0[] = $lines[$i]; } } } if (empty($oldprojectforbreak)) { $oldprojectforbreak = (empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT) ? 0 : -1); // 0 to start break , -1 no break } $restrictBefore = null; if (! empty($conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS)) { require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; $restrictBefore = dol_time_plus_duree(dol_now(), - $conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS, 'm'); } //dol_syslog('projectLinesPerDay inc='.$inc.' preselectedday='.$preselectedday.' task parent id='.$parent.' level='.$level." count(lines)=".$numlines." count(lineswithoutlevel0)=".count($lineswithoutlevel0)); for ($i = 0; $i < $numlines; $i++) { if ($parent == 0) { $level = 0; } if ($lines[$i]->fk_task_parent == $parent) { $obj = &$lines[$i]; // To display extrafields // If we want all or we have a role on task, we show it if (empty($mine) || !empty($tasksrole[$lines[$i]->id])) { //dol_syslog("projectLinesPerWeek Found line ".$i.", a qualified task (i have role or want to show all tasks) with id=".$lines[$i]->id." project id=".$lines[$i]->fk_project); if ($restricteditformytask == 2 && empty($tasksrole[$lines[$i]->id])) { // we have no role on task and we request to hide such cases continue; } // Break on a new project if ($parent == 0 && $lines[$i]->fk_project != $lastprojectid) { $lastprojectid = $lines[$i]->fk_project; if ($preselectedday) { $projectstatic->id = $lines[$i]->fk_project; } } if (empty($workloadforid[$projectstatic->id])) { if ($preselectedday) { $projectstatic->loadTimeSpent($preselectedday, 0, $fuser->id); // Load time spent from table projet_task_time for the project into this->weekWorkLoad and this->weekWorkLoadPerTask for all days of a week $workloadforid[$projectstatic->id] = 1; } } $projectstatic->id = $lines[$i]->fk_project; $projectstatic->ref = $lines[$i]->projectref; $projectstatic->title = $lines[$i]->projectlabel; $projectstatic->public = $lines[$i]->public; $projectstatic->status = $lines[$i]->projectstatus; $taskstatic->id = $lines[$i]->id; $taskstatic->ref = ($lines[$i]->ref ? $lines[$i]->ref : $lines[$i]->id); $taskstatic->label = $lines[$i]->label; $taskstatic->date_start = $lines[$i]->date_start; $taskstatic->date_end = $lines[$i]->date_end; $thirdpartystatic->id = $lines[$i]->socid; $thirdpartystatic->name = $lines[$i]->thirdparty_name; $thirdpartystatic->email = $lines[$i]->thirdparty_email; if (empty($oldprojectforbreak) || ($oldprojectforbreak != -1 && $oldprojectforbreak != $projectstatic->id)) { $addcolspan = 0; if (!empty($arrayfields['t.planned_workload']['checked'])) { $addcolspan++; } if (!empty($arrayfields['t.progress']['checked'])) { $addcolspan++; } foreach ($arrayfields as $key => $val) { if ($val['checked'] && substr($key, 0, 5) == 'efpt.') { $addcolspan++; } } print '<tr class="oddeven trforbreak nobold">'."\n"; print '<td colspan="'.(7 + $addcolspan).'">'; print $projectstatic->getNomUrl(1, '', 0, '<strong>'.$langs->transnoentitiesnoconv("YourRole").':</strong> '.$projectsrole[$lines[$i]->fk_project]); if ($thirdpartystatic->id > 0) { print ' - '.$thirdpartystatic->getNomUrl(1); } if ($projectstatic->title) { print ' - '; print '<span class="secondary">'.$projectstatic->title.'</span>'; } /* $colspan=5+(empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)?0:2); print '<table class="">'; print '<tr class="liste_titre">'; // PROJECT fields if (! empty($arrayfields['p.fk_opp_status']['checked'])) print_liste_field_titre($arrayfields['p.fk_opp_status']['label'], $_SERVER["PHP_SELF"], 'p.fk_opp_status', "", $param, '', $sortfield, $sortorder, 'center '); if (! empty($arrayfields['p.opp_amount']['checked'])) print_liste_field_titre($arrayfields['p.opp_amount']['label'], $_SERVER["PHP_SELF"], 'p.opp_amount', "", $param, '', $sortfield, $sortorder, 'right '); if (! empty($arrayfields['p.opp_percent']['checked'])) print_liste_field_titre($arrayfields['p.opp_percent']['label'], $_SERVER["PHP_SELF"], 'p.opp_percent', "", $param, '', $sortfield, $sortorder, 'right '); if (! empty($arrayfields['p.budget_amount']['checked'])) print_liste_field_titre($arrayfields['p.budget_amount']['label'], $_SERVER["PHP_SELF"], 'p.budget_amount', "", $param, '', $sortfield, $sortorder, 'right '); if (! empty($arrayfields['p.usage_bill_time']['checked'])) print_liste_field_titre($arrayfields['p.usage_bill_time']['label'], $_SERVER["PHP_SELF"], 'p.usage_bill_time', "", $param, '', $sortfield, $sortorder, 'right '); $extrafieldsobjectkey='projet'; $extrafieldsobjectprefix='efp.'; include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; print '</tr>'; print '<tr>'; // PROJECT fields if (! empty($arrayfields['p.fk_opp_status']['checked'])) { print '<td class="nowrap">'; $code = dol_getIdFromCode($db, $lines[$i]->fk_opp_status, 'c_lead_status', 'rowid', 'code'); if ($code) print $langs->trans("OppStatus".$code); print "</td>\n"; } if (! empty($arrayfields['p.opp_amount']['checked'])) { print '<td class="nowrap">'; print price($lines[$i]->opp_amount, 0, $langs, 1, 0, -1, $conf->currency); print "</td>\n"; } if (! empty($arrayfields['p.opp_percent']['checked'])) { print '<td class="nowrap">'; print price($lines[$i]->opp_percent, 0, $langs, 1, 0).' %'; print "</td>\n"; } if (! empty($arrayfields['p.budget_amount']['checked'])) { print '<td class="nowrap">'; print price($lines[$i]->budget_amount, 0, $langs, 1, 0, 0, $conf->currency); print "</td>\n"; } if (! empty($arrayfields['p.usage_bill_time']['checked'])) { print '<td class="nowrap">'; print yn($lines[$i]->usage_bill_time); print "</td>\n"; } $extrafieldsobjectkey='projet'; $extrafieldsobjectprefix='efp.'; include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; print '</tr>'; print '</table>'; */ print '</td>'; print '</tr>'; } if ($oldprojectforbreak != -1) { $oldprojectforbreak = $projectstatic->id; } print '<tr class="oddeven" data-taskid="'.$lines[$i]->id.'">'."\n"; // User /* print '<td class="nowrap">'; print $fuser->getNomUrl(1, 'withproject', 'time'); print '</td>'; */ // Project if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { print "<td>"; if ($oldprojectforbreak == -1) { print $projectstatic->getNomUrl(1, '', 0, $langs->transnoentitiesnoconv("YourRole").': '.$projectsrole[$lines[$i]->fk_project]); } print "</td>"; } // Thirdparty if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { print '<td class="tdoverflowmax100">'; if ($thirdpartystatic->id > 0) { print $thirdpartystatic->getNomUrl(1, 'project', 10); } print '</td>'; } // Ref print '<td>'; print '<!-- Task id = '.$lines[$i]->id.' -->'; for ($k = 0; $k < $level; $k++) { print '<div class="marginleftonly">'; } print $taskstatic->getNomUrl(1, 'withproject', 'time'); // Label task print '<br>'; print '<span class="opacitymedium">'.$taskstatic->label.'</a>'; for ($k = 0; $k < $level; $k++) { print "</div>"; } print "</td>\n"; // TASK extrafields $extrafieldsobjectkey = 'projet_task'; $extrafieldsobjectprefix = 'efpt.'; include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; // Planned Workload if (!empty($arrayfields['t.planned_workload']['checked'])) { print '<td class="leftborder plannedworkload right">'; if ($lines[$i]->planned_workload) { print convertSecondToTime($lines[$i]->planned_workload, 'allhourmin'); } else { print '--:--'; } print '</td>'; } // Progress declared % if (!empty($arrayfields['t.progress']['checked'])) { print '<td class="right">'; print $formother->select_percent($lines[$i]->progress, $lines[$i]->id.'progress'); print '</td>'; } if (!empty($arrayfields['timeconsumed']['checked'])) { // Time spent by everybody print '<td class="right">'; // $lines[$i]->duration is a denormalised field = summ of time spent by everybody for task. What we need is time consummed by user if ($lines[$i]->duration) { print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?id='.$lines[$i]->id.'">'; print convertSecondToTime($lines[$i]->duration, 'allhourmin'); print '</a>'; } else { print '--:--'; } print "</td>\n"; // Time spent by user print '<td class="right">'; $tmptimespent = $taskstatic->getSummaryOfTimeSpent($fuser->id); if ($tmptimespent['total_duration']) { print convertSecondToTime($tmptimespent['total_duration'], 'allhourmin'); } else { print '--:--'; } print "</td>\n"; } $disabledproject = 1; $disabledtask = 1; //print "x".$lines[$i]->fk_project; //var_dump($lines[$i]); //var_dump($projectsrole[$lines[$i]->fk_project]); // If at least one role for project if ($lines[$i]->public || !empty($projectsrole[$lines[$i]->fk_project]) || $user->rights->projet->all->creer) { $disabledproject = 0; $disabledtask = 0; } // If $restricteditformytask is on and I have no role on task, i disable edit if ($restricteditformytask && empty($tasksrole[$lines[$i]->id])) { $disabledtask = 1; } if ($restrictBefore && $preselectedday < $restrictBefore) { $disabledtask = 1; } // Select hour print '<td class="nowraponall leftborder center minwidth150imp">'; $tableCell = $form->selectDate($preselectedday, $lines[$i]->id, 1, 1, 2, "addtime", 0, 0, $disabledtask); print $tableCell; print '</td>'; $cssonholiday = ''; if (!$isavailable[$preselectedday]['morning'] && !$isavailable[$preselectedday]['afternoon']) { $cssonholiday .= 'onholidayallday '; } elseif (!$isavailable[$preselectedday]['morning']) { $cssonholiday .= 'onholidaymorning '; } elseif (!$isavailable[$preselectedday]['afternoon']) { $cssonholiday .= 'onholidayafternoon '; } global $daytoparse; $tmparray = dol_getdate($daytoparse, true); // detail of current day $idw = ($tmparray['wday'] - (empty($conf->global->MAIN_START_WEEK) ? 0 : 1)); global $numstartworkingday, $numendworkingday; $cssweekend = ''; if ((($idw + 1) < $numstartworkingday) || (($idw + 1) > $numendworkingday)) { // This is a day is not inside the setup of working days, so we use a week-end css. $cssweekend = 'weekend'; } // Duration print '<td class="center duration'.($cssonholiday ? ' '.$cssonholiday : '').($cssweekend ? ' '.$cssweekend : '').'">'; $dayWorkLoad = $projectstatic->weekWorkLoadPerTask[$preselectedday][$lines[$i]->id]; $totalforeachday[$preselectedday] += $dayWorkLoad; $alreadyspent = ''; if ($dayWorkLoad > 0) { $alreadyspent = convertSecondToTime($dayWorkLoad, 'allhourmin'); } $idw = 0; $tableCell = ''; $tableCell .= '<span class="timesheetalreadyrecorded" title="texttoreplace"><input type="text" class="center" size="2" disabled id="timespent['.$inc.']['.$idw.']" name="task['.$lines[$i]->id.']['.$idw.']" value="'.$alreadyspent.'"></span>'; $tableCell .= '<span class="hideonsmartphone"> + </span>'; //$tableCell.=' '; $tableCell .= $form->select_duration($lines[$i]->id.'duration', '', $disabledtask, 'text', 0, 1); //$tableCell.=' <input type="submit" class="button"'.($disabledtask?' disabled':'').' value="'.$langs->trans("Add").'">'; print $tableCell; $modeinput = 'hours'; print '<script type="text/javascript">'; print "jQuery(document).ready(function () {\n"; print " jQuery('.inputhour, .inputminute').bind('keyup', function(e) { updateTotal(0, '".$modeinput."') });"; print "})\n"; print '</script>'; print '</td>'; // Note print '<td class="center">'; print '<textarea name="'.$lines[$i]->id.'note" rows="'.ROWS_2.'" id="'.$lines[$i]->id.'note"'.($disabledtask ? ' disabled="disabled"' : '').'>'; print '</textarea>'; print '</td>'; // Warning print '<td class="right">'; if ((!$lines[$i]->public) && $disabledproject) { print $form->textwithpicto('', $langs->trans("UserIsNotContactOfProject")); } elseif ($disabledtask) { $titleassigntask = $langs->trans("AssignTaskToMe"); if ($fuser->id != $user->id) { $titleassigntask = $langs->trans("AssignTaskToUser", '...'); } print $form->textwithpicto('', $langs->trans("TaskIsNotAssignedToUser", $titleassigntask)); } print '</td>'; print "</tr>\n"; } $inc++; $level++; if ($lines[$i]->id > 0) { //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level); //var_dump($totalforeachday); $ret = projectLinesPerDay($inc, $lines[$i]->id, $fuser, ($parent == 0 ? $lineswithoutlevel0 : $lines), $level, $projectsrole, $tasksrole, $mine, $restricteditformytask, $preselectedday, $isavailable, $oldprojectforbreak, $arrayfields, $extrafields); //var_dump('ret with parent='.$lines[$i]->id.' level='.$level); //var_dump($ret); foreach ($ret as $key => $val) { $totalforeachday[$key] += $val; } //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level.' + subtasks'); //var_dump($totalforeachday); } $level--; } else { //$level--; } } return $totalforeachday; } /** * Output a task line into a perday intput mode * * @param string $inc Line output identificator (start to 0, then increased by recursive call) * @param int $firstdaytoshow First day to show * @param User|null $fuser Restrict list to user if defined * @param string $parent Id of parent task to show (0 to show all) * @param Task[] $lines Array of lines (list of tasks but we will show only if we have a specific role on task) * @param int $level Level (start to 0, then increased/decrease by recursive call) * @param string $projectsrole Array of roles user has on project * @param string $tasksrole Array of roles user has on task * @param string $mine Show only task lines I am assigned to * @param int $restricteditformytask 0=No restriction, 1=Enable add time only if task is assigned to me, 2=Enable add time only if tasks is assigned to me and hide others * @param array $isavailable Array with data that say if user is available for several days for morning and afternoon * @param int $oldprojectforbreak Old project id of last project break * @param array $arrayfields Array of additional column * @param Extrafields $extrafields Object extrafields * @return array Array with time spent for $fuser for each day of week on tasks in $lines and substasks */ function projectLinesPerWeek(&$inc, $firstdaytoshow, $fuser, $parent, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, &$isavailable, $oldprojectforbreak = 0, $arrayfields = array(), $extrafields = null) { global $conf, $db, $user, $langs; global $form, $formother, $projectstatic, $taskstatic, $thirdpartystatic; $numlines = count($lines); $lastprojectid = 0; $workloadforid = array(); $totalforeachday = array(); $lineswithoutlevel0 = array(); // Create a smaller array with sublevels only to be used later. This increase dramatically performances. if ($parent == 0) { // Always and only if at first level for ($i = 0; $i < $numlines; $i++) { if ($lines[$i]->fk_task_parent) { $lineswithoutlevel0[] = $lines[$i]; } } } //dol_syslog('projectLinesPerWeek inc='.$inc.' firstdaytoshow='.$firstdaytoshow.' task parent id='.$parent.' level='.$level." count(lines)=".$numlines." count(lineswithoutlevel0)=".count($lineswithoutlevel0)); if (empty($oldprojectforbreak)) { $oldprojectforbreak = (empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT) ? 0 : -1); // 0 = start break, -1 = never break } $restrictBefore = null; if (! empty($conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS)) { require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; $restrictBefore = dol_time_plus_duree(dol_now(), - $conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS, 'm'); } for ($i = 0; $i < $numlines; $i++) { if ($parent == 0) { $level = 0; } if ($lines[$i]->fk_task_parent == $parent) { $obj = &$lines[$i]; // To display extrafields // If we want all or we have a role on task, we show it if (empty($mine) || !empty($tasksrole[$lines[$i]->id])) { //dol_syslog("projectLinesPerWeek Found line ".$i.", a qualified task (i have role or want to show all tasks) with id=".$lines[$i]->id." project id=".$lines[$i]->fk_project); if ($restricteditformytask == 2 && empty($tasksrole[$lines[$i]->id])) { // we have no role on task and we request to hide such cases continue; } // Break on a new project if ($parent == 0 && $lines[$i]->fk_project != $lastprojectid) { $lastprojectid = $lines[$i]->fk_project; $projectstatic->id = $lines[$i]->fk_project; } //var_dump('--- '.$level.' '.$firstdaytoshow.' '.$fuser->id.' '.$projectstatic->id.' '.$workloadforid[$projectstatic->id]); //var_dump($projectstatic->weekWorkLoadPerTask); if (empty($workloadforid[$projectstatic->id])) { $projectstatic->loadTimeSpent($firstdaytoshow, 0, $fuser->id); // Load time spent from table projet_task_time for the project into this->weekWorkLoad and this->weekWorkLoadPerTask for all days of a week $workloadforid[$projectstatic->id] = 1; } //var_dump($projectstatic->weekWorkLoadPerTask); //var_dump('--- '.$projectstatic->id.' '.$workloadforid[$projectstatic->id]); $projectstatic->id = $lines[$i]->fk_project; $projectstatic->ref = $lines[$i]->projectref; $projectstatic->title = $lines[$i]->projectlabel; $projectstatic->public = $lines[$i]->public; $projectstatic->thirdparty_name = $lines[$i]->thirdparty_name; $projectstatic->status = $lines[$i]->projectstatus; $taskstatic->id = $lines[$i]->id; $taskstatic->ref = ($lines[$i]->ref ? $lines[$i]->ref : $lines[$i]->id); $taskstatic->label = $lines[$i]->label; $taskstatic->date_start = $lines[$i]->date_start; $taskstatic->date_end = $lines[$i]->date_end; $thirdpartystatic->id = $lines[$i]->thirdparty_id; $thirdpartystatic->name = $lines[$i]->thirdparty_name; $thirdpartystatic->email = $lines[$i]->thirdparty_email; if (empty($oldprojectforbreak) || ($oldprojectforbreak != -1 && $oldprojectforbreak != $projectstatic->id)) { $addcolspan = 0; if (!empty($arrayfields['t.planned_workload']['checked'])) { $addcolspan++; } if (!empty($arrayfields['t.progress']['checked'])) { $addcolspan++; } foreach ($arrayfields as $key => $val) { if ($val['checked'] && substr($key, 0, 5) == 'efpt.') { $addcolspan++; } } print '<tr class="oddeven trforbreak nobold">'."\n"; print '<td colspan="'.(11 + $addcolspan).'">'; print $projectstatic->getNomUrl(1, '', 0, '<strong>'.$langs->transnoentitiesnoconv("YourRole").':</strong> '.$projectsrole[$lines[$i]->fk_project]); if ($thirdpartystatic->id > 0) { print ' - '.$thirdpartystatic->getNomUrl(1); } if ($projectstatic->title) { print ' - '; print '<span class="secondary">'.$projectstatic->title.'</span>'; } /*$colspan=5+(empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)?0:2); print '<table class="">'; print '<tr class="liste_titre">'; // PROJECT fields if (! empty($arrayfields['p.fk_opp_status']['checked'])) print_liste_field_titre($arrayfields['p.fk_opp_status']['label'], $_SERVER["PHP_SELF"], 'p.fk_opp_status', "", $param, '', $sortfield, $sortorder, 'center '); if (! empty($arrayfields['p.opp_amount']['checked'])) print_liste_field_titre($arrayfields['p.opp_amount']['label'], $_SERVER["PHP_SELF"], 'p.opp_amount', "", $param, '', $sortfield, $sortorder, 'right '); if (! empty($arrayfields['p.opp_percent']['checked'])) print_liste_field_titre($arrayfields['p.opp_percent']['label'], $_SERVER["PHP_SELF"], 'p.opp_percent', "", $param, '', $sortfield, $sortorder, 'right '); if (! empty($arrayfields['p.budget_amount']['checked'])) print_liste_field_titre($arrayfields['p.budget_amount']['label'], $_SERVER["PHP_SELF"], 'p.budget_amount', "", $param, '', $sortfield, $sortorder, 'right '); if (! empty($arrayfields['p.usage_bill_time']['checked'])) print_liste_field_titre($arrayfields['p.usage_bill_time']['label'], $_SERVER["PHP_SELF"], 'p.usage_bill_time', "", $param, '', $sortfield, $sortorder, 'right '); $extrafieldsobjectkey='projet'; $extrafieldsobjectprefix='efp.'; include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; print '</tr>'; print '<tr>'; // PROJECT fields if (! empty($arrayfields['p.fk_opp_status']['checked'])) { print '<td class="nowrap">'; $code = dol_getIdFromCode($db, $lines[$i]->fk_opp_status, 'c_lead_status', 'rowid', 'code'); if ($code) print $langs->trans("OppStatus".$code); print "</td>\n"; } if (! empty($arrayfields['p.opp_amount']['checked'])) { print '<td class="nowrap">'; print price($lines[$i]->opp_amount, 0, $langs, 1, 0, -1, $conf->currency); print "</td>\n"; } if (! empty($arrayfields['p.opp_percent']['checked'])) { print '<td class="nowrap">'; print price($lines[$i]->opp_percent, 0, $langs, 1, 0).' %'; print "</td>\n"; } if (! empty($arrayfields['p.budget_amount']['checked'])) { print '<td class="nowrap">'; print price($lines[$i]->budget_amount, 0, $langs, 1, 0, 0, $conf->currency); print "</td>\n"; } if (! empty($arrayfields['p.usage_bill_time']['checked'])) { print '<td class="nowrap">'; print yn($lines[$i]->usage_bill_time); print "</td>\n"; } $extrafieldsobjectkey='projet'; $extrafieldsobjectprefix='efp.'; include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; print '</tr>'; print '</table>'; */ print '</td>'; print '</tr>'; } if ($oldprojectforbreak != -1) { $oldprojectforbreak = $projectstatic->id; } print '<tr class="oddeven" data-taskid="'.$lines[$i]->id.'">'."\n"; // User /* print '<td class="nowrap">'; print $fuser->getNomUrl(1, 'withproject', 'time'); print '</td>'; */ // Project if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { print '<td class="nowrap">'; if ($oldprojectforbreak == -1) { print $projectstatic->getNomUrl(1, '', 0, $langs->transnoentitiesnoconv("YourRole").': '.$projectsrole[$lines[$i]->fk_project]); } print "</td>"; } // Thirdparty if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { print '<td class="tdoverflowmax100">'; if ($thirdpartystatic->id > 0) { print $thirdpartystatic->getNomUrl(1, 'project'); } print '</td>'; } // Ref print '<td class="nowrap">'; print '<!-- Task id = '.$lines[$i]->id.' -->'; for ($k = 0; $k < $level; $k++) { print '<div class="marginleftonly">'; } print $taskstatic->getNomUrl(1, 'withproject', 'time'); // Label task print '<br>'; print '<span class="opacitymedium">'.$taskstatic->label.'</span>'; for ($k = 0; $k < $level; $k++) { print "</div>"; } print "</td>\n"; // TASK extrafields $extrafieldsobjectkey = 'projet_task'; $extrafieldsobjectprefix = 'efpt.'; include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; // Planned Workload if (!empty($arrayfields['t.planned_workload']['checked'])) { print '<td class="leftborder plannedworkload right">'; if ($lines[$i]->planned_workload) { print convertSecondToTime($lines[$i]->planned_workload, 'allhourmin'); } else { print '--:--'; } print '</td>'; } if (!empty($arrayfields['t.progress']['checked'])) { // Progress declared % print '<td class="right">'; print $formother->select_percent($lines[$i]->progress, $lines[$i]->id.'progress'); print '</td>'; } if (!empty($arrayfields['timeconsumed']['checked'])) { // Time spent by everybody print '<td class="right">'; // $lines[$i]->duration is a denormalised field = summ of time spent by everybody for task. What we need is time consummed by user if ($lines[$i]->duration) { print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?id='.$lines[$i]->id.'">'; print convertSecondToTime($lines[$i]->duration, 'allhourmin'); print '</a>'; } else { print '--:--'; } print "</td>\n"; // Time spent by user print '<td class="right">'; $tmptimespent = $taskstatic->getSummaryOfTimeSpent($fuser->id); if ($tmptimespent['total_duration']) { print convertSecondToTime($tmptimespent['total_duration'], 'allhourmin'); } else { print '--:--'; } print "</td>\n"; } $disabledproject = 1; $disabledtask = 1; //print "x".$lines[$i]->fk_project; //var_dump($lines[$i]); //var_dump($projectsrole[$lines[$i]->fk_project]); // If at least one role for project if ($lines[$i]->public || !empty($projectsrole[$lines[$i]->fk_project]) || $user->rights->projet->all->creer) { $disabledproject = 0; $disabledtask = 0; } // If $restricteditformytask is on and I have no role on task, i disable edit if ($restricteditformytask && empty($tasksrole[$lines[$i]->id])) { $disabledtask = 1; } //var_dump($projectstatic->weekWorkLoadPerTask); // Fields to show current time $tableCell = ''; $modeinput = 'hours'; for ($idw = 0; $idw < 7; $idw++) { $tmpday = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); $cssonholiday = ''; if (!$isavailable[$tmpday]['morning'] && !$isavailable[$tmpday]['afternoon']) { $cssonholiday .= 'onholidayallday '; } elseif (!$isavailable[$tmpday]['morning']) { $cssonholiday .= 'onholidaymorning '; } elseif (!$isavailable[$tmpday]['afternoon']) { $cssonholiday .= 'onholidayafternoon '; } $tmparray = dol_getdate($tmpday); $dayWorkLoad = $projectstatic->weekWorkLoadPerTask[$tmpday][$lines[$i]->id]; $totalforeachday[$tmpday] += $dayWorkLoad; $alreadyspent = ''; if ($dayWorkLoad > 0) { $alreadyspent = convertSecondToTime($dayWorkLoad, 'allhourmin'); } $alttitle = $langs->trans("AddHereTimeSpentForDay", $tmparray['day'], $tmparray['mon']); global $numstartworkingday, $numendworkingday; $cssweekend = ''; if (($idw + 1 < $numstartworkingday) || ($idw + 1 > $numendworkingday)) { // This is a day is not inside the setup of working days, so we use a week-end css. $cssweekend = 'weekend'; } $disabledtaskday = $disabledtask; if (! $disabledtask && $restrictBefore && $tmpday < $restrictBefore) { $disabledtaskday = 1; } $tableCell = '<td class="center hide'.$idw.($cssonholiday ? ' '.$cssonholiday : '').($cssweekend ? ' '.$cssweekend : '').'">'; //$tableCell .= 'idw='.$idw.' '.$conf->global->MAIN_START_WEEK.' '.$numstartworkingday.'-'.$numendworkingday; $placeholder = ''; if ($alreadyspent) { $tableCell .= '<span class="timesheetalreadyrecorded" title="texttoreplace"><input type="text" class="center smallpadd" size="2" disabled id="timespent['.$inc.']['.$idw.']" name="task['.$lines[$i]->id.']['.$idw.']" value="'.$alreadyspent.'"></span>'; //$placeholder=' placeholder="00:00"'; //$tableCell.='+'; } $tableCell .= '<input type="text" alt="'.($disabledtaskday ? '' : $alttitle).'" title="'.($disabledtaskday ? '' : $alttitle).'" '.($disabledtaskday ? 'disabled' : $placeholder).' class="center smallpadd" size="2" id="timeadded['.$inc.']['.$idw.']" name="task['.$lines[$i]->id.']['.$idw.']" value="" cols="2" maxlength="5"'; $tableCell .= ' onkeypress="return regexEvent(this,event,\'timeChar\')"'; $tableCell .= ' onkeyup="updateTotal('.$idw.',\''.$modeinput.'\')"'; $tableCell .= ' onblur="regexEvent(this,event,\''.$modeinput.'\'); updateTotal('.$idw.',\''.$modeinput.'\')" />'; $tableCell .= '</td>'; print $tableCell; } // Warning print '<td class="right">'; if ((!$lines[$i]->public) && $disabledproject) { print $form->textwithpicto('', $langs->trans("UserIsNotContactOfProject")); } elseif ($disabledtask) { $titleassigntask = $langs->trans("AssignTaskToMe"); if ($fuser->id != $user->id) { $titleassigntask = $langs->trans("AssignTaskToUser", '...'); } print $form->textwithpicto('', $langs->trans("TaskIsNotAssignedToUser", $titleassigntask)); } print '</td>'; print "</tr>\n"; } // Call to show task with a lower level (task under the current task) $inc++; $level++; if ($lines[$i]->id > 0) { //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level); //var_dump($totalforeachday); $ret = projectLinesPerWeek($inc, $firstdaytoshow, $fuser, $lines[$i]->id, ($parent == 0 ? $lineswithoutlevel0 : $lines), $level, $projectsrole, $tasksrole, $mine, $restricteditformytask, $isavailable, $oldprojectforbreak, $arrayfields, $extrafields); //var_dump('ret with parent='.$lines[$i]->id.' level='.$level); //var_dump($ret); foreach ($ret as $key => $val) { $totalforeachday[$key] += $val; } //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level.' + subtasks'); //var_dump($totalforeachday); } $level--; } else { //$level--; } } return $totalforeachday; } /** * Output a task line into a perday intput mode * * @param string $inc Line output identificator (start to 0, then increased by recursive call) * @param int $firstdaytoshow First day to show * @param User|null $fuser Restrict list to user if defined * @param string $parent Id of parent task to show (0 to show all) * @param Task[] $lines Array of lines (list of tasks but we will show only if we have a specific role on task) * @param int $level Level (start to 0, then increased/decrease by recursive call) * @param string $projectsrole Array of roles user has on project * @param string $tasksrole Array of roles user has on task * @param string $mine Show only task lines I am assigned to * @param int $restricteditformytask 0=No restriction, 1=Enable add time only if task is a task i am affected to * @param array $isavailable Array with data that say if user is available for several days for morning and afternoon * @param int $oldprojectforbreak Old project id of last project break * @param array $TWeek Array of week numbers * @return array Array with time spent for $fuser for each day of week on tasks in $lines and substasks */ function projectLinesPerMonth(&$inc, $firstdaytoshow, $fuser, $parent, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, &$isavailable, $oldprojectforbreak = 0, $TWeek = array()) { global $conf, $db, $user, $langs; global $form, $formother, $projectstatic, $taskstatic, $thirdpartystatic; $numlines = count($lines); $lastprojectid = 0; $workloadforid = array(); $totalforeachweek = array(); $lineswithoutlevel0 = array(); // Create a smaller array with sublevels only to be used later. This increase dramatically performances. if ($parent == 0) { // Always and only if at first level for ($i = 0; $i < $numlines; $i++) { if ($lines[$i]->fk_task_parent) { $lineswithoutlevel0[] = $lines[$i]; } } } //dol_syslog('projectLinesPerWeek inc='.$inc.' firstdaytoshow='.$firstdaytoshow.' task parent id='.$parent.' level='.$level." count(lines)=".$numlines." count(lineswithoutlevel0)=".count($lineswithoutlevel0)); if (empty($oldprojectforbreak)) { $oldprojectforbreak = (empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT) ? 0 : -1); // 0 = start break, -1 = never break } $restrictBefore = null; if (! empty($conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS)) { require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; $restrictBefore = dol_time_plus_duree(dol_now(), - $conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS, 'm'); } for ($i = 0; $i < $numlines; $i++) { if ($parent == 0) { $level = 0; } if ($lines[$i]->fk_task_parent == $parent) { // If we want all or we have a role on task, we show it if (empty($mine) || !empty($tasksrole[$lines[$i]->id])) { //dol_syslog("projectLinesPerWeek Found line ".$i.", a qualified task (i have role or want to show all tasks) with id=".$lines[$i]->id." project id=".$lines[$i]->fk_project); // Break on a new project if ($parent == 0 && $lines[$i]->fk_project != $lastprojectid) { $lastprojectid = $lines[$i]->fk_project; $projectstatic->id = $lines[$i]->fk_project; } //var_dump('--- '.$level.' '.$firstdaytoshow.' '.$fuser->id.' '.$projectstatic->id.' '.$workloadforid[$projectstatic->id]); //var_dump($projectstatic->weekWorkLoadPerTask); if (empty($workloadforid[$projectstatic->id])) { $projectstatic->loadTimeSpentMonth($firstdaytoshow, 0, $fuser->id); // Load time spent from table projet_task_time for the project into this->weekWorkLoad and this->weekWorkLoadPerTask for all days of a week $workloadforid[$projectstatic->id] = 1; } //var_dump($projectstatic->weekWorkLoadPerTask); //var_dump('--- '.$projectstatic->id.' '.$workloadforid[$projectstatic->id]); $projectstatic->id = $lines[$i]->fk_project; $projectstatic->ref = $lines[$i]->projectref; $projectstatic->title = $lines[$i]->projectlabel; $projectstatic->public = $lines[$i]->public; $projectstatic->thirdparty_name = $lines[$i]->thirdparty_name; $projectstatic->status = $lines[$i]->projectstatus; $taskstatic->id = $lines[$i]->id; $taskstatic->ref = ($lines[$i]->ref ? $lines[$i]->ref : $lines[$i]->id); $taskstatic->label = $lines[$i]->label; $taskstatic->date_start = $lines[$i]->date_start; $taskstatic->date_end = $lines[$i]->date_end; $thirdpartystatic->id = $lines[$i]->thirdparty_id; $thirdpartystatic->name = $lines[$i]->thirdparty_name; $thirdpartystatic->email = $lines[$i]->thirdparty_email; if (empty($oldprojectforbreak) || ($oldprojectforbreak != -1 && $oldprojectforbreak != $projectstatic->id)) { print '<tr class="oddeven trforbreak nobold">'."\n"; print '<td colspan="'.(6 + count($TWeek)).'">'; print $projectstatic->getNomUrl(1, '', 0, '<strong>'.$langs->transnoentitiesnoconv("YourRole").':</strong> '.$projectsrole[$lines[$i]->fk_project]); if ($thirdpartystatic->id > 0) { print ' - '.$thirdpartystatic->getNomUrl(1); } if ($projectstatic->title) { print ' - '; print '<span class="secondary">'.$projectstatic->title.'</span>'; } print '</td>'; print '</tr>'; } if ($oldprojectforbreak != -1) { $oldprojectforbreak = $projectstatic->id; } print '<tr class="oddeven" data-taskid="'.$lines[$i]->id.'">'."\n"; // User /* print '<td class="nowrap">'; print $fuser->getNomUrl(1, 'withproject', 'time'); print '</td>'; */ // Project /*print '<td class="nowrap">'; if ($oldprojectforbreak == -1) print $projectstatic->getNomUrl(1,'',0,$langs->transnoentitiesnoconv("YourRole").': '.$projectsrole[$lines[$i]->fk_project]); print "</td>";*/ // Thirdparty /*print '<td class="tdoverflowmax100">'; if ($thirdpartystatic->id > 0) print $thirdpartystatic->getNomUrl(1, 'project'); print '</td>';*/ // Ref print '<td class="nowrap">'; print '<!-- Task id = '.$lines[$i]->id.' -->'; for ($k = 0; $k < $level; $k++) { print '<div class="marginleftonly">'; } print $taskstatic->getNomUrl(1, 'withproject', 'time'); // Label task print '<br>'; print '<span class="opacitymedium">'.$taskstatic->label.'</span>'; for ($k = 0; $k < $level; $k++) { print "</div>"; } print "</td>\n"; // Planned Workload print '<td class="leftborder plannedworkload right">'; if ($lines[$i]->planned_workload) { print convertSecondToTime($lines[$i]->planned_workload, 'allhourmin'); } else { print '--:--'; } print '</td>'; // Progress declared % print '<td class="right">'; print $formother->select_percent($lines[$i]->progress, $lines[$i]->id.'progress'); print '</td>'; // Time spent by everybody print '<td class="right">'; // $lines[$i]->duration is a denormalised field = summ of time spent by everybody for task. What we need is time consummed by user if ($lines[$i]->duration) { print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?id='.$lines[$i]->id.'">'; print convertSecondToTime($lines[$i]->duration, 'allhourmin'); print '</a>'; } else { print '--:--'; } print "</td>\n"; // Time spent by user print '<td class="right">'; $tmptimespent = $taskstatic->getSummaryOfTimeSpent($fuser->id); if ($tmptimespent['total_duration']) { print convertSecondToTime($tmptimespent['total_duration'], 'allhourmin'); } else { print '--:--'; } print "</td>\n"; $disabledproject = 1; $disabledtask = 1; //print "x".$lines[$i]->fk_project; //var_dump($lines[$i]); //var_dump($projectsrole[$lines[$i]->fk_project]); // If at least one role for project if ($lines[$i]->public || !empty($projectsrole[$lines[$i]->fk_project]) || $user->rights->projet->all->creer) { $disabledproject = 0; $disabledtask = 0; } // If $restricteditformytask is on and I have no role on task, i disable edit if ($restricteditformytask && empty($tasksrole[$lines[$i]->id])) { $disabledtask = 1; } //var_dump($projectstatic->weekWorkLoadPerTask); //TODO // Fields to show current time $tableCell = ''; $modeinput = 'hours'; $TFirstDay = getFirstDayOfEachWeek($TWeek, date('Y', $firstdaytoshow)); $TFirstDay[reset($TWeek)] = 1; $firstdaytoshowarray = dol_getdate($firstdaytoshow); $year = $firstdaytoshowarray['year']; $month = $firstdaytoshowarray['mon']; foreach ($TWeek as $weekIndex => $weekNb) { $weekWorkLoad = $projectstatic->monthWorkLoadPerTask[$weekNb][$lines[$i]->id]; $totalforeachweek[$weekNb] += $weekWorkLoad; $alreadyspent = ''; if ($weekWorkLoad > 0) { $alreadyspent = convertSecondToTime($weekWorkLoad, 'allhourmin'); } $alttitle = $langs->trans("AddHereTimeSpentForWeek", $weekNb); $disabledtaskweek = $disabledtask; $firstdayofweek = dol_mktime(0, 0, 0, $month, $TFirstDay[$weekIndex], $year); if (! $disabledtask && $restrictBefore && $firstdayofweek < $restrictBefore) { $disabledtaskweek = 1; } $tableCell = '<td class="center hide weekend">'; $placeholder = ''; if ($alreadyspent) { $tableCell .= '<span class="timesheetalreadyrecorded" title="texttoreplace"><input type="text" class="center smallpadd" size="2" disabled id="timespent['.$inc.']['.((int) $weekNb).']" name="task['.$lines[$i]->id.']['.$weekNb.']" value="'.$alreadyspent.'"></span>'; //$placeholder=' placeholder="00:00"'; //$tableCell.='+'; } $tableCell .= '<input type="text" alt="'.($disabledtaskweek ? '' : $alttitle).'" title="'.($disabledtaskweek ? '' : $alttitle).'" '.($disabledtaskweek ? 'disabled' : $placeholder).' class="center smallpadd" size="2" id="timeadded['.$inc.']['.((int) $weekNb).']" name="task['.$lines[$i]->id.']['.($TFirstDay[$weekNb] - 1).']" value="" cols="2" maxlength="5"'; $tableCell .= ' onkeypress="return regexEvent(this,event,\'timeChar\')"'; $tableCell .= ' onkeyup="updateTotal('.$weekNb.',\''.$modeinput.'\')"'; $tableCell .= ' onblur="regexEvent(this,event,\''.$modeinput.'\'); updateTotal('.$weekNb.',\''.$modeinput.'\')" />'; $tableCell .= '</td>'; print $tableCell; } // Warning print '<td class="right">'; if ((!$lines[$i]->public) && $disabledproject) { print $form->textwithpicto('', $langs->trans("UserIsNotContactOfProject")); } elseif ($disabledtask) { $titleassigntask = $langs->trans("AssignTaskToMe"); if ($fuser->id != $user->id) { $titleassigntask = $langs->trans("AssignTaskToUser", '...'); } print $form->textwithpicto('', $langs->trans("TaskIsNotAssignedToUser", $titleassigntask)); } print '</td>'; print "</tr>\n"; } // Call to show task with a lower level (task under the current task) $inc++; $level++; if ($lines[$i]->id > 0) { //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level); //var_dump($totalforeachday); $ret = projectLinesPerMonth($inc, $firstdaytoshow, $fuser, $lines[$i]->id, ($parent == 0 ? $lineswithoutlevel0 : $lines), $level, $projectsrole, $tasksrole, $mine, $restricteditformytask, $isavailable, $oldprojectforbreak, $TWeek); //var_dump('ret with parent='.$lines[$i]->id.' level='.$level); //var_dump($ret); foreach ($ret as $key => $val) { $totalforeachweek[$key] += $val; } //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level.' + subtasks'); //var_dump($totalforeachday); } $level--; } else { //$level--; } } return $totalforeachweek; } /** * Search in task lines with a particular parent if there is a task for a particular user (in taskrole) * * @param string $inc Counter that count number of lines legitimate to show (for return) * @param int $parent Id of parent task to start * @param array $lines Array of all tasks * @param string $taskrole Array of task filtered on a particular user * @return int 1 if there is */ function searchTaskInChild(&$inc, $parent, &$lines, &$taskrole) { //print 'Search in line with parent id = '.$parent.'<br>'; $numlines = count($lines); for ($i = 0; $i < $numlines; $i++) { // Process line $lines[$i] if ($lines[$i]->fk_parent == $parent && $lines[$i]->id != $lines[$i]->fk_parent) { // If task is legitimate to show, no more need to search deeper if (isset($taskrole[$lines[$i]->id])) { //print 'Found a legitimate task id='.$lines[$i]->id.'<br>'; $inc++; return $inc; } searchTaskInChild($inc, $lines[$i]->id, $lines, $taskrole); //print 'Found inc='.$inc.'<br>'; if ($inc > 0) { return $inc; } } } return $inc; } /** * Return HTML table with list of projects and number of opened tasks * * @param DoliDB $db Database handler * @param Form $form Object form * @param int $socid Id thirdparty * @param int $projectsListId Id of project I have permission on * @param int $mytasks Limited to task I am contact to * @param int $status -1=No filter on statut, 0 or 1 = Filter on status * @param array $listofoppstatus List of opportunity status * @param array $hiddenfields List of info to not show ('projectlabel', 'declaredprogress', '...', ) * @return void */ function print_projecttasks_array($db, $form, $socid, $projectsListId, $mytasks = 0, $status = -1, $listofoppstatus = array(), $hiddenfields = array()) { global $langs, $conf, $user; global $theme_datacolor; require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; $listofstatus = array_keys($listofoppstatus); if (is_array($listofstatus) && !empty($conf->global->USE_COLOR_FOR_PROSPECTION_STATUS)) { // Define $themeColorId and array $statusOppList for each $listofstatus $themeColorId = 0; $statusOppList = array(); foreach ($listofstatus as $oppStatus) { $oppStatusCode = dol_getIdFromCode($db, $oppStatus, 'c_lead_status', 'rowid', 'code'); if ($oppStatusCode) { $statusOppList[$oppStatus]['code'] = $oppStatusCode; $statusOppList[$oppStatus]['color'] = isset($theme_datacolor[$themeColorId]) ? implode(', ', $theme_datacolor[$themeColorId]) : ''; } $themeColorId++; } } $projectstatic = new Project($db); $thirdpartystatic = new Societe($db); $sortfield = ''; $sortorder = ''; $project_year_filter = 0; $title = $langs->trans("Projects"); if (strcmp($status, '') && $status >= 0) { $title = $langs->trans("Projects").' '.$langs->trans($projectstatic->statuts_long[$status]); } $arrayidtypeofcontact = array(); print '<div class="div-table-responsive-no-min">'; print '<table class="noborder centpercent">'; $sql = " FROM ".MAIN_DB_PREFIX."projet as p"; if ($mytasks) { $sql .= ", ".MAIN_DB_PREFIX."projet_task as t"; $sql .= ", ".MAIN_DB_PREFIX."element_contact as ec"; $sql .= ", ".MAIN_DB_PREFIX."c_type_contact as ctc"; } else { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."projet_task as t ON p.rowid = t.fk_projet"; } $sql .= " WHERE p.entity IN (".getEntity('project').")"; $sql .= " AND p.rowid IN (".$db->sanitize($projectsListId).")"; if ($socid) { $sql .= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".((int) $socid).")"; } if ($mytasks) { $sql .= " AND p.rowid = t.fk_projet"; $sql .= " AND ec.element_id = t.rowid"; $sql .= " AND ec.fk_socpeople = ".((int) $user->id); $sql .= " AND ec.fk_c_type_contact = ctc.rowid"; // Replace the 2 lines with ec.fk_c_type_contact in $arrayidtypeofcontact $sql .= " AND ctc.element = 'project_task'"; } if ($status >= 0) { $sql .= " AND p.fk_statut = ".(int) $status; } if (!empty($conf->global->PROJECT_LIMIT_YEAR_RANGE)) { $project_year_filter = GETPOST("project_year_filter"); //Check if empty or invalid year. Wildcard ignores the sql check if ($project_year_filter != "*") { if (empty($project_year_filter) || !ctype_digit($project_year_filter)) { $project_year_filter = date("Y"); } $sql .= " AND (p.dateo IS NULL OR p.dateo <= ".$db->idate(dol_get_last_day($project_year_filter, 12, false)).")"; $sql .= " AND (p.datee IS NULL OR p.datee >= ".$db->idate(dol_get_first_day($project_year_filter, 1, false)).")"; } } // Get id of project we must show tasks $arrayidofprojects = array(); $sql1 = "SELECT p.rowid as projectid"; $sql1 .= $sql; $resql = $db->query($sql1); if ($resql) { $i = 0; $num = $db->num_rows($resql); while ($i < $num) { $objp = $db->fetch_object($resql); $arrayidofprojects[$objp->projectid] = $objp->projectid; $i++; } } else { dol_print_error($db); } if (empty($arrayidofprojects)) { $arrayidofprojects[0] = -1; } // Get list of project with calculation on tasks $sql2 = "SELECT p.rowid as projectid, p.ref, p.title, p.fk_soc,"; $sql2 .= " s.rowid as socid, s.nom as socname, s.name_alias,"; $sql2 .= " s.code_client, s.code_compta, s.client,"; $sql2 .= " s.code_fournisseur, s.code_compta_fournisseur, s.fournisseur,"; $sql2 .= " s.logo, s.email, s.entity,"; $sql2 .= " p.fk_user_creat, p.public, p.fk_statut as status, p.fk_opp_status as opp_status, p.opp_percent, 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 (".$db->sanitize(join(',', $arrayidofprojects)).")"; $sql2 .= " GROUP BY p.rowid, p.ref, p.title, p.fk_soc, s.rowid, s.nom, s.name_alias, s.code_client, s.code_compta, s.client, s.code_fournisseur, s.code_compta_fournisseur, s.fournisseur,"; $sql2 .= " s.logo, s.email, s.entity, p.fk_user_creat, p.public, p.fk_statut, p.fk_opp_status, p.opp_percent, p.opp_amount, p.dateo, p.datee"; $sql2 .= " ORDER BY p.title, p.ref"; $resql = $db->query($sql2); if ($resql) { $total_task = 0; $total_opp_amount = 0; $ponderated_opp_amount = 0; $num = $db->num_rows($resql); $i = 0; print '<tr class="liste_titre">'; print_liste_field_titre($title.'<a href="'.DOL_URL_ROOT.'/projet/list.php?search_status='.((int) $status).'"><span class="badge marginleftonlyshort">'.$num.'</span></a>', $_SERVER["PHP_SELF"], "", "", "", "", $sortfield, $sortorder); print_liste_field_titre("ThirdParty", $_SERVER["PHP_SELF"], "", "", "", "", $sortfield, $sortorder); if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES)) { if (!in_array('prospectionstatus', $hiddenfields)) { print_liste_field_titre("OpportunityStatus", "", "", "", "", 'style="max-width: 100px"', $sortfield, $sortorder, 'center '); } print_liste_field_titre($form->textwithpicto($langs->trans("Amount"), $langs->trans("OpportunityAmount").' ('.$langs->trans("Tooltip").' = '.$langs->trans("OpportunityWeightedAmount").')'), "", "", "", "", 'style="max-width: 100px"', $sortfield, $sortorder, 'right '); //print_liste_field_titre('OpportunityWeightedAmount', '', '', '', '', 'align="right"', $sortfield, $sortorder); } if (empty($conf->global->PROJECT_HIDE_TASKS)) { print_liste_field_titre("Tasks", "", "", "", "", 'align="right"', $sortfield, $sortorder); if (!in_array('plannedworkload', $hiddenfields)) { print_liste_field_titre("PlannedWorkload", "", "", "", "", 'style="max-width: 100px"', $sortfield, $sortorder, 'right '); } if (!in_array('declaredprogress', $hiddenfields)) { print_liste_field_titre("%", "", "", "", "", '', $sortfield, $sortorder, 'right ', $langs->trans("ProgressDeclared")); } } if (!in_array('projectstatus', $hiddenfields)) { print_liste_field_titre("Status", "", "", "", "", '', $sortfield, $sortorder, 'right '); } print "</tr>\n"; $total_plannedworkload = 0; $total_declaredprogressworkload = 0; while ($i < $num) { $objp = $db->fetch_object($resql); $projectstatic->id = $objp->projectid; $projectstatic->user_author_id = $objp->fk_user_creat; $projectstatic->public = $objp->public; // Check is user has read permission on project $userAccess = $projectstatic->restrictedProjectArea($user); if ($userAccess >= 0) { $projectstatic->ref = $objp->ref; $projectstatic->status = $objp->status; $projectstatic->title = $objp->title; $projectstatic->datee = $db->jdate($objp->datee); $projectstatic->dateo = $db->jdate($objp->dateo); print '<tr class="oddeven">'; print '<td class="tdoverflowmax150">'; print $projectstatic->getNomUrl(1, '', 0, '', '-', 0, -1, 'nowraponall'); if (!in_array('projectlabel', $hiddenfields)) { print '<br><span class="opacitymedium">'.dol_trunc($objp->title, 24).'</span>'; } print '</td>'; print '<td class="nowraponall tdoverflowmax100">'; if ($objp->fk_soc > 0) { $thirdpartystatic->id = $objp->socid; $thirdpartystatic->name = $objp->socname; //$thirdpartystatic->name_alias = $objp->name_alias; //$thirdpartystatic->code_client = $objp->code_client; $thirdpartystatic->code_compta = $objp->code_compta; $thirdpartystatic->client = $objp->client; //$thirdpartystatic->code_fournisseur = $objp->code_fournisseur; $thirdpartystatic->code_compta_fournisseur = $objp->code_compta_fournisseur; $thirdpartystatic->fournisseur = $objp->fournisseur; $thirdpartystatic->logo = $objp->logo; $thirdpartystatic->email = $objp->email; $thirdpartystatic->entity = $objp->entity; print $thirdpartystatic->getNomUrl(1); } print '</td>'; if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES)) { if (!in_array('prospectionstatus', $hiddenfields)) { print '<td class="center tdoverflowmax75">'; // Because color of prospection status has no meaning yet, it is used if hidden constant is set if (empty($conf->global->USE_COLOR_FOR_PROSPECTION_STATUS)) { $oppStatusCode = dol_getIdFromCode($db, $objp->opp_status, 'c_lead_status', 'rowid', 'code'); if ($langs->trans("OppStatus".$oppStatusCode) != "OppStatus".$oppStatusCode) { print $langs->trans("OppStatus".$oppStatusCode); } } else { if (isset($statusOppList[$objp->opp_status])) { $oppStatusCode = $statusOppList[$objp->opp_status]['code']; $oppStatusColor = $statusOppList[$objp->opp_status]['color']; } else { $oppStatusCode = dol_getIdFromCode($db, $objp->opp_status, 'c_lead_status', 'rowid', 'code'); $oppStatusColor = ''; } if ($oppStatusCode) { if (!empty($oppStatusColor)) { print '<a href="'.dol_buildpath('/projet/list.php?search_opp_status='.$objp->opp_status, 1).'" style="display: inline-block; width: 4px; border: 5px solid rgb('.$oppStatusColor.'); border-radius: 2px;" title="'.$langs->trans("OppStatus".$oppStatusCode).'"></a>'; } else { print '<a href="'.dol_buildpath('/projet/list.php?search_opp_status='.$objp->opp_status, 1).'" title="'.$langs->trans("OppStatus".$oppStatusCode).'">'.$oppStatusCode.'</a>'; } } } print '</td>'; } print '<td class="right">'; if ($objp->opp_percent && $objp->opp_amount) { $opp_weighted_amount = $objp->opp_percent * $objp->opp_amount / 100; $alttext = $langs->trans("OpportunityWeightedAmount").' '.price($opp_weighted_amount, 0, '', 1, -1, 0, $conf->currency); $ponderated_opp_amount += price2num($opp_weighted_amount); } if ($objp->opp_amount) { print '<span class="amount" title="'.$alttext.'">'.$form->textwithpicto(price($objp->opp_amount, 0, '', 1, -1, 0), $alttext).'</span>'; } print '</td>'; } if (empty($conf->global->PROJECT_HIDE_TASKS)) { print '<td class="right">'.$objp->nb.'</td>'; $plannedworkload = $objp->planned_workload; $total_plannedworkload += $plannedworkload; if (!in_array('plannedworkload', $hiddenfields)) { print '<td class="right">'.($plannedworkload ?convertSecondToTime($plannedworkload) : '').'</td>'; } if (!in_array('declaredprogress', $hiddenfields)) { $declaredprogressworkload = $objp->declared_progess_workload; $total_declaredprogressworkload += $declaredprogressworkload; print '<td class="right">'; //print $objp->planned_workload.'-'.$objp->declared_progess_workload."<br>"; print ($plannedworkload ?round(100 * $declaredprogressworkload / $plannedworkload, 0).'%' : ''); print '</td>'; } } if (!in_array('projectstatus', $hiddenfields)) { print '<td class="right">'; print $projectstatic->getLibStatut(3); print '</td>'; } print "</tr>\n"; $total_task = $total_task + $objp->nb; $total_opp_amount = $total_opp_amount + $objp->opp_amount; } $i++; } print '<tr class="liste_total">'; print '<td>'.$langs->trans("Total")."</td><td></td>"; if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES)) { if (!in_array('prospectionstatus', $hiddenfields)) { print '<td class="liste_total"></td>'; } print '<td class="liste_total right">'; //$form->textwithpicto(price($ponderated_opp_amount, 0, '', 1, -1, -1, $conf->currency), $langs->trans("OpportunityPonderatedAmountDesc"), 1); print $form->textwithpicto(price($total_opp_amount, 0, '', 1, -1, 0), $langs->trans("OpportunityPonderatedAmountDesc").' : '.price($ponderated_opp_amount, 0, '', 1, -1, 0, $conf->currency)); print '</td>'; } if (empty($conf->global->PROJECT_HIDE_TASKS)) { print '<td class="liste_total right">'.$total_task.'</td>'; if (!in_array('plannedworkload', $hiddenfields)) { print '<td class="liste_total right">'.($total_plannedworkload ?convertSecondToTime($total_plannedworkload) : '').'</td>'; } if (!in_array('declaredprogress', $hiddenfields)) { print '<td class="liste_total right">'.($total_plannedworkload ?round(100 * $total_declaredprogressworkload / $total_plannedworkload, 0).'%' : '').'</td>'; } } if (!in_array('projectstatus', $hiddenfields)) { print '<td class="liste_total"></td>'; } print '</tr>'; $db->free($resql); } else { dol_print_error($db); } print "</table>"; print '</div>'; if (!empty($conf->global->PROJECT_LIMIT_YEAR_RANGE)) { //Add the year filter input print '<form method="get" action="'.$_SERVER["PHP_SELF"].'">'; print '<table width="100%">'; print '<tr>'; print '<td>'.$langs->trans("Year").'</td>'; print '<td class="right"><input type="text" size="4" class="flat" name="project_year_filter" value="'.$project_year_filter.'"/>'; print "</tr>\n"; print '</table></form>'; } } /** * @param Task $task the task object * @param bool|string $label true = auto, false = dont display, string = replace output * @param bool|string $progressNumber true = auto, false = dont display, string = replace output * @param bool $hideOnProgressNull hide if progress is null * @param bool $spaced used to add space at bottom (made by css) * @return string * @see getTaskProgressBadge() */ function getTaskProgressView($task, $label = true, $progressNumber = true, $hideOnProgressNull = false, $spaced = false) { global $langs, $conf; $out = ''; $plannedworkloadoutputformat = 'allhourmin'; $timespentoutputformat = 'allhourmin'; if (!empty($conf->global->PROJECT_PLANNED_WORKLOAD_FORMAT)) { $plannedworkloadoutputformat = $conf->global->PROJECT_PLANNED_WORKLOAD_FORMAT; } if (!empty($conf->global->PROJECT_TIMES_SPENT_FORMAT)) { $timespentoutputformat = $conf->global->PROJECT_TIME_SPENT_FORMAT; } if (empty($task->progress) && !empty($hideOnProgressNull)) { return ''; } $spaced = !empty($spaced) ? 'spaced' : ''; $diff = ''; // define progress color according to time spend vs workload $progressBarClass = 'progress-bar-info'; $progressCalculated = 0; if ($task->planned_workload) { $progressCalculated = round(100 * floatval($task->duration_effective) / floatval($task->planned_workload), 2); // this conf is actually hidden, by default we use 10% for "be carefull or warning" $warningRatio = !empty($conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT) ? (1 + $conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT / 100) : 1.10; $diffTitle = '<br>'.$langs->trans('ProgressDeclared').' : '.$task->progress.($task->progress ? '%' : ''); $diffTitle .= '<br>'.$langs->trans('ProgressCalculated').' : '.$progressCalculated.($progressCalculated ? '%' : ''); //var_dump($progressCalculated.' '.$warningRatio.' '.$task->progress.' '.floatval($task->progress * $warningRatio)); if (floatval($progressCalculated) > floatval($task->progress * $warningRatio)) { $progressBarClass = 'progress-bar-danger'; $title = $langs->trans('TheReportedProgressIsLessThanTheCalculatedProgressionByX', abs($task->progress - $progressCalculated).' '.$langs->trans("point")); $diff = '<span class="text-danger classfortooltip paddingrightonly" title="'.dol_htmlentities($title.$diffTitle).'" ><i class="fa fa-caret-down"></i> '.($task->progress - $progressCalculated).'%</span>'; } elseif (floatval($progressCalculated) > floatval($task->progress)) { // warning if close at 10% $progressBarClass = 'progress-bar-warning'; $title = $langs->trans('TheReportedProgressIsLessThanTheCalculatedProgressionByX', abs($task->progress - $progressCalculated).' '.$langs->trans("point")); $diff = '<span class="text-warning classfortooltip paddingrightonly" title="'.dol_htmlentities($title.$diffTitle).'" ><i class="fa fa-caret-left"></i> '.($task->progress - $progressCalculated).'%</span>'; } else { $progressBarClass = 'progress-bar-success'; $title = $langs->trans('TheReportedProgressIsMoreThanTheCalculatedProgressionByX', ($task->progress - $progressCalculated).' '.$langs->trans("point")); $diff = '<span class="text-success classfortooltip paddingrightonly" title="'.dol_htmlentities($title.$diffTitle).'" ><i class="fa fa-caret-up"></i> '.($task->progress - $progressCalculated).'%</span>'; } } $out .= '<div class="progress-group">'; if ($label !== false) { $out .= ' <span class="progress-text">'; if ($label !== true) { $out .= $label; // replace label by param } else { $out .= $task->getNomUrl(1).' '.dol_htmlentities($task->label); } $out .= ' </span>'; } if ($progressNumber !== false) { $out .= ' <span class="progress-number">'; if ($progressNumber !== true) { $out .= $progressNumber; // replace label by param } else { if ($task->hasDelay()) { $out .= img_warning($langs->trans("Late")).' '; } $url = DOL_URL_ROOT.'/projet/tasks/time.php?id='.$task->id; $out .= !empty($diff) ? $diff.' ' : ''; $out .= '<a href="'.$url.'" >'; $out .= '<b title="'.$langs->trans('TimeSpent').'" >'; if ($task->duration_effective) { $out .= convertSecondToTime($task->duration_effective, $timespentoutputformat); } else { $out .= '--:--'; } $out .= '</b>'; $out .= '</a>'; $out .= ' / '; $out .= '<a href="'.$url.'" >'; $out .= '<span title="'.$langs->trans('PlannedWorkload').'" >'; if ($task->planned_workload) { $out .= convertSecondToTime($task->planned_workload, $plannedworkloadoutputformat); } else { $out .= '--:--'; } $out .= '</a>'; } $out .= ' </span>'; } $out .= '</span>'; $out .= ' <div class="progress sm '.$spaced.'">'; $diffval = floatval($task->progress) - floatval($progressCalculated); if ($diffval >= 0) { // good $out .= ' <div class="progress-bar '.$progressBarClass.'" style="width: '.floatval($task->progress).'%" title="'.floatval($task->progress).'%">'; if (!empty($task->progress)) { $out .= ' <div class="progress-bar progress-bar-consumed" style="width: '.floatval($progressCalculated / $task->progress * 100).'%" title="'.floatval($progressCalculated).'%"></div>'; } $out .= ' </div>'; } else { // bad $out .= ' <div class="progress-bar progress-bar-consumed" style="width: '.floatval($progressCalculated).'%" title="'.floatval($progressCalculated).'%">'; $out .= ' <div class="progress-bar '.$progressBarClass.'" style="width: '.($task->progress ? floatval($task->progress / $progressCalculated * 100).'%' : '1px').'" title="'.floatval($task->progress).'%"></div>'; $out .= ' </div>'; } $out .= ' </div>'; $out .= '</div>'; return $out; } /** * @param Task $task the task object * @param string $label empty = auto (progress), string = replace output * @param string $tooltip empty = auto , string = replace output * @return string * @see getTaskProgressView() */ function getTaskProgressBadge($task, $label = '', $tooltip = '') { global $conf, $langs; $out = ''; $badgeClass = ''; if ($task->progress != '') { // TODO : manage 100% // define color according to time spend vs workload $badgeClass = 'badge '; if ($task->planned_workload) { $progressCalculated = round(100 * floatval($task->duration_effective) / floatval($task->planned_workload), 2); // this conf is actually hidden, by default we use 10% for "be carefull or warning" $warningRatio = !empty($conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT) ? (1 + $conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT / 100) : 1.10; if (floatval($progressCalculated) > floatval($task->progress * $warningRatio)) { $badgeClass .= 'badge-danger'; if (empty($tooltip)) { $tooltip = $task->progress.'% < '.$langs->trans("TimeConsumed").' '.$progressCalculated.'%'; } } elseif (floatval($progressCalculated) > floatval($task->progress)) { // warning if close at 10% $badgeClass .= 'badge-warning'; if (empty($tooltip)) { $tooltip = $task->progress.'% < '.$langs->trans("TimeConsumed").' '.$progressCalculated.'%'; } } else { $badgeClass .= 'badge-success'; if (empty($tooltip)) { $tooltip = $task->progress.'% >= '.$langs->trans("TimeConsumed").' '.$progressCalculated.'%'; } } } } $title = ''; if (!empty($tooltip)) { $badgeClass .= ' classfortooltip'; $title = 'title="'.dol_htmlentities($tooltip).'"'; } if (empty($label)) { $label = $task->progress.' %'; } if (!empty($label)) { $out = '<span class="'.$badgeClass.'" '.$title.' >'.$label.'</span>'; } return $out; }
Save