dolibarr 21.0.0-beta
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 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
28// Load Dolibarr environment
29require '../main.inc.php';
30require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
31require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
32require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
33require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
34require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
35
44// Load translation files required by the page
45$langs->loadLangs(array('projects', 'companies'));
46
47$hookmanager = new HookManager($db);
48
49// Initialize a technical object to manage hooks. Note that conf->hooks_modules contains array
50$hookmanager->initHooks(array('projectsindex'));
51
52$action = GETPOST('action', 'aZ09');
53$search_project_user = GETPOST('search_project_user');
54$mine = (GETPOST('mode', 'aZ09') == 'mine' || $search_project_user == $user->id) ? 1 : 0;
55if ($mine == 0 && $search_project_user === '') {
56 $search_project_user = getDolGlobalString('MAIN_SEARCH_PROJECT_USER_PROJECTSINDEX');
57}
58if ($search_project_user == $user->id) {
59 $mine = 1;
60}
61
62$sortfield = GETPOST('sortfield', 'aZ09comma');
63$sortorder = GETPOST('sortorder', 'aZ09comma');
64
65$max = getDolGlobalInt('MAIN_SIZE_SHORTLIST_LIMIT', 5);
66
67// Security check
68$socid = 0;
69//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.
70if (!$user->hasRight('projet', 'lire')) {
72}
73
74
75/*
76 * Actions
77 */
78
79$parameters = array();
80$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
81if ($reshook < 0) {
82 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
83}
84if (empty($reshook)) {
85 if ($action == 'refresh_search_project_user' && $user->hasRight('projet', 'lire')) {
86 $search_project_user = GETPOSTINT('search_project_user');
87 $tabparam = array("MAIN_SEARCH_PROJECT_USER_PROJECTSINDEX" => $search_project_user);
88
89 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
90 $result = dol_set_user_param($db, $conf, $user, $tabparam);
91 }
92}
93
94
95/*
96 * View
97 */
98
99$companystatic = new Societe($db);
100$projectstatic = new Project($db);
101$form = new Form($db);
102$formfile = new FormFile($db);
103
104$projectset = ($mine ? $mine : (!$user->hasRight('projet', 'all', 'lire') ? 0 : 2));
105$projectsListId = $projectstatic->getProjectsAuthorizedForUser($user, $projectset, 1);
106//var_dump($projectsListId);
107
108
109$title = $langs->trans('ProjectsArea');
110
111$help_url = 'EN:Module_Projects|FR:Module_Projets|ES:M&oacute;dulo_Proyectos|DE:Modul_Projekte';
112
113llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-project page-dashboard');
114
115
116//if ($mine) $title=$langs->trans("MyProjectsArea");
117
118
119// Title for combo list see all projects
120$titleall = $langs->trans("AllAllowedProjects");
121if ($user->hasRight('projet', 'all', 'lire') && !$socid) {
122 $titleall = $langs->trans("AllProjects");
123} else {
124 $titleall = $langs->trans("AllAllowedProjects").'<br><br>';
125}
126
127$morehtml = '';
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 $tooltiphelp = $langs->trans("MyProjectsDesc");
142} else {
143 if ($user->hasRight('projet', 'all', 'lire') && !$socid) {
144 $tooltiphelp = $langs->trans("ProjectsDesc");
145 } else {
146 $tooltiphelp = $langs->trans("ProjectsPublicDesc");
147 }
148}
149
150print_barre_liste($form->textwithpicto($title, $tooltiphelp), 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';
155$listofoppstatus = array(); $listofopplabel = array(); $listofoppcode = array(); $colorseries = array();
156$sql = "SELECT cls.rowid, cls.code, cls.percent, cls.label";
157$sql .= " FROM ".MAIN_DB_PREFIX."c_lead_status as cls";
158$sql .= " WHERE active=1";
159$resql = $db->query($sql);
160if ($resql) {
161 $num = $db->num_rows($resql);
162 $i = 0;
163
164 while ($i < $num) {
165 $objp = $db->fetch_object($resql);
166 $listofoppstatus[$objp->rowid] = $objp->percent;
167 $listofopplabel[$objp->rowid] = $objp->label; // default label if translation from "OppStatus".code not found.
168 $listofoppcode[$objp->rowid] = $objp->code;
169 switch ($objp->code) {
170 case 'PROSP':
171 $colorseries[$objp->rowid] = "-".$badgeStatus0;
172 break;
173 case 'QUAL':
174 $colorseries[$objp->rowid] = "-".$badgeStatus1;
175 break;
176 case 'PROPO':
177 $colorseries[$objp->rowid] = $badgeStatus1;
178 break;
179 case 'NEGO':
180 $colorseries[$objp->rowid] = $badgeStatus4;
181 break;
182 case 'LOST':
183 $colorseries[$objp->rowid] = $badgeStatus9;
184 break;
185 case 'WON':
186 $colorseries[$objp->rowid] = $badgeStatus6;
187 break;
188 default:
189 $colorseries[$objp->rowid] = $badgeStatus2;
190 break;
191 }
192 $i++;
193 }
194} else {
195 dol_print_error($db);
196}
197//var_dump($listofoppcode);
198
199
200print '<div class="fichecenter">';
201
202print '<div class="twocolumns">';
203
204print '<div class="firstcolumn fichehalfleft boxhalfleft" id="boxhalfleft">';
205
206
207// Statistics
208include DOL_DOCUMENT_ROOT.'/projet/graph_opportunities.inc.php';
209
210// List of draft projects
211print_projecttasks_array($db, $form, $socid, $projectsListId, 0, 0, $listofoppstatus, array('projectlabel', 'plannedworkload', 'declaredprogress', 'prospectionstatus', 'projectstatus'), $max);
212
213
214print '</div><div class="secondcolumn fichehalfright boxhalfright" id="boxhalfright">';
215
216
217// Latest modified projects
218$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";
219$sql .= ", s.rowid as socid, s.nom as name, s.name_alias";
220$sql .= ", s.code_client, s.code_compta, s.client";
221$sql .= ", s.code_fournisseur, s.code_compta_fournisseur, s.fournisseur";
222$sql .= ", s.logo, s.email, s.entity";
223$sql .= ", s.canvas, s.status as thirdpartystatus";
224$sql .= " FROM ".MAIN_DB_PREFIX."projet as p";
225$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on p.fk_soc = s.rowid";
226$sql .= " WHERE p.entity IN (".getEntity('project').")";
227if ($mine || !$user->hasRight('projet', 'all', 'lire')) {
228 $sql .= " AND p.rowid IN (".$db->sanitize($projectsListId).")"; // If we have this test true, it also means projectset is not 2
229}
230if ($socid) {
231 $sql .= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".((int) $socid).")";
232}
233$sql .= " ORDER BY p.tms DESC";
234$sql .= $db->plimit($max, 0);
235
236$resql = $db->query($sql);
237if ($resql) {
238 startSimpleTable($langs->trans("LatestModifiedProjects", $max), "projet/list.php", "sortfield=p.tms&sortorder=DESC", 3, -1, 'project');
239
240 $num = $db->num_rows($resql);
241
242 if ($num) {
243 $i = 0;
244 while ($i < $num) {
245 $obj = $db->fetch_object($resql);
246
247 print '<tr class="oddeven">';
248 print '<td class="nowrap">';
249
250 $projectstatic->id = $obj->rowid;
251 $projectstatic->ref = $obj->ref;
252 $projectstatic->title = $obj->title;
253 $projectstatic->thirdparty_name = $obj->name;
254 $projectstatic->status = $obj->status;
255 $projectstatic->date_start = $db->jdate($obj->date_start);
256 $projectstatic->date_end = $db->jdate($obj->date_end);
257
258 $companystatic->id = $obj->socid;
259 $companystatic->name = $obj->name;
260 $companystatic->name_alias = $obj->name_alias;
261 //$companystatic->code_client = $obj->code_client;
262 $companystatic->code_compta = $obj->code_compta;
263 $companystatic->code_compta_client = $obj->code_compta;
264 $companystatic->client = $obj->client;
265 //$companystatic->code_fournisseur = $obj->code_fournisseur;
266 $companystatic->code_compta_fournisseur = $obj->code_compta_fournisseur;
267 $companystatic->fournisseur = $obj->fournisseur;
268 $companystatic->logo = $obj->logo;
269 $companystatic->email = $obj->email;
270 $companystatic->entity = $obj->entity;
271 $companystatic->canvas = $obj->canvas;
272 $companystatic->status = $obj->thirdpartystatus;
273
274 print '<table class="nobordernopadding"><tr class="nocellnopadd">';
275 print '<td width="96" class="nobordernopadding nowraponall">';
276 print $projectstatic->getNomUrl(1);
277 print '</td>';
278
279 print '<td width="16" class="nobordernopadding nowrap">';
280 print '&nbsp;';
281 print '</td>';
282
283 print '<td width="16" class="right nobordernopadding hideonsmartphone">';
284 $filename = dol_sanitizeFileName($obj->ref);
285 $filedir = $conf->projet->dir_output.'/'.dol_sanitizeFileName($obj->ref);
286 $urlsource = $_SERVER['PHP_SELF'].'?id='.$obj->rowid;
287 print $formfile->getDocumentsLink($projectstatic->element, $filename, $filedir);
288 print '</td></tr></table>';
289
290 print '</td>';
291
292 // Label
293 print '<td class="tdoverflowmax150" title="'.dol_escape_htmltag($obj->title).'">';
294 print dol_escape_htmltag($projectstatic->title);
295 print '</td>';
296
297 // Thirdparty
298 print '<td class="tdoverflowmax150" title="'.dol_escape_htmltag($companystatic->name).'">';
299 if ($companystatic->id > 0) {
300 print $companystatic->getNomUrl(1, 'company', 16);
301 }
302 print '</td>';
303
304 // Date
305 $datem = $db->jdate($obj->datem);
306 print '<td class="center" title="'.dol_escape_htmltag($langs->trans("DateModification").': '.dol_print_date($datem, 'dayhour', 'tzuserrel')).'">';
307 print dol_print_date($datem, 'day', 'tzuserrel');
308 print '</td>';
309
310 // Status
311 print '<td class="right">'.$projectstatic->LibStatut($obj->status, 3).'</td>';
312 print '</tr>';
313 $i++;
314 }
315 } else {
316 print '<tr><td colspan="4"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
317 }
318
319 finishSimpleTable(true);
320} else {
321 dol_print_error($db);
322}
323
324
325$companystatic = new Societe($db); // We need a clean new object for next loop because current one has some properties set.
326
327if (empty($sortfield)) {
328 $sortfield = 'nb';
329 $sortorder = 'desc';
330}
331
332// List of open projects per thirdparty
333$sql = "SELECT COUNT(p.rowid) as nb, SUM(p.opp_amount)";
334$sql .= ", s.rowid as socid, s.nom as name, s.name_alias";
335$sql .= ", s.code_client, s.code_compta, s.client";
336$sql .= ", s.code_fournisseur, s.code_compta_fournisseur, s.fournisseur";
337$sql .= ", s.logo, s.email, s.entity";
338$sql .= ", s.canvas, s.status";
339$sql .= " FROM ".MAIN_DB_PREFIX."projet as p";
340$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on p.fk_soc = s.rowid";
341$sql .= " WHERE p.entity IN (".getEntity('project').")";
342$sql .= " AND p.fk_statut = 1";
343if ($mine || !$user->hasRight('projet', 'all', 'lire')) {
344 $sql .= " AND p.rowid IN (".$db->sanitize($projectsListId).")"; // If we have this test true, it also means projectset is not 2
345}
346if ($socid > 0) {
347 $sql .= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".((int) $socid).")";
348}
349$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";
350$sql .= $db->order($sortfield, $sortorder);
351//$sql .= $db->plimit($max + 1, 0);
352
353$resql = $db->query($sql);
354if ($resql) {
355 $num = $db->num_rows($resql);
356 $i = 0;
357 $othernb = 0;
358
359 if ($num) {
360 // Open project per thirdparty
361 print '<div class="div-table-responsive-no-min">';
362 print '<table class="noborder centpercent">';
363 print '<tr class="liste_titre">';
364 print_liste_field_titre("OpenedProjectsByThirdparties", $_SERVER["PHP_SELF"], "", "", "", '', $sortfield, $sortorder);
365 print_liste_field_titre("Number", $_SERVER["PHP_SELF"], "nb", "", "", '', $sortfield, $sortorder, 'right ');
366 print "</tr>\n";
367 }
368
369 while ($i < $num) {
370 $obj = $db->fetch_object($resql);
371
372 if ($i >= $max) {
373 $othernb += $obj->nb;
374 $i++;
375 continue;
376 }
377
378 print '<tr class="oddeven">';
379 print '<td class="nowraponall tdoverflowmax100">';
380 if ($obj->socid > 0) {
381 $companystatic->id = $obj->socid;
382 $companystatic->name = $obj->name;
383 $companystatic->name_alias = $obj->name_alias;
384 $companystatic->code_client = $obj->code_client;
385 $companystatic->code_compta = $obj->code_compta;
386 $companystatic->code_compta_client = $obj->code_compta;
387 $companystatic->client = $obj->client;
388 $companystatic->code_fournisseur = $obj->code_fournisseur;
389 $companystatic->code_compta_fournisseur = $obj->code_compta_fournisseur;
390 $companystatic->fournisseur = $obj->fournisseur;
391 $companystatic->logo = $obj->logo;
392 $companystatic->email = $obj->email;
393 $companystatic->entity = $obj->entity;
394 $companystatic->canvas = $obj->canvas;
395 $companystatic->status = $obj->status;
396
397 print $companystatic->getNomUrl(1);
398 } else {
399 print $langs->trans("OthersNotLinkedToThirdParty");
400 }
401 print '</td>';
402 print '<td class="right">';
403 if ($obj->socid) {
404 print '<a href="'.DOL_URL_ROOT.'/projet/list.php?socid='.$obj->socid.'&search_status=1">'.$obj->nb.'</a>';
405 } else {
406 print '<a href="'.DOL_URL_ROOT.'/projet/list.php?search_societe='.urlencode('^$').'&search_status=1">'.$obj->nb.'</a>';
407 }
408 print '</td>';
409 print "</tr>\n";
410
411 $i++;
412 }
413 if ($othernb) {
414 print '<tr class="oddeven">';
415 print '<td class="nowrap">';
416 print '<span class="opacitymedium">'.$langs->trans("More").'...</span>';
417 print '</td>';
418 print '<td class="nowrap right">';
419 print $othernb;
420 print '</td>';
421 print "</tr>\n";
422 }
423
424 if ($num) {
425 print "</table>";
426 print '</div>';
427 }
428
429 $db->free($resql);
430} else {
431 dol_print_error($db);
432}
433
434if ((!getDolGlobalInt('PROJECT_USE_OPPORTUNITIES') || getDolGlobalInt('PROJECT_SHOW_OPEN_PROJECTS_LIST_ON_PROJECT_AREA')) && !getDolGlobalInt('PROJECT_HIDE_OPEN_PROJECTS_LIST_ON_PROJECT_AREA')) {
435 // 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
436 // we really want it and to allow interface backward compatibility.
437 print '<br>';
438
439 print_projecttasks_array($db, $form, $socid, $projectsListId, 0, 1, $listofoppstatus, array());
440}
441
442print '</div></div></div>';
443
444$parameters = array('user' => $user);
445$reshook = $hookmanager->executeHooks('dashboardProjects', $parameters, $projectstatic); // Note that $action and $object may have been modified by hook
446
447// End of page
448llxFooter();
449$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
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...)
llxFooter()
Footer empty.
Definition document.php:107
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_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
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.