dolibarr  13.0.2
card.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2001-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2004-2016 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <https://www.gnu.org/licenses/>.
18  */
19 
26 require '../main.inc.php';
27 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
28 require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
29 require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
30 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
31 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
32 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
33 require_once DOL_DOCUMENT_ROOT.'/core/modules/project/modules_project.php';
34 require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
35 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
36 
37 // Load translation files required by the page
38 $langs->loadLangs(array('projects', 'companies'));
39 
40 $id = GETPOST('id', 'int');
41 $ref = GETPOST('ref', 'alpha');
42 $action = GETPOST('action', 'aZ09');
43 $backtopage = GETPOST('backtopage', 'alpha');
44 $cancel = GETPOST('cancel', 'alpha');
45 $confirm = GETPOST('confirm', 'aZ09');
46 $status = GETPOST('status', 'int');
47 $opp_status = GETPOST('opp_status', 'int');
48 $opp_percent = price2num(GETPOST('opp_percent', 'alpha'));
49 
50 if ($id == '' && $ref == '' && ($action != "create" && $action != "add" && $action != "update" && !$_POST["cancel"])) accessforbidden();
51 
52 $mine = GETPOST('mode') == 'mine' ? 1 : 0;
53 //if (! $user->rights->projet->all->lire) $mine=1; // Special for projects
54 
55 // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
56 $hookmanager->initHooks(array('projectcard', 'globalcard'));
57 
58 $object = new Project($db);
59 $extrafields = new ExtraFields($db);
60 
61 // Load object
62 //include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Can't use generic include because when creating a project, ref is defined and we dont want error if fetch fails from ref.
63 if ($id > 0 || !empty($ref))
64 {
65  $ret = $object->fetch($id, $ref); // If we create project, ref may be defined into POST but record does not yet exists into database
66  if ($ret > 0) {
67  $object->fetch_thirdparty();
68  if (!empty($conf->global->PROJECT_ALLOW_COMMENT_ON_PROJECT) && method_exists($object, 'fetchComments') && empty($object->comments)) $object->fetchComments();
69  $id = $object->id;
70  }
71 }
72 
73 // Security check
74 $socid = GETPOST('socid', 'int');
75 //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 assignement.
76 $result = restrictedArea($user, 'projet', $object->id, 'projet&project');
77 
78 // fetch optionals attributes and labels
79 $extrafields->fetch_name_optionals_label($object->table_element);
80 
81 $date_start = dol_mktime(0, 0, 0, GETPOST('projectstartmonth', 'int'), GETPOST('projectstartday', 'int'), GETPOST('projectstartyear', 'int'));
82 $date_end = dol_mktime(0, 0, 0, GETPOST('projectendmonth', 'int'), GETPOST('projectendday', 'int'), GETPOST('projectendyear', 'int'));
83 
84 
85 /*
86  * Actions
87  */
88 
89 $parameters = array('id'=>$socid, 'objcanvas'=>$objcanvas);
90 $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
91 if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
92 
93 if (empty($reshook))
94 {
95  // Cancel
96  if ($cancel)
97  {
98  if (GETPOST("comefromclone") == 1)
99  {
100  $result = $object->delete($user);
101  if ($result > 0)
102  {
103  header("Location: index.php");
104  exit;
105  } else {
106  dol_syslog($object->error, LOG_DEBUG);
107  setEventMessages($langs->trans("CantRemoveProject", $langs->transnoentitiesnoconv("ProjectOverview")), null, 'errors');
108  }
109  }
110  if ($backtopage)
111  {
112  header("Location: ".$backtopage);
113  exit;
114  }
115 
116  $action = '';
117  }
118 
119  if ($action == 'add' && $user->rights->projet->creer)
120  {
121  $error = 0;
122  if (!GETPOST('ref'))
123  {
124  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Ref")), null, 'errors');
125  $error++;
126  }
127  if (!GETPOST('title'))
128  {
129  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("ProjectLabel")), null, 'errors');
130  $error++;
131  }
132 
133  if (GETPOST('opp_amount') != '' && !(GETPOST('opp_status') > 0))
134  {
135  $error++;
136  setEventMessages($langs->trans("ErrorOppStatusRequiredIfAmount"), null, 'errors');
137  }
138 
139  // Create with status validated immediatly
140  if (!empty($conf->global->PROJECT_CREATE_NO_DRAFT))
141  {
142  $status = Project::STATUS_VALIDATED;
143  }
144 
145  if (!$error)
146  {
147  $error = 0;
148 
149  $db->begin();
150 
151  $object->ref = GETPOST('ref', 'alphanohtml');
152  $object->title = GETPOST('title', 'alphanohtml');
153  $object->socid = GETPOST('socid', 'int');
154  $object->description = GETPOST('description', 'restricthtml'); // Do not use 'alpha' here, we want field as it is
155  $object->public = GETPOST('public', 'alphanohtml');
156  $object->opp_amount = price2num(GETPOST('opp_amount', 'alphanohtml'));
157  $object->budget_amount = price2num(GETPOST('budget_amount', 'alphanohtml'));
158  $object->date_c = dol_now();
159  $object->date_start = $date_start;
160  $object->date_end = $date_end;
161  $object->statut = $status;
162  $object->opp_status = $opp_status;
163  $object->opp_percent = $opp_percent;
164  $object->usage_opportunity = (GETPOST('usage_opportunity', 'alpha') == 'on' ? 1 : 0);
165  $object->usage_task = (GETPOST('usage_task', 'alpha') == 'on' ? 1 : 0);
166  $object->usage_bill_time = (GETPOST('usage_bill_time', 'alpha') == 'on' ? 1 : 0);
167  $object->usage_organize_event = (GETPOST('usage_organize_event', 'alpha') == 'on' ? 1 : 0);
168 
169  // Fill array 'array_options' with data from add form
170  $ret = $extrafields->setOptionalsFromPost(null, $object);
171  if ($ret < 0) $error++;
172 
173  $result = $object->create($user);
174  if (!$error && $result > 0)
175  {
176  // Add myself as project leader
177  $typeofcontact = 'PROJECTLEADER'; // TODO If use rename this code in dictionary, the add_contact will generate an error.
178  $result = $object->add_contact($user->id, $typeofcontact, 'internal');
179  if ($result < 0)
180  {
181  $langs->load("errors");
182  setEventMessages($object->error, $object->errors, 'errors');
183  $error++;
184  }
185  } else {
186  $langs->load("errors");
187  setEventMessages($object->error, $object->errors, 'errors');
188  $error++;
189  }
190  if (!$error && !empty($object->id) > 0)
191  {
192  // Category association
193  $categories = GETPOST('categories', 'array');
194  $result = $object->setCategories($categories);
195  if ($result < 0) {
196  $langs->load("errors");
197  setEventMessages($object->error, $object->errors, 'errors');
198  $error++;
199  }
200  }
201 
202  if (!$error)
203  {
204  $db->commit();
205 
206  if (!empty($backtopage))
207  {
208  $backtopage = preg_replace('/--IDFORBACKTOPAGE--/', $object->id, $backtopage); // New method to autoselect project after a New on another form object creation
209  $backtopage = $backtopage.'&projectid='.$object->id; // Old method
210  header("Location: ".$backtopage);
211  exit;
212  } else {
213  header("Location:card.php?id=".$object->id);
214  exit;
215  }
216  } else {
217  $db->rollback();
218 
219  $action = 'create';
220  }
221  } else {
222  $action = 'create';
223  }
224  }
225 
226  if ($action == 'update' && !$_POST["cancel"] && $user->rights->projet->creer)
227  {
228  $error = 0;
229 
230  if (empty($ref))
231  {
232  $error++;
233  //$_GET["id"]=$_POST["id"]; // We return on the project card
234  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Ref")), null, 'errors');
235  }
236  if (empty($_POST["title"]))
237  {
238  $error++;
239  //$_GET["id"]=$_POST["id"]; // We return on the project card
240  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("ProjectLabel")), null, 'errors');
241  }
242 
243  $db->begin();
244 
245  if (!$error)
246  {
247  $object->oldcopy = clone $object;
248 
249  $old_start_date = $object->date_start;
250 
251  $object->ref = GETPOST('ref', 'alpha');
252  $object->title = GETPOST('title', 'alphanohtml'); // Do not use 'alpha' here, we want field as it is
253  $object->statut = GETPOST('status', 'int');
254  $object->socid = GETPOST('socid', 'int');
255  $object->description = GETPOST('description', 'restricthtml'); // Do not use 'alpha' here, we want field as it is
256  $object->public = GETPOST('public', 'alpha');
257  $object->date_start = (!GETPOST('projectstart')) ? '' : $date_start;
258  $object->date_end = (!GETPOST('projectend')) ? '' : $date_end;
259  if (GETPOSTISSET('opp_amount')) $object->opp_amount = price2num(GETPOST('opp_amount', 'alpha'));
260  if (GETPOSTISSET('budget_amount')) $object->budget_amount = price2num(GETPOST('budget_amount', 'alpha'));
261  if (GETPOSTISSET('opp_status')) $object->opp_status = $opp_status;
262  if (GETPOSTISSET('opp_percent')) $object->opp_percent = $opp_percent;
263  $object->usage_opportunity = (GETPOST('usage_opportunity', 'alpha') == 'on' ? 1 : 0);
264  $object->usage_task = (GETPOST('usage_task', 'alpha') == 'on' ? 1 : 0);
265  $object->usage_bill_time = (GETPOST('usage_bill_time', 'alpha') == 'on' ? 1 : 0);
266  $object->usage_organize_event = (GETPOST('usage_organize_event', 'alpha') == 'on' ? 1 : 0);
267 
268  // Fill array 'array_options' with data from add form
269  $ret = $extrafields->setOptionalsFromPost(null, $object);
270  if ($ret < 0) $error++;
271  }
272 
273  if ($object->opp_amount && ($object->opp_status <= 0))
274  {
275  $error++;
276  setEventMessages($langs->trans("ErrorOppStatusRequiredIfAmount"), null, 'errors');
277  }
278 
279  if (!$error)
280  {
281  $result = $object->update($user);
282  if ($result < 0)
283  {
284  $error++;
285  if ($result == -4) setEventMessages($langs->trans("ErrorRefAlreadyExists"), null, 'errors');
286  else setEventMessages($object->error, $object->errors, 'errors');
287  } else {
288  // Category association
289  $categories = GETPOST('categories', 'array');
290  $result = $object->setCategories($categories);
291  if ($result < 0)
292  {
293  $error++;
294  setEventMessages($object->error, $object->errors, 'errors');
295  }
296  }
297  }
298 
299  if (!$error)
300  {
301  if (GETPOST("reportdate") && ($object->date_start != $old_start_date))
302  {
303  $result = $object->shiftTaskDate($old_start_date);
304  if ($result < 0)
305  {
306  $error++;
307  setEventMessages($langs->trans("ErrorShiftTaskDate").':'.$object->error, $object->errors, 'errors');
308  }
309  }
310  }
311 
312  // Check if we must change status
313  if (GETPOST('closeproject'))
314  {
315  $resclose = $object->setClose($user);
316  if ($resclose < 0)
317  {
318  $error++;
319  setEventMessages($langs->trans("FailedToCloseProject").':'.$object->error, $object->errors, 'errors');
320  }
321  }
322 
323 
324  if ($error)
325  {
326  $db->rollback();
327  $action = 'edit';
328  } else {
329  $db->commit();
330 
331  if (GETPOST('socid', 'int') > 0) $object->fetch_thirdparty(GETPOST('socid', 'int'));
332  else unset($object->thirdparty);
333  }
334  }
335 
336  // Build doc
337  if ($action == 'builddoc' && $user->rights->projet->creer)
338  {
339  // Save last template used to generate document
340  if (GETPOST('model')) $object->setDocModel($user, GETPOST('model', 'alpha'));
341 
342  $outputlangs = $langs;
343  if (GETPOST('lang_id', 'aZ09'))
344  {
345  $outputlangs = new Translate("", $conf);
346  $outputlangs->setDefaultLang(GETPOST('lang_id', 'aZ09'));
347  }
348  $result = $object->generateDocument($object->model_pdf, $outputlangs);
349  if ($result <= 0)
350  {
351  setEventMessages($object->error, $object->errors, 'errors');
352  $action = '';
353  }
354  }
355 
356  // Delete file in doc form
357  if ($action == 'remove_file' && $user->rights->projet->creer)
358  {
359  if ($object->id > 0)
360  {
361  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
362 
363  $langs->load("other");
364  $upload_dir = $conf->projet->dir_output;
365  $file = $upload_dir.'/'.GETPOST('file');
366  $ret = dol_delete_file($file, 0, 0, 0, $object);
367  if ($ret)
368  setEventMessages($langs->trans("FileWasRemoved", GETPOST('file')), null, 'mesgs');
369  else setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('file')), null, 'errors');
370  $action = '';
371  }
372  }
373 
374 
375  if ($action == 'confirm_validate' && $confirm == 'yes')
376  {
377  $result = $object->setValid($user);
378  if ($result <= 0)
379  {
380  setEventMessages($object->error, $object->errors, 'errors');
381  }
382  }
383 
384  if ($action == 'confirm_close' && $confirm == 'yes')
385  {
386  $result = $object->setClose($user);
387  if ($result <= 0)
388  {
389  setEventMessages($object->error, $object->errors, 'errors');
390  }
391  }
392 
393  if ($action == 'confirm_reopen' && $confirm == 'yes')
394  {
395  $result = $object->setValid($user);
396  if ($result <= 0)
397  {
398  setEventMessages($object->error, $object->errors, 'errors');
399  }
400  }
401 
402  if ($action == 'confirm_delete' && GETPOST("confirm") == "yes" && $user->rights->projet->supprimer)
403  {
404  $object->fetch($id);
405  $result = $object->delete($user);
406  if ($result > 0)
407  {
408  setEventMessages($langs->trans("RecordDeleted"), null, 'mesgs');
409  header("Location: list.php?restore_lastsearch_values=1");
410  exit;
411  } else {
412  dol_syslog($object->error, LOG_DEBUG);
413  setEventMessages($object->error, $object->errors, 'errors');
414  }
415  }
416 
417  if ($action == 'confirm_clone' && $user->rights->projet->creer && $confirm == 'yes')
418  {
419  $clone_contacts = GETPOST('clone_contacts') ? 1 : 0;
420  $clone_tasks = GETPOST('clone_tasks') ? 1 : 0;
421  $clone_project_files = GETPOST('clone_project_files') ? 1 : 0;
422  $clone_task_files = GETPOST('clone_task_files') ? 1 : 0;
423  $clone_notes = GETPOST('clone_notes') ? 1 : 0;
424  $move_date = GETPOST('move_date') ? 1 : 0;
425  $clone_thirdparty = GETPOST('socid', 'int') ?GETPOST('socid', 'int') : 0;
426 
427  $result = $object->createFromClone($user, $object->id, $clone_contacts, $clone_tasks, $clone_project_files, $clone_task_files, $clone_notes, $move_date, 0, $clone_thirdparty);
428  if ($result <= 0)
429  {
430  setEventMessages($object->error, $object->errors, 'errors');
431  } else {
432  // Load new object
433  $newobject = new Project($db);
434  $newobject->fetch($result);
435  $newobject->fetch_optionals();
436  $newobject->fetch_thirdparty(); // Load new object
437  $object = $newobject;
438  $action = 'edit';
439  $comefromclone = true;
440  }
441  }
442 
443  // Actions to send emails
444  $triggersendname = 'PROJECT_SENTBYMAIL';
445  $paramname = 'id';
446  $autocopy = 'MAIN_MAIL_AUTOCOPY_PROJECT_TO'; // used to know the automatic BCC to add
447  $trackid = 'proj'.$object->id;
448  include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
449 }
450 
451 
452 /*
453  * View
454  */
455 
456 $form = new Form($db);
457 $formfile = new FormFile($db);
458 $formproject = new FormProjets($db);
459 $userstatic = new User($db);
460 
461 $title = $langs->trans("Project").' - '.$object->ref.($object->thirdparty->name ? ' - '.$object->thirdparty->name : '').($object->title ? ' - '.$object->title : '');
462 if (!empty($conf->global->MAIN_HTML_TITLE) && preg_match('/projectnameonly/', $conf->global->MAIN_HTML_TITLE)) $title = $object->ref.($object->thirdparty->name ? ' - '.$object->thirdparty->name : '').($object->title ? ' - '.$object->title : '');
463 $help_url = "EN:Module_Projects|FR:Module_Projets|ES:M&oacute;dulo_Proyectos";
464 
465 llxHeader("", $title, $help_url);
466 
467 $titleboth = $langs->trans("LeadsOrProjects");
468 $titlenew = $langs->trans("NewLeadOrProject"); // Leads and opportunities by default
469 if ($conf->global->PROJECT_USE_OPPORTUNITIES == 0) {
470  $titleboth = $langs->trans("Projects");
471  $titlenew = $langs->trans("NewProject");
472 }
473 if ($conf->global->PROJECT_USE_OPPORTUNITIES == 2) { // 2 = leads only
474  $titleboth = $langs->trans("Leads");
475  $titlenew = $langs->trans("NewLead");
476 }
477 
478 if ($action == 'create' && $user->rights->projet->creer)
479 {
480  /*
481  * Create
482  */
483 
484  $thirdparty = new Societe($db);
485  if ($socid > 0) $thirdparty->fetch($socid);
486 
487  print load_fiche_titre($titlenew, '', 'project');
488 
489  print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
490  print '<input type="hidden" name="token" value="'.newToken().'">';
491  print '<input type="hidden" name="action" value="add">';
492  print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
493 
495 
496  print '<table class="border centpercent tableforfieldcreate">';
497 
498  $defaultref = '';
499  $modele = empty($conf->global->PROJECT_ADDON) ? 'mod_project_simple' : $conf->global->PROJECT_ADDON;
500 
501  // Search template files
502  $file = ''; $classname = ''; $filefound = 0;
503  $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
504  foreach ($dirmodels as $reldir)
505  {
506  $file = dol_buildpath($reldir."core/modules/project/".$modele.'.php', 0);
507  if (file_exists($file))
508  {
509  $filefound = 1;
510  $classname = $modele;
511  break;
512  }
513  }
514 
515  if ($filefound)
516  {
517  $result = dol_include_once($reldir."core/modules/project/".$modele.'.php');
518  $modProject = new $classname;
519 
520  $defaultref = $modProject->getNextValue($thirdparty, $object);
521  }
522 
523  if (is_numeric($defaultref) && $defaultref <= 0) $defaultref = '';
524 
525  // Ref
526  $suggestedref = ($_POST["ref"] ? $_POST["ref"] : $defaultref);
527  print '<tr><td class="titlefieldcreate"><span class="fieldrequired">'.$langs->trans("Ref").'</span></td><td><input size="12" type="text" name="ref" value="'.dol_escape_htmltag($suggestedref).'">';
528  print ' '.$form->textwithpicto('', $langs->trans("YouCanCompleteRef", $suggestedref));
529  print '</td></tr>';
530 
531  // Label
532  print '<tr><td><span class="fieldrequired">'.$langs->trans("ProjectLabel").'</span></td><td><input class="minwidth500" type="text" name="title" value="'.dol_escape_htmltag(GETPOST("title", 'alphanohtml')).'" autofocus></td></tr>';
533 
534  // Usage (opp, task, bill time, ...)
535  print '<tr><td class="tdtop">';
536  print $langs->trans("Usage");
537  print '</td>';
538  print '<td>';
539  if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES)) {
540  print '<input type="checkbox" id="usage_opportunity" name="usage_opportunity"'.(GETPOSTISSET('usage_opportunity') ? (GETPOST('usage_opportunity', 'alpha') != '' ? ' checked="checked"' : '') : ' checked="checked"').'"> ';
541  $htmltext = $langs->trans("ProjectFollowOpportunity");
542  print '<label for="usage_opportunity">'.$form->textwithpicto($langs->trans("ProjectFollowOpportunity"), $htmltext).'</label>';
543  print '<script>';
544  print '$( document ).ready(function() {
545  jQuery("#usage_opportunity").change(function() {
546  if (jQuery("#usage_opportunity").prop("checked")) {
547  console.log("Show opportunities fields");
548  jQuery(".classuseopportunity").show();
549  } else {
550  console.log("Hide opportunities fields "+jQuery("#usage_opportunity").prop("checked"));
551  jQuery(".classuseopportunity").hide();
552  }
553  });
554  });';
555  print '</script>';
556  print '<br>';
557  }
558  if (empty($conf->global->PROJECT_HIDE_TASKS))
559  {
560  print '<input type="checkbox" id="usage_task" name="usage_task"'.(GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') != '' ? ' checked="checked"' : '') : ' checked="checked"').'"> ';
561  $htmltext = $langs->trans("ProjectFollowTasks");
562  print '<label for="usage_task">'.$form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext).'</label>';
563  print '<br>';
564  }
565  if (empty($conf->global->PROJECT_HIDE_TASKS) && !empty($conf->global->PROJECT_BILL_TIME_SPENT))
566  {
567  print '<input type="checkbox" id="usage_bill_time" name="usage_bill_time"'.(GETPOST('usage_bill_time', 'alpha') != '' ? ' checked="checked"' : '').'"> ';
568  $htmltext = $langs->trans("ProjectBillTimeDescription");
569  print '<label for="usage_bill_time">'.$form->textwithpicto($langs->trans("BillTime"), $htmltext).'</label>';
570  print '<br>';
571  }
572  /*
573  print '<input type="checkbox" name="usage_organize_event"'.(GETPOST('usage_organize_event', 'alpha')!=''?' checked="checked"':'').'"> ';
574  $htmltext = $langs->trans("OrganizeEvent");
575  print $form->textwithpicto($langs->trans("OrganizeEvent"), $htmltext);*/
576  print '</td>';
577  print '</tr>';
578 
579  // Thirdparty
580  if ($conf->societe->enabled)
581  {
582  print '<tr><td>';
583  print (empty($conf->global->PROJECT_THIRDPARTY_REQUIRED) ? '' : '<span class="fieldrequired">');
584  print $langs->trans("ThirdParty");
585  print (empty($conf->global->PROJECT_THIRDPARTY_REQUIRED) ? '' : '</span>');
586  print '</td><td class="maxwidthonsmartphone">';
587  $filteronlist = '';
588  if (!empty($conf->global->PROJECT_FILTER_FOR_THIRDPARTY_LIST)) $filteronlist = $conf->global->PROJECT_FILTER_FOR_THIRDPARTY_LIST;
589  $text = img_picto('', 'company').$form->select_company(GETPOST('socid', 'int'), 'socid', $filteronlist, 'SelectThirdParty', 1, 0, array(), 0, 'minwidth300 widthcentpercentminusxx');
590  if (empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS) && empty($conf->dol_use_jmobile))
591  {
592  $texthelp = $langs->trans("IfNeedToUseOtherObjectKeepEmpty");
593  print $form->textwithtooltip($text.' '.img_help(), $texthelp, 1);
594  } else print $text;
595  if (!GETPOSTISSET('backtopage')) print ' <a href="'.DOL_URL_ROOT.'/societe/card.php?action=create&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create').'"><span class="fa fa-plus-circle valignmiddle paddingleft" title="'.$langs->trans("AddThirdParty").'"></span></a>';
596  print '</td></tr>';
597  }
598 
599  // Status
600  if ($status != '')
601  {
602  print '<tr><td>'.$langs->trans("Status").'</td><td>';
603  print '<input type="hidden" name="status" value="'.$status.'">';
604  print $object->LibStatut($status, 4);
605  print '</td></tr>';
606  }
607 
608  // Visibility
609  print '<tr><td>'.$langs->trans("Visibility").'</td><td class="maxwidthonsmartphone">';
610  $array = array();
611  if (empty($conf->global->PROJECT_DISABLE_PRIVATE_PROJECT)) $array[0] = $langs->trans("PrivateProject");
612  if (empty($conf->global->PROJECT_DISABLE_PUBLIC_PROJECT)) $array[1] = $langs->trans("SharedProject");
613  print $form->selectarray('public', $array, GETPOST('public') ?GETPOST('public') : $object->public, 0, 0, 0, '', 0, 0, 0, '', '', 1);
614  print '</td></tr>';
615 
616  // Date start
617  print '<tr><td>'.$langs->trans("DateStart").'</td><td>';
618  print $form->selectDate(($date_start ? $date_start : ''), 'projectstart', 0, 0, 0, '', 1, 0);
619  print '</td></tr>';
620 
621  // Date end
622  print '<tr><td>'.$langs->trans("DateEnd").'</td><td>';
623  print $form->selectDate(($date_end ? $date_end : -1), 'projectend', 0, 0, 0, '', 1, 0);
624  print '</td></tr>';
625 
626  if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES))
627  {
628  // Opportunity status
629  print '<tr class="classuseopportunity"><td>'.$langs->trans("OpportunityStatus").'</td>';
630  print '<td class="maxwidthonsmartphone">';
631  print $formproject->selectOpportunityStatus('opp_status', GETPOST('opp_status') ?GETPOST('opp_status') : $object->opp_status, 1, 0, 0, 0, '', 0, 1);
632  print '</tr>';
633 
634  // Opportunity probability
635  print '<tr class="classuseopportunity"><td>'.$langs->trans("OpportunityProbability").'</td>';
636  print '<td><input size="5" type="text" id="opp_percent" name="opp_percent" value="'.dol_escape_htmltag(GETPOSTISSET('opp_percent') ? GETPOST('opp_percent') : '').'"><span class="hideonsmartphone"> %</span>';
637  print '<input type="hidden" name="opp_percent_not_set" id="opp_percent_not_set" value="'.dol_escape_htmltag(GETPOSTISSET('opp_percent') ? '0' : '1').'">';
638  print '</td>';
639  print '</tr>';
640 
641  // Opportunity amount
642  print '<tr class="classuseopportunity"><td>'.$langs->trans("OpportunityAmount").'</td>';
643  print '<td><input size="5" type="text" name="opp_amount" value="'.dol_escape_htmltag(GETPOSTISSET('opp_amount') ? GETPOST('opp_amount') : '').'"></td>';
644  print '</tr>';
645  }
646 
647  // Budget
648  print '<tr><td>'.$langs->trans("Budget").'</td>';
649  print '<td><input size="5" type="text" name="budget_amount" value="'.dol_escape_htmltag(GETPOSTISSET('budget_amount') ? GETPOST('budget_amount') : '').'"></td>';
650  print '</tr>';
651 
652  // Description
653  print '<tr><td class="tdtop">'.$langs->trans("Description").'</td>';
654  print '<td>';
655  $doleditor = new DolEditor('description', GETPOST("description", 'restricthtml'), '', 90, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_SOCIETE, ROWS_3, '90%');
656  $doleditor->Create();
657  print '</td></tr>';
658 
659  if ($conf->categorie->enabled) {
660  // Categories
661  print '<tr><td>'.$langs->trans("Categories").'</td><td colspan="3">';
662  $cate_arbo = $form->select_all_categories(Categorie::TYPE_PROJECT, '', 'parent', 64, 0, 1);
663  $arrayselected = GETPOST('categories', 'array');
664  print img_picto('', 'category').$form->multiselectarray('categories', $cate_arbo, $arrayselected, '', 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0);
665  print "</td></tr>";
666  }
667 
668  // Other options
669  $parameters = array();
670  $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
671  print $hookmanager->resPrint;
672  if (empty($reshook))
673  {
674  print $object->showOptionals($extrafields, 'create');
675  }
676 
677  print '</table>';
678 
680 
681  print '<div class="center">';
682  print '<input type="submit" class="button" value="'.$langs->trans("CreateDraft").'">';
683  if (!empty($backtopage))
684  {
685  print ' &nbsp; &nbsp; ';
686  print '<input type="submit" class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
687  } else {
688  print ' &nbsp; &nbsp; ';
689  print '<input type="button" class="button button-cancel" value="'.$langs->trans("Cancel").'" onClick="javascript:history.go(-1)">';
690  }
691  print '</div>';
692 
693  print '</form>';
694 
695  // Change probability from status
696  print '<script type="text/javascript" language="javascript">
697  jQuery(document).ready(function() {
698  function change_percent()
699  {
700  var element = jQuery("#opp_status option:selected");
701  var defaultpercent = element.attr("defaultpercent");
702  /*if (jQuery("#opp_percent_not_set").val() == "") */
703  jQuery("#opp_percent").val(defaultpercent);
704  }
705  /*init_myfunc();*/
706  jQuery("#opp_status").change(function() {
707  change_percent();
708  });
709 
710  jQuery("#usage_task").change(function() {
711  console.log("We click on usage task "+jQuery("#usage_task").is(":checked"));
712  if (! jQuery("#usage_task").is(":checked")) {
713  jQuery("#usage_bill_time").prop("checked", false);
714  }
715  });
716 
717  jQuery("#usage_bill_time").change(function() {
718  console.log("We click on usage to bill time");
719  if (jQuery("#usage_bill_time").is(":checked")) {
720  jQuery("#usage_task").prop("checked", true);
721  }
722  });
723  });
724  </script>';
725 } elseif ($object->id > 0)
726 {
727  /*
728  * Show or edit
729  */
730 
731  $res = $object->fetch_optionals();
732 
733  // To verify role of users
734  $userAccess = $object->restrictedProjectArea($user, 'read');
735  $userWrite = $object->restrictedProjectArea($user, 'write');
736  $userDelete = $object->restrictedProjectArea($user, 'delete');
737  //print "userAccess=".$userAccess." userWrite=".$userWrite." userDelete=".$userDelete;
738 
739 
740  // Confirmation validation
741  if ($action == 'validate')
742  {
743  print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ValidateProject'), $langs->trans('ConfirmValidateProject'), 'confirm_validate', '', 0, 1);
744  }
745  // Confirmation close
746  if ($action == 'close')
747  {
748  print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id, $langs->trans("CloseAProject"), $langs->trans("ConfirmCloseAProject"), "confirm_close", '', '', 1);
749  }
750  // Confirmation reopen
751  if ($action == 'reopen')
752  {
753  print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id, $langs->trans("ReOpenAProject"), $langs->trans("ConfirmReOpenAProject"), "confirm_reopen", '', '', 1);
754  }
755  // Confirmation delete
756  if ($action == 'delete')
757  {
758  $text = $langs->trans("ConfirmDeleteAProject");
759  $task = new Task($db);
760  $taskarray = $task->getTasksArray(0, 0, $object->id, 0, 0);
761  $nboftask = count($taskarray);
762  if ($nboftask) $text .= '<br>'.img_warning().' '.$langs->trans("ThisWillAlsoRemoveTasks", $nboftask);
763  print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id, $langs->trans("DeleteAProject"), $text, "confirm_delete", '', '', 1);
764  }
765 
766  // Clone confirmation
767  if ($action == 'clone')
768  {
769  $formquestion = array(
770  'text' => $langs->trans("ConfirmClone"),
771  array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int') > 0 ?GETPOST('socid', 'int') : $object->socid, 'socid', '', "None", 0, 0, null, 0, 'minwidth200')),
772  array('type' => 'checkbox', 'name' => 'clone_contacts', 'label' => $langs->trans("CloneContacts"), 'value' => true),
773  array('type' => 'checkbox', 'name' => 'clone_tasks', 'label' => $langs->trans("CloneTasks"), 'value' => true),
774  array('type' => 'checkbox', 'name' => 'move_date', 'label' => $langs->trans("CloneMoveDate"), 'value' => true),
775  array('type' => 'checkbox', 'name' => 'clone_notes', 'label' => $langs->trans("CloneNotes"), 'value' => true),
776  array('type' => 'checkbox', 'name' => 'clone_project_files', 'label' => $langs->trans("CloneProjectFiles"), 'value' => false),
777  array('type' => 'checkbox', 'name' => 'clone_task_files', 'label' => $langs->trans("CloneTaskFiles"), 'value' => false)
778  );
779 
780  print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id, $langs->trans("ToClone"), $langs->trans("ConfirmCloneProject"), "confirm_clone", $formquestion, '', 1, 300, 590);
781  }
782 
783 
784  print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
785  print '<input type="hidden" name="token" value="'.newToken().'">';
786  print '<input type="hidden" name="action" value="update">';
787  print '<input type="hidden" name="id" value="'.$object->id.'">';
788  print '<input type="hidden" name="comefromclone" value="'.$comefromclone.'">';
789 
790  $head = project_prepare_head($object);
791 
792  if ($action == 'edit' && $userWrite > 0)
793  {
794  print dol_get_fiche_head($head, 'project', $langs->trans("Project"), 0, ($object->public ? 'projectpub' : 'project'));
795 
796  print '<table class="border centpercent">';
797 
798  // Ref
799  $suggestedref = $object->ref;
800  print '<tr><td class="titlefield fieldrequired">'.$langs->trans("Ref").'</td>';
801  print '<td><input size="12" name="ref" value="'.$suggestedref.'">';
802  print ' '.$form->textwithpicto('', $langs->trans("YouCanCompleteRef", $suggestedref));
803  print '</td></tr>';
804 
805  // Label
806  print '<tr><td class="fieldrequired">'.$langs->trans("ProjectLabel").'</td>';
807  print '<td><input class="quatrevingtpercent" name="title" value="'.dol_escape_htmltag($object->title).'"></td></tr>';
808 
809  // Status
810  print '<tr><td class="fieldrequired">'.$langs->trans("Status").'</td><td>';
811  print '<select class="flat" name="status">';
812  foreach ($object->statuts_short as $key => $val)
813  {
814  print '<option value="'.$key.'"'.((GETPOSTISSET('status') ?GETPOST('status') : $object->statut) == $key ? ' selected="selected"' : '').'>'.$langs->trans($val).'</option>';
815  }
816  print '</select>';
817  print '</td></tr>';
818 
819  // Usage
820  print '<tr><td class="tdtop">';
821  print $langs->trans("Usage");
822  print '</td>';
823  print '<td>';
824  if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES))
825  {
826  print '<input type="checkbox" id="usage_opportunity" name="usage_opportunity"'.(GETPOSTISSET('usage_opportunity') ? (GETPOST('usage_opportunity', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_opportunity ? ' checked="checked"' : '')).'"> ';
827  $htmltext = $langs->trans("ProjectFollowOpportunity");
828  print $form->textwithpicto($langs->trans("ProjectFollowOpportunity"), $htmltext);
829  print '<script>';
830  print '$( document ).ready(function() {
831  jQuery("#usage_opportunity").change(function() {
832  if (jQuery("#usage_opportunity").prop("checked")) {
833  console.log("Show opportunities fields");
834  jQuery(".classuseopportunity").show();
835  } else {
836  console.log("Hide opportunities fields "+jQuery("#usage_opportunity").prop("checked"));
837  jQuery(".classuseopportunity").hide();
838  }
839  });
840  });';
841  print '</script>';
842  print '<br>';
843  }
844  if (empty($conf->global->PROJECT_HIDE_TASKS))
845  {
846  print '<input type="checkbox" name="usage_task"'.(GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_task ? ' checked="checked"' : '')).'"> ';
847  $htmltext = $langs->trans("ProjectFollowTasks");
848  print $form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext);
849  print '<br>';
850  }
851  if (empty($conf->global->PROJECT_HIDE_TASKS) && !empty($conf->global->PROJECT_BILL_TIME_SPENT))
852  {
853  print '<input type="checkbox" name="usage_bill_time"'.(GETPOSTISSET('usage_bill_time') ? (GETPOST('usage_bill_time', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_bill_time ? ' checked="checked"' : '')).'"> ';
854  $htmltext = $langs->trans("ProjectBillTimeDescription");
855  print $form->textwithpicto($langs->trans("BillTime"), $htmltext);
856  print '<br>';
857  }
858  print '</td></tr>';
859 
860  // Thirdparty
861  if ($conf->societe->enabled)
862  {
863  print '<tr><td>';
864  print (empty($conf->global->PROJECT_THIRDPARTY_REQUIRED) ? '' : '<span class="fieldrequired">');
865  print $langs->trans("ThirdParty");
866  print (empty($conf->global->PROJECT_THIRDPARTY_REQUIRED) ? '' : '</span>');
867  print '</td><td>';
868  $filteronlist = '';
869  if (!empty($conf->global->PROJECT_FILTER_FOR_THIRDPARTY_LIST)) $filteronlist = $conf->global->PROJECT_FILTER_FOR_THIRDPARTY_LIST;
870  $text = $form->select_company($object->thirdparty->id, 'socid', $filteronlist, 'None', 1, 0, array(), 0, 'minwidth300');
871  if (empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS) && empty($conf->dol_use_jmobile))
872  {
873  $texthelp = $langs->trans("IfNeedToUseOtherObjectKeepEmpty");
874  print $form->textwithtooltip($text.' '.img_help(), $texthelp, 1, 0, '', '', 2);
875  } else print $text;
876  print '</td></tr>';
877  }
878 
879  // Visibility
880  print '<tr><td>'.$langs->trans("Visibility").'</td><td>';
881  $array = array();
882  if (empty($conf->global->PROJECT_DISABLE_PRIVATE_PROJECT)) $array[0] = $langs->trans("PrivateProject");
883  if (empty($conf->global->PROJECT_DISABLE_PUBLIC_PROJECT)) $array[1] = $langs->trans("SharedProject");
884  print $form->selectarray('public', $array, $object->public, 0, 0, 0, '', 0, 0, 0, '', '', 1);
885  print '</td></tr>';
886 
887  if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES))
888  {
889  $classfortr = ($object->usage_opportunity ? '' : ' hideobject');
890  // Opportunity status
891  print '<tr class="classuseopportunity'.$classfortr.'"><td>'.$langs->trans("OpportunityStatus").'</td>';
892  print '<td>';
893  print $formproject->selectOpportunityStatus('opp_status', $object->opp_status, 1, 0, 0, 0, 'inline-block valignmiddle', 0, 1);
894  print '<div id="divtocloseproject" class="inline-block valign" style="display: none;"> &nbsp; &nbsp; ';
895  print '<input type="checkbox" id="inputcloseproject" name="closeproject" /> ';
896  print $langs->trans("AlsoCloseAProject");
897  print '</div>';
898  print '</td>';
899  print '</tr>';
900 
901  // Opportunity probability
902  print '<tr class="classuseopportunity'.$classfortr.'"><td>'.$langs->trans("OpportunityProbability").'</td>';
903  print '<td><input size="5" type="text" id="opp_percent" name="opp_percent" value="'.(GETPOSTISSET('opp_percent') ? GETPOST('opp_percent') : (strcmp($object->opp_percent, '') ?vatrate($object->opp_percent) : '')).'"> %';
904  print '<span id="oldopppercent"></span>';
905  print '</td>';
906  print '</tr>';
907 
908  // Opportunity amount
909  print '<tr class="classuseopportunity'.$classfortr.'"><td>'.$langs->trans("OpportunityAmount").'</td>';
910  print '<td><input size="5" type="text" name="opp_amount" value="'.(GETPOSTISSET('opp_amount') ? GETPOST('opp_amount') : (strcmp($object->opp_amount, '') ? price2num($object->opp_amount) : '')).'"></td>';
911  print '</tr>';
912  }
913 
914  // Date start
915  print '<tr><td>'.$langs->trans("DateStart").'</td><td>';
916  print $form->selectDate($object->date_start ? $object->date_start : -1, 'projectstart', 0, 0, 0, '', 1, 0);
917  print ' &nbsp; &nbsp; <input type="checkbox" class="valignmiddle" name="reportdate" value="yes" ';
918  if ($comefromclone) {print ' checked '; }
919  print '/> '.$langs->trans("ProjectReportDate");
920  print '</td></tr>';
921 
922  // Date end
923  print '<tr><td>'.$langs->trans("DateEnd").'</td><td>';
924  print $form->selectDate($object->date_end ? $object->date_end : -1, 'projectend', 0, 0, 0, '', 1, 0);
925  print '</td></tr>';
926 
927  // Budget
928  print '<tr><td>'.$langs->trans("Budget").'</td>';
929  print '<td><input size="5" type="text" name="budget_amount" value="'.(GETPOSTISSET('budget_amount') ? GETPOST('budget_amount') : (strcmp($object->budget_amount, '') ? price2num($object->budget_amount) : '')).'"></td>';
930  print '</tr>';
931 
932  // Description
933  print '<tr><td class="tdtop">'.$langs->trans("Description").'</td>';
934  print '<td>';
935  $doleditor = new DolEditor('description', $object->description, '', 90, 'dolibarr_notes', '', false, true, $conf->global->FCKEDITOR_ENABLE_SOCIETE, ROWS_3, '90%');
936  $doleditor->Create();
937  print '</td></tr>';
938 
939  // Tags-Categories
940  if ($conf->categorie->enabled)
941  {
942  print '<tr><td>'.$langs->trans("Categories").'</td><td>';
943  $cate_arbo = $form->select_all_categories(Categorie::TYPE_PROJECT, '', 'parent', 64, 0, 1);
944  $c = new Categorie($db);
945  $cats = $c->containing($object->id, Categorie::TYPE_PROJECT);
946  foreach ($cats as $cat) {
947  $arrayselected[] = $cat->id;
948  }
949  print img_picto('', 'category').$form->multiselectarray('categories', $cate_arbo, $arrayselected, 0, 0, 'quatrevingtpercent widthcentpercentminusx', 0, '0');
950  print "</td></tr>";
951  }
952 
953  // Other options
954  $parameters = array();
955  $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
956  print $hookmanager->resPrint;
957  if (empty($reshook))
958  {
959  print $object->showOptionals($extrafields, 'edit');
960  }
961 
962  print '</table>';
963  } else {
964  print dol_get_fiche_head($head, 'project', $langs->trans("Project"), -1, ($object->public ? 'projectpub' : 'project'));
965 
966  // Project card
967 
968  $linkback = '<a href="'.DOL_URL_ROOT.'/projet/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
969 
970  $morehtmlref = '<div class="refidno">';
971  // Title
972  $morehtmlref .= dol_escape_htmltag($object->title);
973  // Thirdparty
974  $morehtmlref .= '<br>'.$langs->trans('ThirdParty').' : ';
975  if ($object->thirdparty->id > 0)
976  {
977  $morehtmlref .= $object->thirdparty->getNomUrl(1, 'project');
978  }
979  $morehtmlref .= '</div>';
980 
981  // Define a complementary filter for search of next/prev ref.
982  if (!$user->rights->projet->all->lire)
983  {
984  $objectsListId = $object->getProjectsAuthorizedForUser($user, 0, 0);
985  $object->next_prev_filter = " rowid in (".(count($objectsListId) ?join(',', array_keys($objectsListId)) : '0').")";
986  }
987 
988  dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
989 
990 
991  print '<div class="fichecenter">';
992  print '<div class="fichehalfleft">';
993  print '<div class="underbanner clearboth"></div>';
994 
995  print '<table class="border tableforfield" width="100%">';
996 
997  // Usage
998  print '<tr><td class="tdtop">';
999  print $langs->trans("Usage");
1000  print '</td>';
1001  print '<td>';
1002  if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES))
1003  {
1004  print '<input type="checkbox" disabled name="usage_opportunity"'.(GETPOSTISSET('usage_opportunity') ? (GETPOST('usage_opportunity', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_opportunity ? ' checked="checked"' : '')).'"> ';
1005  $htmltext = $langs->trans("ProjectFollowOpportunity");
1006  print $form->textwithpicto($langs->trans("ProjectFollowOpportunity"), $htmltext);
1007  print '<br>';
1008  }
1009  if (empty($conf->global->PROJECT_HIDE_TASKS))
1010  {
1011  print '<input type="checkbox" disabled name="usage_task"'.(GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_task ? ' checked="checked"' : '')).'"> ';
1012  $htmltext = $langs->trans("ProjectFollowTasks");
1013  print $form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext);
1014  print '<br>';
1015  }
1016  if (!empty($conf->global->PROJECT_BILL_TIME_SPENT))
1017  {
1018  print '<input type="checkbox" disabled name="usage_bill_time"'.(GETPOSTISSET('usage_bill_time') ? (GETPOST('usage_bill_time', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_bill_time ? ' checked="checked"' : '')).'"> ';
1019  $htmltext = $langs->trans("ProjectBillTimeDescription");
1020  print $form->textwithpicto($langs->trans("BillTime"), $htmltext);
1021  print '<br>';
1022  }
1023  print '</td></tr>';
1024 
1025  // Visibility
1026  print '<tr><td class="titlefield">'.$langs->trans("Visibility").'</td><td>';
1027  if ($object->public) print $langs->trans('SharedProject');
1028  else print $langs->trans('PrivateProject');
1029  print '</td></tr>';
1030 
1031  if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES) && !empty($object->usage_opportunity))
1032  {
1033  // Opportunity status
1034  print '<tr><td>'.$langs->trans("OpportunityStatus").'</td><td>';
1035  $code = dol_getIdFromCode($db, $object->opp_status, 'c_lead_status', 'rowid', 'code');
1036  if ($code) print $langs->trans("OppStatus".$code);
1037  print '</td></tr>';
1038 
1039  // Opportunity percent
1040  print '<tr><td>'.$langs->trans("OpportunityProbability").'</td><td>';
1041  if (strcmp($object->opp_percent, '')) print price($object->opp_percent, 0, $langs, 1, 0).' %';
1042  print '</td></tr>';
1043 
1044  // Opportunity Amount
1045  print '<tr><td>'.$langs->trans("OpportunityAmount").'</td><td>';
1046  /*if ($object->opp_status)
1047  {
1048  print price($obj->opp_amount, 1, $langs, 1, 0, -1, $conf->currency);
1049  }*/
1050  if (strcmp($object->opp_amount, '')) print price($object->opp_amount, 0, $langs, 1, 0, -1, $conf->currency);
1051  print '</td></tr>';
1052 
1053  // Opportunity Weighted Amount
1054  print '<tr><td>'.$langs->trans('OpportunityWeightedAmount').'</td><td>';
1055  if (strcmp($object->opp_amount, '') && strcmp($object->opp_percent, '')) print price($object->opp_amount * $object->opp_percent / 100, 0, $langs, 1, 0, -1, $conf->currency);
1056  print '</td></tr>';
1057  }
1058 
1059  // Date start - end
1060  print '<tr><td>'.$langs->trans("DateStart").' - '.$langs->trans("DateEnd").'</td><td>';
1061  $start = dol_print_date($object->date_start, 'day');
1062  print ($start ? $start : '?');
1063  $end = dol_print_date($object->date_end, 'day');
1064  print ' - ';
1065  print ($end ? $end : '?');
1066  if ($object->hasDelay()) print img_warning("Late");
1067  print '</td></tr>';
1068 
1069  // Budget
1070  print '<tr><td>'.$langs->trans("Budget").'</td><td>';
1071  if (strcmp($object->budget_amount, '')) print price($object->budget_amount, 0, $langs, 1, 0, 0, $conf->currency);
1072  print '</td></tr>';
1073 
1074  // Other attributes
1075  $cols = 2;
1076  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
1077 
1078  print '</table>';
1079 
1080  print '</div>';
1081  print '<div class="fichehalfright">';
1082  print '<div class="ficheaddleft">';
1083  print '<div class="underbanner clearboth"></div>';
1084 
1085  print '<table class="border tableforfield" width="100%">';
1086 
1087  // Description
1088  print '<td class="titlefield tdtop">'.$langs->trans("Description").'</td><td>';
1089  print dol_htmlentitiesbr($object->description);
1090  print '</td></tr>';
1091 
1092  // Categories
1093  if ($conf->categorie->enabled) {
1094  print '<tr><td class="valignmiddle">'.$langs->trans("Categories").'</td><td>';
1095  print $form->showCategories($object->id, Categorie::TYPE_PROJECT, 1);
1096  print "</td></tr>";
1097  }
1098 
1099  print '</table>';
1100 
1101  print '</div>';
1102  print '</div>';
1103  print '</div>';
1104 
1105  print '<div class="clearboth"></div>';
1106  }
1107 
1109 
1110  if ($action == 'edit' && $userWrite > 0)
1111  {
1112  print '<div class="center">';
1113  print '<input name="update" class="button" type="submit" value="'.$langs->trans("Modify").'">&nbsp; &nbsp; &nbsp;';
1114  print '<input type="submit" class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
1115  print '</div>';
1116  }
1117 
1118  print '</form>';
1119 
1120  // Change probability from status
1121  if (!empty($conf->use_javascript_ajax) && !empty($conf->global->PROJECT_USE_OPPORTUNITIES))
1122  {
1123  // Default value to close or not when we set opp to 'WON'.
1124  $defaultcheckedwhenoppclose = 1;
1125  if (empty($conf->global->PROJECT_HIDE_TASKS)) $defaultcheckedwhenoppclose = 0;
1126 
1127  print '<!-- Javascript to manage opportunity status change -->';
1128  print '<script type="text/javascript" language="javascript">
1129  jQuery(document).ready(function() {
1130  function change_percent()
1131  {
1132  var element = jQuery("#opp_status option:selected");
1133  var defaultpercent = element.attr("defaultpercent");
1134  var defaultcloseproject = '.$defaultcheckedwhenoppclose.';
1135  var elemcode = element.attr("elemcode");
1136  var oldpercent = \''.dol_escape_js($object->opp_percent).'\';
1137 
1138  console.log("We select "+elemcode);
1139 
1140  /* Define if checkbox to close is checked or not */
1141  var closeproject = 0;
1142  if (elemcode == \'LOST\') closeproject = 1;
1143  if (elemcode == \'WON\') closeproject = defaultcloseproject;
1144  if (closeproject) jQuery("#inputcloseproject").prop("checked", true);
1145  else jQuery("#inputcloseproject").prop("checked", false);
1146 
1147  /* Make the close project checkbox visible or not */
1148  console.log("closeproject="+closeproject);
1149  if (elemcode == \'WON\' || elemcode == \'LOST\')
1150  {
1151  jQuery("#divtocloseproject").show();
1152  }
1153  else
1154  {
1155  jQuery("#divtocloseproject").hide();
1156  }
1157 
1158  /* Change percent with default percent (defaultpercent) if new status (defaultpercent) is higher than current (jQuery("#opp_percent").val()) */
1159  console.log("oldpercent="+oldpercent);
1160  if (oldpercent != \'\' && (parseFloat(defaultpercent) < parseFloat(oldpercent)))
1161  {
1162  if (jQuery("#opp_percent").val() != \'\' && oldpercent != \'\') jQuery("#oldopppercent").text(\' - '.dol_escape_js($langs->transnoentities("PreviousValue")).': \'+oldpercent+\' %\');
1163  if (parseFloat(oldpercent) != 100) { jQuery("#opp_percent").val(oldpercent); }
1164  else { jQuery("#opp_percent").val(defaultpercent); }
1165  }
1166  else
1167  {
1168  if ((parseFloat(jQuery("#opp_percent").val()) < parseFloat(defaultpercent)));
1169  {
1170  if (jQuery("#opp_percent").val() != \'\' && oldpercent != \'\') jQuery("#oldopppercent").text(\' - '.dol_escape_js($langs->transnoentities("PreviousValue")).': \'+oldpercent+\' %\');
1171  jQuery("#opp_percent").val(defaultpercent);
1172  }
1173  }
1174  }
1175 
1176  jQuery("#opp_status").change(function() {
1177  change_percent();
1178  });
1179  });
1180  </script>';
1181  }
1182 
1183  /*
1184  * Actions Buttons
1185  */
1186  print '<div class="tabsAction">';
1187  $parameters = array();
1188  $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been
1189  // modified by hook
1190  if (empty($reshook))
1191  {
1192  if ($action != "edit" && $action != 'presend')
1193  {
1194  // Create event
1195  /*if ($conf->agenda->enabled && ! empty($conf->global->MAIN_ADD_EVENT_ON_ELEMENT_CARD)) // Add hidden condition because this is not a
1196  // "workflow" action so should appears somewhere else on
1197  // page.
1198  {
1199  print '<a class="butAction" href="'.DOL_URL_ROOT.'/comm/action/card.php?action=create&amp;origin=' . $object->element . '&amp;originid=' . $object->id . '&amp;socid=' . $object->socid . '&amp;projectid=' . $object->id . '">' . $langs->trans("AddAction") . '</a>';
1200  }*/
1201 
1202  // Send
1203  if (empty($user->socid)) {
1204  if ($object->statut != 2)
1205  {
1206  print '<a class="butAction" href="card.php?id='.$object->id.'&amp;action=presend&mode=init#formmailbeforetitle">'.$langs->trans('SendMail').'</a>';
1207  }
1208  }
1209 
1210  // Modify
1211  if ($object->statut != 2 && $user->rights->projet->creer)
1212  {
1213  if ($userWrite > 0)
1214  {
1215  print '<a class="butAction" href="card.php?id='.$object->id.'&amp;action=edit">'.$langs->trans("Modify").'</a>';
1216  } else {
1217  print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("NotOwnerOfProject").'">'.$langs->trans('Modify').'</a>';
1218  }
1219  }
1220 
1221  // Validate
1222  if ($object->statut == 0 && $user->rights->projet->creer)
1223  {
1224  if ($userWrite > 0)
1225  {
1226  print '<a class="butAction" href="card.php?id='.$object->id.'&action=validate">'.$langs->trans("Validate").'</a>';
1227  } else {
1228  print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("NotOwnerOfProject").'">'.$langs->trans('Validate').'</a>';
1229  }
1230  }
1231 
1232  // Close
1233  if ($object->statut == 1 && $user->rights->projet->creer)
1234  {
1235  if ($userWrite > 0)
1236  {
1237  print '<a class="butAction" href="card.php?id='.$object->id.'&amp;action=close">'.$langs->trans("Close").'</a>';
1238  } else {
1239  print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("NotOwnerOfProject").'">'.$langs->trans('Close').'</a>';
1240  }
1241  }
1242 
1243  // Reopen
1244  if ($object->statut == 2 && $user->rights->projet->creer)
1245  {
1246  if ($userWrite > 0)
1247  {
1248  print '<a class="butAction" href="card.php?id='.$object->id.'&amp;action=reopen">'.$langs->trans("ReOpen").'</a>';
1249  } else {
1250  print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("NotOwnerOfProject").'">'.$langs->trans('ReOpen').'</a>';
1251  }
1252  }
1253 
1254  // Add button to create objects from project
1255  if (!empty($conf->global->PROJECT_SHOW_CREATE_OBJECT_BUTTON))
1256  {
1257  if (!empty($conf->propal->enabled) && $user->rights->propal->creer)
1258  {
1259  $langs->load("propal");
1260  print '<a class="butAction" href="'.DOL_URL_ROOT.'/comm/propal/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("AddProp").'</a>';
1261  }
1262  if (!empty($conf->commande->enabled) && $user->rights->commande->creer)
1263  {
1264  $langs->load("orders");
1265  print '<a class="butAction" href="'.DOL_URL_ROOT.'/commande/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("CreateOrder").'</a>';
1266  }
1267  if (!empty($conf->facture->enabled) && $user->rights->facture->creer)
1268  {
1269  $langs->load("bills");
1270  print '<a class="butAction" href="'.DOL_URL_ROOT.'/compta/facture/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("CreateBill").'</a>';
1271  }
1272  if (!empty($conf->supplier_proposal->enabled) && $user->rights->supplier_proposal->creer)
1273  {
1274  $langs->load("supplier_proposal");
1275  print '<a class="butAction" href="'.DOL_URL_ROOT.'/supplier_proposal/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("AddSupplierProposal").'</a>';
1276  }
1277  if (!empty($conf->supplier_order->enabled) && $user->rights->fournisseur->commande->creer)
1278  {
1279  $langs->load("suppliers");
1280  print '<a class="butAction" href="'.DOL_URL_ROOT.'/fourn/commande/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("AddSupplierOrder").'</a>';
1281  }
1282  if (!empty($conf->supplier_invoice->enabled) && $user->rights->fournisseur->facture->creer)
1283  {
1284  $langs->load("suppliers");
1285  print '<a class="butAction" href="'.DOL_URL_ROOT.'/fourn/facture/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("AddSupplierInvoice").'</a>';
1286  }
1287  if (!empty($conf->ficheinter->enabled) && $user->rights->ficheinter->creer)
1288  {
1289  $langs->load("interventions");
1290  print '<a class="butAction" href="'.DOL_URL_ROOT.'/fichinter/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("AddIntervention").'</a>';
1291  }
1292  if (!empty($conf->contrat->enabled) && $user->rights->contrat->creer)
1293  {
1294  $langs->load("contracts");
1295  print '<a class="butAction" href="'.DOL_URL_ROOT.'/contrat/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("AddContract").'</a>';
1296  }
1297  if (!empty($conf->expensereport->enabled) && $user->rights->expensereport->creer)
1298  {
1299  $langs->load("trips");
1300  print '<a class="butAction" href="'.DOL_URL_ROOT.'/expensereport/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("AddTrip").'</a>';
1301  }
1302  if (!empty($conf->don->enabled) && $user->rights->don->creer)
1303  {
1304  $langs->load("donations");
1305  print '<a class="butAction" href="'.DOL_URL_ROOT.'/don/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("AddDonation").'</a>';
1306  }
1307  }
1308 
1309  // Clone
1310  if ($user->rights->projet->creer)
1311  {
1312  if ($userWrite > 0)
1313  {
1314  print '<a class="butAction" href="card.php?id='.$object->id.'&action=clone">'.$langs->trans('ToClone').'</a>';
1315  } else {
1316  print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("NotOwnerOfProject").'">'.$langs->trans('ToClone').'</a>';
1317  }
1318  }
1319 
1320  // Delete
1321  if ($user->rights->projet->supprimer || ($object->statut == 0 && $user->rights->projet->creer))
1322  {
1323  if ($userDelete > 0 || ($object->statut == 0 && $user->rights->projet->creer))
1324  {
1325  print '<a class="butActionDelete" href="card.php?id='.$object->id.'&amp;action=delete&amp;token='.newToken().'">'.$langs->trans("Delete").'</a>';
1326  } else {
1327  print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("NotOwnerOfProject").'">'.$langs->trans('Delete').'</a>';
1328  }
1329  }
1330  }
1331  }
1332 
1333  print "</div>";
1334 
1335  if (GETPOST('modelselected')) {
1336  $action = 'presend';
1337  }
1338 
1339  if ($action != 'presend')
1340  {
1341  print '<div class="fichecenter"><div class="fichehalfleft">';
1342  print '<a name="builddoc"></a>'; // ancre
1343 
1344  /*
1345  * Documents generes
1346  */
1347  $filename = dol_sanitizeFileName($object->ref);
1348  $filedir = $conf->projet->dir_output."/".dol_sanitizeFileName($object->ref);
1349  $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
1350  $genallowed = ($user->rights->projet->lire && $userAccess > 0);
1351  $delallowed = ($user->rights->projet->creer && $userWrite > 0);
1352 
1353  print $formfile->showdocuments('project', $filename, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf);
1354 
1355  print '</div><div class="fichehalfright"><div class="ficheaddleft">';
1356 
1357  $MAXEVENT = 10;
1358 
1359  $morehtmlright = '<a href="'.DOL_URL_ROOT.'/projet/info.php?id='.$object->id.'">';
1360  $morehtmlright .= $langs->trans("SeeAll");
1361  $morehtmlright .= '</a>';
1362 
1363  // List of actions on element
1364  include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
1365  $formactions = new FormActions($db);
1366  $somethingshown = $formactions->showactions($object, 'project', 0, 1, '', $MAXEVENT, '', $morehtmlright);
1367 
1368  print '</div></div></div>';
1369  }
1370 
1371  // Presend form
1372  $modelmail = 'project';
1373  $defaulttopic = 'SendProjectRef';
1374  $diroutput = $conf->projet->dir_output;
1375  $autocopy = 'MAIN_MAIL_AUTOCOPY_PROJECT_TO'; // used to know the automatic BCC to add
1376  $trackid = 'proj'.$object->id;
1377 
1378  include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
1379 
1380  // Hook to add more things on page
1381  $parameters = array();
1382  $reshook = $hookmanager->executeHooks('mainCardTabAddMore', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1383 } else {
1384  print $langs->trans("RecordNotFound");
1385 }
1386 
1387 // End of page
1388 llxFooter();
1389 $db->close();
if(!function_exists('dol_getprefix')) dol_include_once($relpath, $classname= '')
Make an include_once using default root and alternate root if it fails.
GETPOST($paramname, $check= 'alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
if(preg_match('/set_([a-z0-9_\-]+)/i', $action, $reg)) if(preg_match('/del_([a-z0-9_\-]+)/i', $action, $reg)) if($action== 'set') elseif($action== 'specimen') elseif($action== 'setmodel') elseif($action== 'del') elseif($action== 'setdoc') $formactions
View.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm= 'auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
if(!empty($arrayfields['u.datec']['checked'])) print_liste_field_titre("DateCreationShort"u if(!empty($arrayfields['u.tms']['checked'])) print_liste_field_titre("DateModificationShort"u if(!empty($arrayfields['u.statut']['checked'])) print_liste_field_titre("Status"u statut
Definition: list.php:632
Class to manage building of HTML components.
img_help($usehelpcursor=1, $usealttitle=1)
Show help logo with cursor &quot;?&quot;.
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into javascript code.
dol_now($mode= 'auto')
Return date for now.
Class to manage Dolibarr users.
Definition: user.class.php:44
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom= 'UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
const STATUS_VALIDATED
Open/Validated status.
img_warning($titlealt= 'default', $moreatt= '', $morecss= 'pictowarning')
Show warning logo.
price($amount, $form=0, $outlangs= '', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code= '')
Function to format a value into an amount for visual output Function used into PDF and HTML pages...
llxHeader()
Empty header.
Definition: wrapper.php:45
Class to manage standard extra fields.
setEventMessages($mesg, $mesgs, $style= 'mesgs', $messagekey= '')
Set event messages in dol_events session object.
Class to manage generation of HTML components Only common components must be here.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage categories.
Class to manage projects.
load_fiche_titre($titre, $morehtmlright= '', $picto= 'generic', $pictoisfullpath=0, $id= '', $morecssontable= '', $morehtmlcenter= '')
Load a title with picto.
price2num($amount, $rounding= '', $option=0)
Function that return a number with universal decimal format (decimal separator is &#39;...
Class to manage building of HTML components.
img_picto($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt= '', $morecss= '', $marginleftonlyshort=2)
Show picto whatever it&#39;s its name (generic function)
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename= '', $restricttologhandler= '', $logcontext=null)
Write log message into outputs.
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1)
Remove a file or several files with a mask.
Definition: files.lib.php:1144
restrictedArea($user, $features, $objectid=0, $tableandshare= '', $feature2= '', $dbt_keyfield= 'fk_soc', $dbt_select= 'rowid', $isdraft=0)
Check permissions of a user to show a page and an object.
accessforbidden($message= '', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program Calling this function terminate execution ...
Class to manage translations.
dol_sanitizeFileName($str, $newstr= '_', $unaccent=1)
Clean a string to use it as a file name.
Class to offer components to list and upload files.
vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0)
Return a string with VAT rate label formated for view output Used into pdf and HTML pages...
print $_SERVER["PHP_SELF"]
Edit parameters.
dol_getIdFromCode($db, $key, $tablename, $fieldkey= 'code', $fieldid= 'id', $entityfilter=0)
Return an id or code from a code or id.
dol_get_fiche_head($links=array(), $active= '', $title= '', $notab=0, $picto= '', $pictoisfullpath=0, $morehtmlright= '', $morecss= '', $limittoshow=0, $moretabssuffix= '')
Show tabs of a record.
project_prepare_head(Project $project)
Prepare array with list of tabs.
Definition: project.lib.php:36
print
Draft customers invoices.
Definition: index.php:89
Class to manage tasks.
Definition: task.class.php:35
dol_print_date($time, $format= '', $tzoutput= 'auto', $outputlangs= '', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
newToken()
Return the value of token currently saved into session with name &#39;newtoken&#39;.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
Class to manage a WYSIWYG editor.
dol_banner_tab($object, $paramid, $morehtml= '', $shownav=1, $fieldid= 'rowid', $fieldref= 'ref', $morehtmlref= '', $moreparam= '', $nodbprefix=0, $morehtmlleft= '', $morehtmlstatus= '', $onlybanner=0, $morehtmlright= '')
Show tab footer of a card.
llxFooter()
Empty footer.
Definition: wrapper.php:59
if(!defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN'
Draft customers invoices.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $keepmoretags= '', $escapeonlyhtmltags=0)
Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields...