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