dolibarr 22.0.5
index.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2001-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2022 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005-2010 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2019 Nicolas ZABOURI <info@inovea-conseil.com>
6 * Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
7 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
29// Load Dolibarr environment
30require '../main.inc.php';
31require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
32require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
33require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
34require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
35require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
36
45// Load translation files required by the page
46$langs->loadLangs(array('projects', 'companies'));
47
48$hookmanager = new HookManager($db);
49
50// Initialize a technical object to manage hooks. Note that conf->hooks_modules contains array
51$hookmanager->initHooks(array('projectsindex'));
52
53$action = GETPOST('action', 'aZ09');
54$search_project_user = GETPOST('search_project_user');
55$mine = (GETPOST('mode', 'aZ09') == 'mine' || $search_project_user == $user->id) ? 1 : 0;
56if ($mine == 0 && $search_project_user === '') {
57 $search_project_user = getDolGlobalString('MAIN_SEARCH_PROJECT_USER_PROJECTSINDEX');
58}
59if ($search_project_user == $user->id) {
60 $mine = 1;
61}
62
63$sortfield = GETPOST('sortfield', 'aZ09comma');
64$sortorder = GETPOST('sortorder', 'aZ09comma');
65
66$max = getDolGlobalInt('MAIN_SIZE_SHORTLIST_LIMIT', 5);
67
68// Security check
69$socid = 0;
70//if ($user->socid > 0) $socid = $user->socid; // For external user, no check is done on company because readability is managed by public status of project and assignment.
71if (!$user->hasRight('projet', 'lire')) {
73}
74
75
76/*
77 * Actions
78 */
79
80$parameters = array();
81$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
82if ($reshook < 0) {
83 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
84}
85if (empty($reshook)) {
86 if ($action == 'refresh_search_project_user' && $user->hasRight('projet', 'lire')) {
87 $search_project_user = GETPOSTINT('search_project_user');
88 $tabparam = array("MAIN_SEARCH_PROJECT_USER_PROJECTSINDEX" => $search_project_user);
89
90 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
91 $result = dol_set_user_param($db, $conf, $user, $tabparam);
92 }
93}
94
95
96/*
97 * View
98 */
99
100$companystatic = new Societe($db);
101$projectstatic = new Project($db);
102$form = new Form($db);
103$formfile = new FormFile($db);
104
105$projectset = ($mine ? $mine : (!$user->hasRight('projet', 'all', 'lire') ? 0 : 2));
106$projectsListId = $projectstatic->getProjectsAuthorizedForUser($user, $projectset, 1);
107//var_dump($projectsListId);
108
109
110$title = $langs->trans('ProjectsArea');
111
112$help_url = 'EN:Module_Projects|FR:Module_Projets|ES:M&oacute;dulo_Proyectos|DE:Modul_Projekte';
113
114llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-project page-dashboard');
115
116
117//if ($mine) $title=$langs->trans("MyProjectsArea");
118
119
120// Title for combo list see all projects
121$titleall = $langs->trans("AllAllowedProjects");
122if ($user->hasRight('projet', 'all', 'lire') && !$socid) {
123 $titleall = $langs->trans("AllProjects");
124} else {
125 $titleall = $langs->trans("AllAllowedProjects").'<br><br>';
126}
127
128$morehtml = '<form name="projectform" method="POST" action="'.$_SERVER["PHP_SELF"].'">';
129$morehtml .= '<input type="hidden" name="token" value="'.newToken().'">';
130$morehtml .= '<input type="hidden" name="action" value="refresh_search_project_user">';
131
132$morehtml .= '<select name="search_project_user" id="search_project_user">';
133$morehtml .= '<option name="all" value="0"'.($mine ? '' : ' selected').'>'.$titleall.'</option>';
134$morehtml .= '<option name="mine" value="'.$user->id.'"'.(($search_project_user == $user->id) ? ' selected' : '').'>'.$langs->trans("ProjectsImContactFor").'</option>';
135$morehtml .= '</select>';
136$morehtml .= ajax_combobox("search_project_user", array(), 0, 0, 'resolve', '-1', 'small');
137$morehtml .= '<input type="submit" class="button smallpaddingimp" name="refresh" value="'.$langs->trans("Refresh").'">';
138$morehtml .= '</form>';
139
140if ($mine) {
141 $htmltooltip = $langs->trans("MyProjectsDesc");
142} else {
143 if ($user->hasRight('projet', 'all', 'lire') && !$socid) {
144 $htmltooltip = $langs->trans("ProjectsDesc");
145 } else {
146 $htmltooltip = $langs->trans("ProjectsPublicDesc");
147 }
148}
149
150print_barre_liste($form->textwithpicto($title, $htmltooltip), 0, $_SERVER["PHP_SELF"], '', '', '', '', 0, -1, 'project', 0, $morehtml);
151
152
153// Get list of ponderated percent and colors for each status
154include DOL_DOCUMENT_ROOT.'/theme/'.$conf->theme.'/theme_vars.inc.php';
163// Available from theme_vars:
164'
165@phan-var-force string $badgeStatus0
166@phan-var-force string $badgeStatus1
167@phan-var-force string $badgeStatus2
168@phan-var-force string $badgeStatus3
169@phan-var-force string $badgeStatus4
170@phan-var-force string $badgeStatus5
171@phan-var-force string $badgeStatus6
172@phan-var-force string $badgeStatus7
173@phan-var-force string $badgeStatus8
174@phan-var-force string $badgeStatus9
175';
176$listofoppstatus = array();
177$listofopplabel = array();
178$listofoppcode = array();
179$colorseries = array();
180$sql = "SELECT cls.rowid, cls.code, cls.percent, cls.label";
181$sql .= " FROM ".MAIN_DB_PREFIX."c_lead_status as cls";
182$sql .= " WHERE active=1";
183$resql = $db->query($sql);
184if ($resql) {
185 $num = $db->num_rows($resql);
186 $i = 0;
187
188 while ($i < $num) {
189 $objp = $db->fetch_object($resql);
190 $listofoppstatus[$objp->rowid] = $objp->percent;
191 $listofopplabel[$objp->rowid] = $objp->label; // default label if translation from "OppStatus".code not found.
192 $listofoppcode[$objp->rowid] = $objp->code;
193 switch ($objp->code) {
194 case 'PROSP':
195 $colorseries[$objp->rowid] = "-".$badgeStatus0;
196 break;
197 case 'QUAL':
198 $colorseries[$objp->rowid] = "-".$badgeStatus1;
199 break;
200 case 'PROPO':
201 $colorseries[$objp->rowid] = $badgeStatus1;
202 break;
203 case 'NEGO':
204 $colorseries[$objp->rowid] = $badgeStatus4;
205 break;
206 case 'LOST':
207 $colorseries[$objp->rowid] = $badgeStatus9;
208 break;
209 case 'WON':
210 $colorseries[$objp->rowid] = $badgeStatus6;
211 break;
212 default:
213 $colorseries[$objp->rowid] = $badgeStatus2;
214 break;
215 }
216 $i++;
217 }
218} else {
219 dol_print_error($db);
220}
221
222
223print '<div class="fichecenter">';
224
225print '<div class="twocolumns">';
226
227print '<div class="firstcolumn fichehalfleft boxhalfleft" id="boxhalfleft">';
228
229
230// Statistics
231include DOL_DOCUMENT_ROOT.'/projet/graph_opportunities.inc.php';
232
233// List of draft projects
234print_projecttasks_array($db, $form, $socid, $projectsListId, 0, 0, $listofoppstatus, array('projectlabel', 'plannedworkload', 'declaredprogress', 'prospectionstatus', 'projectstatus'), $max);
235
236
237print '</div><div class="secondcolumn fichehalfright boxhalfright" id="boxhalfright">';
238
239
240// Latest modified projects
241$sql = "SELECT p.rowid, p.ref, p.title, p.dateo as date_start, p.datee as date_end, p.fk_statut as status, p.tms as datem";
242$sql .= ", s.rowid as socid, s.nom as name, s.name_alias";
243$sql .= ", s.code_client, s.code_compta, s.client";
244$sql .= ", s.code_fournisseur, s.code_compta_fournisseur, s.fournisseur";
245$sql .= ", s.logo, s.email, s.entity";
246$sql .= ", s.canvas, s.status as thirdpartystatus";
247$sql .= " FROM ".MAIN_DB_PREFIX."projet as p";
248$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on p.fk_soc = s.rowid";
249$sql .= " WHERE p.entity IN (".getEntity('project').")";
250if ($mine || !$user->hasRight('projet', 'all', 'lire')) {
251 $sql .= " AND p.rowid IN (".$db->sanitize($projectsListId).")"; // If we have this test true, it also means projectset is not 2
252}
253if ($socid) {
254 $sql .= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".((int) $socid).")";
255}
256$sql .= " ORDER BY p.tms DESC";
257$sql .= $db->plimit($max, 0);
258
259$resql = $db->query($sql);
260if ($resql) {
261 startSimpleTable($langs->trans("LatestModifiedProjects", $max), "projet/list.php", "sortfield=p.tms&sortorder=DESC", 3, -1, 'project');
262
263 $num = $db->num_rows($resql);
264
265 if ($num) {
266 $i = 0;
267 while ($i < $num) {
268 $obj = $db->fetch_object($resql);
269
270 print '<tr class="oddeven">';
271 print '<td class="nowrap">';
272
273 $projectstatic->id = $obj->rowid;
274 $projectstatic->ref = $obj->ref;
275 $projectstatic->title = $obj->title;
276 $projectstatic->thirdparty_name = $obj->name;
277 $projectstatic->status = $obj->status;
278 $projectstatic->date_start = $db->jdate($obj->date_start);
279 $projectstatic->date_end = $db->jdate($obj->date_end);
280
281 $companystatic->id = $obj->socid;
282 $companystatic->name = $obj->name;
283 $companystatic->name_alias = $obj->name_alias;
284 //$companystatic->code_client = $obj->code_client;
285 $companystatic->code_compta = $obj->code_compta;
286 $companystatic->code_compta_client = $obj->code_compta;
287 $companystatic->client = $obj->client;
288 //$companystatic->code_fournisseur = $obj->code_fournisseur;
289 $companystatic->code_compta_fournisseur = $obj->code_compta_fournisseur;
290 $companystatic->fournisseur = $obj->fournisseur;
291 $companystatic->logo = $obj->logo;
292 $companystatic->email = $obj->email;
293 $companystatic->entity = $obj->entity;
294 $companystatic->canvas = $obj->canvas;
295 $companystatic->status = $obj->thirdpartystatus;
296
297 print '<table class="nobordernopadding"><tr class="nocellnopadd">';
298 print '<td width="96" class="nobordernopadding nowraponall">';
299 print $projectstatic->getNomUrl(1);
300 print '</td>';
301
302 print '<td width="16" class="nobordernopadding nowrap">';
303 print '&nbsp;';
304 print '</td>';
305
306 print '<td width="16" class="right nobordernopadding hideonsmartphone">';
307 $filename = dol_sanitizeFileName($obj->ref);
308 $filedir = $conf->project->dir_output.'/'.dol_sanitizeFileName($obj->ref);
309 $urlsource = $_SERVER['PHP_SELF'].'?id='.$obj->rowid;
310 print $formfile->getDocumentsLink($projectstatic->element, $filename, $filedir);
311 print '</td></tr></table>';
312
313 print '</td>';
314
315 // Label
316 print '<td class="tdoverflowmax175" title="'.dol_escape_htmltag($obj->title).'">';
317 print dol_escape_htmltag($projectstatic->title);
318 print '</td>';
319
320 // Thirdparty
321 print '<td class="tdoverflowmax125" title="'.dol_escape_htmltag($companystatic->name).'">';
322 if ($companystatic->id > 0) {
323 print $companystatic->getNomUrl(1, 'company', 16);
324 }
325 print '</td>';
326
327 // Date
328 $datem = $db->jdate($obj->datem);
329 print '<td class="center" title="'.dol_escape_htmltag($langs->trans("DateModification").': '.dol_print_date($datem, 'dayhour', 'tzuserrel')).'">';
330 print dol_print_date($datem, 'day', 'tzuserrel');
331 print '</td>';
332
333 // Status
334 print '<td class="right">'.$projectstatic->LibStatut($obj->status, 3).'</td>';
335 print '</tr>';
336 $i++;
337 }
338 } else {
339 print '<tr><td colspan="4"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
340 }
341
342 finishSimpleTable(true);
343} else {
344 dol_print_error($db);
345}
346
347
348$companystatic = new Societe($db); // We need a clean new object for next loop because current one has some properties set.
349
350if (empty($sortfield)) {
351 $sortfield = 'nb';
352 $sortorder = 'desc';
353}
354
355// List of open projects per thirdparty
356$sql = "SELECT COUNT(p.rowid) as nb, SUM(p.opp_amount)";
357$sql .= ", s.rowid as socid, s.nom as name, s.name_alias";
358$sql .= ", s.code_client, s.code_compta, s.client";
359$sql .= ", s.code_fournisseur, s.code_compta_fournisseur, s.fournisseur";
360$sql .= ", s.logo, s.email, s.entity";
361$sql .= ", s.canvas, s.status";
362$sql .= " FROM ".MAIN_DB_PREFIX."projet as p";
363$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on p.fk_soc = s.rowid";
364$sql .= " WHERE p.entity IN (".getEntity('project').")";
365$sql .= " AND p.fk_statut = 1";
366if ($mine || !$user->hasRight('projet', 'all', 'lire')) {
367 $sql .= " AND p.rowid IN (".$db->sanitize($projectsListId).")"; // If we have this test true, it also means projectset is not 2
368}
369if ($socid > 0) {
370 $sql .= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".((int) $socid).")";
371}
372$sql .= " GROUP BY s.rowid, s.nom, s.name_alias, s.code_client, s.code_compta, s.client, s.code_fournisseur, s.code_compta_fournisseur, s.fournisseur, s.logo, s.email, s.entity, s.canvas, s.status";
373$sql .= $db->order($sortfield, $sortorder);
374//$sql .= $db->plimit($max + 1, 0);
375
376$resql = $db->query($sql);
377if ($resql) {
378 $num = $db->num_rows($resql);
379 $i = 0;
380 $othernb = 0;
381
382 if ($num) {
383 // Open project per thirdparty
384 print '<div class="div-table-responsive-no-min">';
385 print '<table class="noborder centpercent">';
386 print '<tr class="liste_titre">';
387 print_liste_field_titre("OpenedProjectsByThirdparties", $_SERVER["PHP_SELF"], "", "", "", '', $sortfield, $sortorder);
388 print_liste_field_titre("Number", $_SERVER["PHP_SELF"], "nb", "", "", '', $sortfield, $sortorder, 'right ');
389 print "</tr>\n";
390 }
391
392 while ($i < $num) {
393 $obj = $db->fetch_object($resql);
394
395 if ($i >= $max) {
396 $othernb += $obj->nb;
397 $i++;
398 continue;
399 }
400
401 print '<tr class="oddeven">';
402 print '<td class="nowraponall tdoverflowmax100">';
403 if ($obj->socid > 0) {
404 $companystatic->id = $obj->socid;
405 $companystatic->name = $obj->name;
406 $companystatic->name_alias = $obj->name_alias;
407 $companystatic->code_client = $obj->code_client;
408 $companystatic->code_compta = $obj->code_compta;
409 $companystatic->code_compta_client = $obj->code_compta;
410 $companystatic->client = $obj->client;
411 $companystatic->code_fournisseur = $obj->code_fournisseur;
412 $companystatic->code_compta_fournisseur = $obj->code_compta_fournisseur;
413 $companystatic->fournisseur = $obj->fournisseur;
414 $companystatic->logo = $obj->logo;
415 $companystatic->email = $obj->email;
416 $companystatic->entity = $obj->entity;
417 $companystatic->canvas = $obj->canvas;
418 $companystatic->status = $obj->status;
419
420 print $companystatic->getNomUrl(1);
421 } else {
422 print $langs->trans("OthersNotLinkedToThirdParty");
423 }
424 print '</td>';
425 print '<td class="right">';
426 if ($obj->socid) {
427 print '<a href="'.DOL_URL_ROOT.'/projet/list.php?socid='.$obj->socid.'&search_status=1">'.$obj->nb.'</a>';
428 } else {
429 print '<a href="'.DOL_URL_ROOT.'/projet/list.php?search_societe='.urlencode('^$').'&search_status=1">'.$obj->nb.'</a>';
430 }
431 print '</td>';
432 print "</tr>\n";
433
434 $i++;
435 }
436 if ($othernb) {
437 print '<tr class="oddeven">';
438 print '<td class="nowrap">';
439 print '<span class="opacitymedium">'.$langs->trans("More").'...</span>';
440 print '</td>';
441 print '<td class="nowrap right">';
442 print $othernb;
443 print '</td>';
444 print "</tr>\n";
445 }
446
447 if ($num) {
448 print "</table>";
449 print '</div>';
450 }
451
452 $db->free($resql);
453} else {
454 dol_print_error($db);
455}
456
457if ((!getDolGlobalInt('PROJECT_USE_OPPORTUNITIES') || getDolGlobalInt('PROJECT_SHOW_OPEN_PROJECTS_LIST_ON_PROJECT_AREA')) && !getDolGlobalInt('PROJECT_HIDE_OPEN_PROJECTS_LIST_ON_PROJECT_AREA')) {
458 // This list is surely very long and useless when we are using opportunities, so we hide it for this use case, but we allow to show it if
459 // we really want it and to allow interface backward compatibility.
460 print '<br>';
461
462 print_projecttasks_array($db, $form, $socid, $projectsListId, 0, 1, $listofoppstatus, array());
463}
464
465print '</div></div></div>';
466
467$parameters = array('user' => $user);
468$reshook = $hookmanager->executeHooks('dashboardProjects', $parameters, $projectstatic); // Note that $action and $object may have been modified by hook
469
470// End of page
471llxFooter();
472$db->close();
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete='resolve', $idforemptyvalue='-1', $morecss='')
Convert a html select field into an ajax combobox.
Definition ajax.lib.php:475
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
Class to offer components to list and upload files.
Class to manage generation of HTML components Only common components must be here.
Class to manage hooks.
Class to manage projects.
Class to manage third parties objects (customers, suppliers, prospects...)
dol_set_user_param($db, $conf, &$user, $tab)
Save personal parameter.
finishSimpleTable($addLineBreak=false)
Add the correct HTML close tags for "startSimpleTable(...)" (use after the last table line)
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
print_liste_field_titre($name, $file="", $field="", $begin="", $param="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an array.
print_barre_liste($title, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $selectlimitsuffix=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0)
Clean a string to use it as a file name.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
startSimpleTable($header, $link="", $arguments="", $emptyColumns=0, $number=-1, $pictofulllist='')
Start a table with headers and a optional clickable number (don't forget to use "finishSimpleTable()"...
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
print_projecttasks_array($db, $form, $socid, $projectsListId, $mytasks=0, $status=-1, $listofoppstatus=array(), $hiddenfields=array(), $max=0)
Return HTML table with list of projects and number of opened tasks.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.