dolibarr 21.0.3
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 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 = '';
129$morehtml .= '<form name="projectform" method="POST" action="'.$_SERVER["PHP_SELF"].'">';
130$morehtml .= '<input type="hidden" name="token" value="'.newToken().'">';
131$morehtml .= '<input type="hidden" name="action" value="refresh_search_project_user">';
132
133$morehtml .= '<SELECT name="search_project_user" id="search_project_user">';
134$morehtml .= '<option name="all" value="0"'.($mine ? '' : ' selected').'>'.$titleall.'</option>';
135$morehtml .= '<option name="mine" value="'.$user->id.'"'.(($search_project_user == $user->id) ? ' selected' : '').'>'.$langs->trans("ProjectsImContactFor").'</option>';
136$morehtml .= '</SELECT>';
137$morehtml .= ajax_combobox("search_project_user", array(), 0, 0, 'resolve', '-1', 'small');
138$morehtml .= '<input type="submit" class="button smallpaddingimp" name="refresh" value="'.$langs->trans("Refresh").'">';
139$morehtml .= '</form>';
140
141if ($mine) {
142 $htmltooltip = $langs->trans("MyProjectsDesc");
143} else {
144 if ($user->hasRight('projet', 'all', 'lire') && !$socid) {
145 $htmltooltip = $langs->trans("ProjectsDesc");
146 } else {
147 $htmltooltip = $langs->trans("ProjectsPublicDesc");
148 }
149}
150
151print_barre_liste($form->textwithpicto($title, $htmltooltip), 0, $_SERVER["PHP_SELF"], '', '', '', '', 0, -1, 'project', 0, $morehtml);
152
153
154// Get list of ponderated percent and colors for each status
155include DOL_DOCUMENT_ROOT.'/theme/'.$conf->theme.'/theme_vars.inc.php';
156// Available from theme_vars:
157'
158@phan-var-force string $badgeStatus0
159@phan-var-force string $badgeStatus1
160@phan-var-force string $badgeStatus2
161@phan-var-force string $badgeStatus3
162@phan-var-force string $badgeStatus4
163@phan-var-force string $badgeStatus5
164@phan-var-force string $badgeStatus6
165@phan-var-force string $badgeStatus7
166@phan-var-force string $badgeStatus8
167@phan-var-force string $badgeStatus9
168';
169$listofoppstatus = array();
170$listofopplabel = array();
171$listofoppcode = array();
172$colorseries = array();
173$sql = "SELECT cls.rowid, cls.code, cls.percent, cls.label";
174$sql .= " FROM ".MAIN_DB_PREFIX."c_lead_status as cls";
175$sql .= " WHERE active=1";
176$resql = $db->query($sql);
177if ($resql) {
178 $num = $db->num_rows($resql);
179 $i = 0;
180
181 while ($i < $num) {
182 $objp = $db->fetch_object($resql);
183 $listofoppstatus[$objp->rowid] = $objp->percent;
184 $listofopplabel[$objp->rowid] = $objp->label; // default label if translation from "OppStatus".code not found.
185 $listofoppcode[$objp->rowid] = $objp->code;
186 switch ($objp->code) {
187 case 'PROSP':
188 $colorseries[$objp->rowid] = "-".$badgeStatus0;
189 break;
190 case 'QUAL':
191 $colorseries[$objp->rowid] = "-".$badgeStatus1;
192 break;
193 case 'PROPO':
194 $colorseries[$objp->rowid] = $badgeStatus1;
195 break;
196 case 'NEGO':
197 $colorseries[$objp->rowid] = $badgeStatus4;
198 break;
199 case 'LOST':
200 $colorseries[$objp->rowid] = $badgeStatus9;
201 break;
202 case 'WON':
203 $colorseries[$objp->rowid] = $badgeStatus6;
204 break;
205 default:
206 $colorseries[$objp->rowid] = $badgeStatus2;
207 break;
208 }
209 $i++;
210 }
211} else {
212 dol_print_error($db);
213}
214//var_dump($listofoppcode);
215
216
217print '<div class="fichecenter">';
218
219print '<div class="twocolumns">';
220
221print '<div class="firstcolumn fichehalfleft boxhalfleft" id="boxhalfleft">';
222
223
224// Statistics
225include DOL_DOCUMENT_ROOT.'/projet/graph_opportunities.inc.php';
226
227// List of draft projects
228print_projecttasks_array($db, $form, $socid, $projectsListId, 0, 0, $listofoppstatus, array('projectlabel', 'plannedworkload', 'declaredprogress', 'prospectionstatus', 'projectstatus'), $max);
229
230
231print '</div><div class="secondcolumn fichehalfright boxhalfright" id="boxhalfright">';
232
233
234// Latest modified projects
235$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";
236$sql .= ", s.rowid as socid, s.nom as name, s.name_alias";
237$sql .= ", s.code_client, s.code_compta, s.client";
238$sql .= ", s.code_fournisseur, s.code_compta_fournisseur, s.fournisseur";
239$sql .= ", s.logo, s.email, s.entity";
240$sql .= ", s.canvas, s.status as thirdpartystatus";
241$sql .= " FROM ".MAIN_DB_PREFIX."projet as p";
242$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on p.fk_soc = s.rowid";
243$sql .= " WHERE p.entity IN (".getEntity('project').")";
244if ($mine || !$user->hasRight('projet', 'all', 'lire')) {
245 $sql .= " AND p.rowid IN (".$db->sanitize($projectsListId).")"; // If we have this test true, it also means projectset is not 2
246}
247if ($socid) {
248 $sql .= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".((int) $socid).")";
249}
250$sql .= " ORDER BY p.tms DESC";
251$sql .= $db->plimit($max, 0);
252
253$resql = $db->query($sql);
254if ($resql) {
255 startSimpleTable($langs->trans("LatestModifiedProjects", $max), "projet/list.php", "sortfield=p.tms&sortorder=DESC", 3, -1, 'project');
256
257 $num = $db->num_rows($resql);
258
259 if ($num) {
260 $i = 0;
261 while ($i < $num) {
262 $obj = $db->fetch_object($resql);
263
264 print '<tr class="oddeven">';
265 print '<td class="nowrap">';
266
267 $projectstatic->id = $obj->rowid;
268 $projectstatic->ref = $obj->ref;
269 $projectstatic->title = $obj->title;
270 $projectstatic->thirdparty_name = $obj->name;
271 $projectstatic->status = $obj->status;
272 $projectstatic->date_start = $db->jdate($obj->date_start);
273 $projectstatic->date_end = $db->jdate($obj->date_end);
274
275 $companystatic->id = $obj->socid;
276 $companystatic->name = $obj->name;
277 $companystatic->name_alias = $obj->name_alias;
278 //$companystatic->code_client = $obj->code_client;
279 $companystatic->code_compta = $obj->code_compta;
280 $companystatic->code_compta_client = $obj->code_compta;
281 $companystatic->client = $obj->client;
282 //$companystatic->code_fournisseur = $obj->code_fournisseur;
283 $companystatic->code_compta_fournisseur = $obj->code_compta_fournisseur;
284 $companystatic->fournisseur = $obj->fournisseur;
285 $companystatic->logo = $obj->logo;
286 $companystatic->email = $obj->email;
287 $companystatic->entity = $obj->entity;
288 $companystatic->canvas = $obj->canvas;
289 $companystatic->status = $obj->thirdpartystatus;
290
291 print '<table class="nobordernopadding"><tr class="nocellnopadd">';
292 print '<td width="96" class="nobordernopadding nowraponall">';
293 print $projectstatic->getNomUrl(1);
294 print '</td>';
295
296 print '<td width="16" class="nobordernopadding nowrap">';
297 print '&nbsp;';
298 print '</td>';
299
300 print '<td width="16" class="right nobordernopadding hideonsmartphone">';
301 $filename = dol_sanitizeFileName($obj->ref);
302 $filedir = $conf->projet->dir_output.'/'.dol_sanitizeFileName($obj->ref);
303 $urlsource = $_SERVER['PHP_SELF'].'?id='.$obj->rowid;
304 print $formfile->getDocumentsLink($projectstatic->element, $filename, $filedir);
305 print '</td></tr></table>';
306
307 print '</td>';
308
309 // Label
310 print '<td class="tdoverflowmax150" title="'.dol_escape_htmltag($obj->title).'">';
311 print dol_escape_htmltag($projectstatic->title);
312 print '</td>';
313
314 // Thirdparty
315 print '<td class="tdoverflowmax150" title="'.dol_escape_htmltag($companystatic->name).'">';
316 if ($companystatic->id > 0) {
317 print $companystatic->getNomUrl(1, 'company', 16);
318 }
319 print '</td>';
320
321 // Date
322 $datem = $db->jdate($obj->datem);
323 print '<td class="center" title="'.dol_escape_htmltag($langs->trans("DateModification").': '.dol_print_date($datem, 'dayhour', 'tzuserrel')).'">';
324 print dol_print_date($datem, 'day', 'tzuserrel');
325 print '</td>';
326
327 // Status
328 print '<td class="right">'.$projectstatic->LibStatut($obj->status, 3).'</td>';
329 print '</tr>';
330 $i++;
331 }
332 } else {
333 print '<tr><td colspan="4"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
334 }
335
336 finishSimpleTable(true);
337} else {
338 dol_print_error($db);
339}
340
341
342$companystatic = new Societe($db); // We need a clean new object for next loop because current one has some properties set.
343
344if (empty($sortfield)) {
345 $sortfield = 'nb';
346 $sortorder = 'desc';
347}
348
349// List of open projects per thirdparty
350$sql = "SELECT COUNT(p.rowid) as nb, SUM(p.opp_amount)";
351$sql .= ", s.rowid as socid, s.nom as name, s.name_alias";
352$sql .= ", s.code_client, s.code_compta, s.client";
353$sql .= ", s.code_fournisseur, s.code_compta_fournisseur, s.fournisseur";
354$sql .= ", s.logo, s.email, s.entity";
355$sql .= ", s.canvas, s.status";
356$sql .= " FROM ".MAIN_DB_PREFIX."projet as p";
357$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on p.fk_soc = s.rowid";
358$sql .= " WHERE p.entity IN (".getEntity('project').")";
359$sql .= " AND p.fk_statut = 1";
360if ($mine || !$user->hasRight('projet', 'all', 'lire')) {
361 $sql .= " AND p.rowid IN (".$db->sanitize($projectsListId).")"; // If we have this test true, it also means projectset is not 2
362}
363if ($socid > 0) {
364 $sql .= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".((int) $socid).")";
365}
366$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";
367$sql .= $db->order($sortfield, $sortorder);
368//$sql .= $db->plimit($max + 1, 0);
369
370$resql = $db->query($sql);
371if ($resql) {
372 $num = $db->num_rows($resql);
373 $i = 0;
374 $othernb = 0;
375
376 if ($num) {
377 // Open project per thirdparty
378 print '<div class="div-table-responsive-no-min">';
379 print '<table class="noborder centpercent">';
380 print '<tr class="liste_titre">';
381 print_liste_field_titre("OpenedProjectsByThirdparties", $_SERVER["PHP_SELF"], "", "", "", '', $sortfield, $sortorder);
382 print_liste_field_titre("Number", $_SERVER["PHP_SELF"], "nb", "", "", '', $sortfield, $sortorder, 'right ');
383 print "</tr>\n";
384 }
385
386 while ($i < $num) {
387 $obj = $db->fetch_object($resql);
388
389 if ($i >= $max) {
390 $othernb += $obj->nb;
391 $i++;
392 continue;
393 }
394
395 print '<tr class="oddeven">';
396 print '<td class="nowraponall tdoverflowmax100">';
397 if ($obj->socid > 0) {
398 $companystatic->id = $obj->socid;
399 $companystatic->name = $obj->name;
400 $companystatic->name_alias = $obj->name_alias;
401 $companystatic->code_client = $obj->code_client;
402 $companystatic->code_compta = $obj->code_compta;
403 $companystatic->code_compta_client = $obj->code_compta;
404 $companystatic->client = $obj->client;
405 $companystatic->code_fournisseur = $obj->code_fournisseur;
406 $companystatic->code_compta_fournisseur = $obj->code_compta_fournisseur;
407 $companystatic->fournisseur = $obj->fournisseur;
408 $companystatic->logo = $obj->logo;
409 $companystatic->email = $obj->email;
410 $companystatic->entity = $obj->entity;
411 $companystatic->canvas = $obj->canvas;
412 $companystatic->status = $obj->status;
413
414 print $companystatic->getNomUrl(1);
415 } else {
416 print $langs->trans("OthersNotLinkedToThirdParty");
417 }
418 print '</td>';
419 print '<td class="right">';
420 if ($obj->socid) {
421 print '<a href="'.DOL_URL_ROOT.'/projet/list.php?socid='.$obj->socid.'&search_status=1">'.$obj->nb.'</a>';
422 } else {
423 print '<a href="'.DOL_URL_ROOT.'/projet/list.php?search_societe='.urlencode('^$').'&search_status=1">'.$obj->nb.'</a>';
424 }
425 print '</td>';
426 print "</tr>\n";
427
428 $i++;
429 }
430 if ($othernb) {
431 print '<tr class="oddeven">';
432 print '<td class="nowrap">';
433 print '<span class="opacitymedium">'.$langs->trans("More").'...</span>';
434 print '</td>';
435 print '<td class="nowrap right">';
436 print $othernb;
437 print '</td>';
438 print "</tr>\n";
439 }
440
441 if ($num) {
442 print "</table>";
443 print '</div>';
444 }
445
446 $db->free($resql);
447} else {
448 dol_print_error($db);
449}
450
451if ((!getDolGlobalInt('PROJECT_USE_OPPORTUNITIES') || getDolGlobalInt('PROJECT_SHOW_OPEN_PROJECTS_LIST_ON_PROJECT_AREA')) && !getDolGlobalInt('PROJECT_HIDE_OPEN_PROJECTS_LIST_ON_PROJECT_AREA')) {
452 // 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
453 // we really want it and to allow interface backward compatibility.
454 print '<br>';
455
456 print_projecttasks_array($db, $form, $socid, $projectsListId, 0, 1, $listofoppstatus, array());
457}
458
459print '</div></div></div>';
460
461$parameters = array('user' => $user);
462$reshook = $hookmanager->executeHooks('dashboardProjects', $parameters, $projectstatic); // Note that $action and $object may have been modified by hook
463
464// End of page
465llxFooter();
466$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:459
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:87
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:71
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_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).
print_liste_field_titre($name, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an array.
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.