dolibarr  19.0.0-dev
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 // Load Dolibarr environment
27 require '../main.inc.php';
28 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
29 require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
30 require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
31 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
32 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
33 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
34 require_once DOL_DOCUMENT_ROOT.'/core/modules/project/modules_project.php';
35 require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
36 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
37 
38 // Load translation files required by the page
39 $langsLoad=array('projects', 'companies');
40 if (isModEnabled('eventorganization')) {
41  $langsLoad[]='eventorganization';
42 }
43 
44 $langs->loadLangs($langsLoad);
45 
46 $id = GETPOST('id', 'int');
47 $ref = GETPOST('ref', 'alpha');
48 $action = GETPOST('action', 'aZ09');
49 $backtopage = GETPOST('backtopage', 'alpha');
50 $backtopageforcancel = GETPOST('backtopageforcancel', 'alpha');
51 $backtopagejsfields = GETPOST('backtopagejsfields', 'alpha');
52 $cancel = GETPOST('cancel', 'alpha');
53 $confirm = GETPOST('confirm', 'aZ09');
54 
55 $dol_openinpopup = 0;
56 if (!empty($backtopagejsfields)) {
57  $tmpbacktopagejsfields = explode(':', $backtopagejsfields);
58  $dol_openinpopup = $tmpbacktopagejsfields[0];
59 }
60 
61 $status = GETPOST('status', 'int');
62 $opp_status = GETPOST('opp_status', 'int');
63 $opp_percent = price2num(GETPOST('opp_percent', 'alphanohtml'));
64 $objcanvas = GETPOST("objcanvas", "alphanohtml");
65 $comefromclone = GETPOST("comefromclone", "alphanohtml");
66 $date_start = dol_mktime(0, 0, 0, GETPOST('projectstartmonth', 'int'), GETPOST('projectstartday', 'int'), GETPOST('projectstartyear', 'int'));
67 $date_end = dol_mktime(0, 0, 0, GETPOST('projectendmonth', 'int'), GETPOST('projectendday', 'int'), GETPOST('projectendyear', 'int'));
68 $date_start_event = dol_mktime(GETPOST('date_start_eventhour', 'int'), GETPOST('date_start_eventmin', 'int'), GETPOST('date_start_eventsec', 'int'), GETPOST('date_start_eventmonth', 'int'), GETPOST('date_start_eventday', 'int'), GETPOST('date_start_eventyear', 'int'));
69 $date_end_event = dol_mktime(GETPOST('date_end_eventhour', 'int'), GETPOST('date_end_eventmin', 'int'), GETPOST('date_end_eventsec', 'int'), GETPOST('date_end_eventmonth', 'int'), GETPOST('date_end_eventday', 'int'), GETPOST('date_end_eventyear', 'int'));
70 $location = GETPOST('location', 'alphanohtml');
71 
72 
73 $mine = GETPOST('mode') == 'mine' ? 1 : 0;
74 //if (! $user->rights->projet->all->lire) $mine=1; // Special for projects
75 
76 // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
77 $hookmanager->initHooks(array('projectcard', 'globalcard'));
78 
79 $object = new Project($db);
80 $extrafields = new ExtraFields($db);
81 
82 // Load object
83 //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.
84 if ($id > 0 || !empty($ref)) {
85  $ret = $object->fetch($id, $ref); // If we create project, ref may be defined into POST but record does not yet exists into database
86  if ($ret > 0) {
87  $object->fetch_thirdparty();
88  if (!empty($conf->global->PROJECT_ALLOW_COMMENT_ON_PROJECT) && method_exists($object, 'fetchComments') && empty($object->comments)) {
89  $object->fetchComments();
90  }
91  $id = $object->id;
92  }
93 }
94 
95 // fetch optionals attributes and labels
96 $extrafields->fetch_name_optionals_label($object->table_element);
97 
98 // Security check
99 $socid = GETPOST('socid', 'int');
100 //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.
101 restrictedArea($user, 'projet', $object->id, 'projet&project');
102 
103 if ($id == '' && $ref == '' && ($action != "create" && $action != "add" && $action != "update" && !GETPOST("cancel"))) {
104  accessforbidden();
105 }
106 
107 $permissiontoadd = $user->hasRight('projet', 'creer');
108 $permissiontodelete = $user->hasRight('projet', 'supprimer');
109 $permissiondellink = $user->hasRight('projet', 'creer'); // Used by the include of actions_dellink.inc.php
110 
111 
112 /*
113  * Actions
114  */
115 
116 $parameters = array('id'=>$socid, 'objcanvas'=>$objcanvas);
117 $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
118 if ($reshook < 0) {
119  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
120 }
121 
122 if (empty($reshook)) {
123  $backurlforlist = DOL_URL_ROOT.'/projet/list.php';
124 
125  // Cancel
126  if ($cancel) {
127  if (GETPOST("comefromclone") == 1) {
128  $result = $object->delete($user);
129  if ($result > 0) {
130  header("Location: index.php");
131  exit;
132  } else {
133  dol_syslog($object->error, LOG_DEBUG);
134  setEventMessages($langs->trans("CantRemoveProject", $langs->transnoentitiesnoconv("ProjectOverview")), null, 'errors');
135  }
136  }
137  }
138 
139  if (empty($backtopage) || ($cancel && empty($id))) {
140  if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) {
141  if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) {
142  $backtopage = $backurlforlist;
143  } else {
144  $backtopage = DOL_URL_ROOT.'/projet/card.php?id='.((!empty($id) && $id > 0) ? $id : '__ID__');
145  }
146  }
147  }
148 
149  if ($cancel) {
150  if (!empty($backtopageforcancel)) {
151  header("Location: ".$backtopageforcancel);
152  exit;
153  } elseif (!empty($backtopage)) {
154  header("Location: ".$backtopage);
155  exit;
156  }
157  $action = '';
158  }
159 
160  include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; // Must be include, not include_once
161 
162  // Action setdraft object
163  if ($action == 'confirm_setdraft' && $confirm == 'yes' && $permissiontoadd) {
164  $result = $object->setStatut($object::STATUS_DRAFT, null, '', 'PROJECT_MODIFY');
165  if ($result >= 0) {
166  // Nothing else done
167  } else {
168  $error++;
169  setEventMessages($object->error, $object->errors, 'errors');
170  }
171  $action = '';
172  }
173 
174  // Action add
175  if ($action == 'add' && $permissiontoadd) {
176  $error = 0;
177  if (!GETPOST('ref')) {
178  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Ref")), null, 'errors');
179  $error++;
180  }
181  if (!GETPOST('title')) {
182  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("ProjectLabel")), null, 'errors');
183  $error++;
184  }
185 
186  if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES)) {
187  if (GETPOST('usage_opportunity') != '' && !(GETPOST('opp_status') > 0)) {
188  $error++;
189  setEventMessages($langs->trans("ErrorOppStatusRequiredIfUsage"), null, 'errors');
190  }
191  if (GETPOST('opp_amount') != '' && !(GETPOST('opp_status') > 0)) {
192  $error++;
193  setEventMessages($langs->trans("ErrorOppStatusRequiredIfAmount"), null, 'errors');
194  }
195  }
196 
197  // Create with status validated immediatly
198  if (!empty($conf->global->PROJECT_CREATE_NO_DRAFT) && !$error) {
199  $status = Project::STATUS_VALIDATED;
200  }
201 
202  if (!$error) {
203  $error = 0;
204 
205  $db->begin();
206 
207  $object->ref = GETPOST('ref', 'alphanohtml');
208  $object->title = GETPOST('title', 'alphanohtml');
209  $object->socid = GETPOST('socid', 'int');
210  $object->description = GETPOST('description', 'restricthtml'); // Do not use 'alpha' here, we want field as it is
211  $object->public = GETPOST('public', 'alphanohtml');
212  $object->opp_amount = price2num(GETPOST('opp_amount', 'alphanohtml'));
213  $object->budget_amount = price2num(GETPOST('budget_amount', 'alphanohtml'));
214  $object->date_c = dol_now();
215  $object->date_start = $date_start;
216  $object->date_end = $date_end;
217  $object->date_start_event = $date_start_event;
218  $object->date_end_event = $date_end_event;
219  $object->location = $location;
220  $object->statut = $status;
221  $object->opp_status = $opp_status;
222  $object->opp_percent = $opp_percent;
223  $object->usage_opportunity = (GETPOST('usage_opportunity', 'alpha') == 'on' ? 1 : 0);
224  $object->usage_task = (GETPOST('usage_task', 'alpha') == 'on' ? 1 : 0);
225  $object->usage_bill_time = (GETPOST('usage_bill_time', 'alpha') == 'on' ? 1 : 0);
226  $object->usage_organize_event = (GETPOST('usage_organize_event', 'alpha') == 'on' ? 1 : 0);
227 
228  // Fill array 'array_options' with data from add form
229  $ret = $extrafields->setOptionalsFromPost(null, $object);
230  if ($ret < 0) {
231  $error++;
232  }
233 
234  $result = $object->create($user);
235  if (!$error && $result > 0) {
236  // Add myself as project leader
237  $typeofcontact = 'PROJECTLEADER';
238  $result = $object->add_contact($user->id, $typeofcontact, 'internal');
239 
240  // -3 means type not found (PROJECTLEADER renamed, de-activated or deleted), so don't prevent creation if it has been the case
241  if ($result == -3) {
242  setEventMessage('ErrorPROJECTLEADERRoleMissingRestoreIt', 'errors');
243  $error++;
244  } elseif ($result < 0) {
245  $langs->load("errors");
246  setEventMessages($object->error, $object->errors, 'errors');
247  $error++;
248  }
249  } else {
250  $langs->load("errors");
251  setEventMessages($object->error, $object->errors, 'errors');
252  $error++;
253  }
254  if (!$error && !empty($object->id) > 0) {
255  // Category association
256  $categories = GETPOST('categories', 'array');
257  $result = $object->setCategories($categories);
258  if ($result < 0) {
259  $langs->load("errors");
260  setEventMessages($object->error, $object->errors, 'errors');
261  $error++;
262  }
263  }
264 
265  if (!$error) {
266  $db->commit();
267 
268  if (!empty($backtopage)) {
269  $backtopage = preg_replace('/--IDFORBACKTOPAGE--|__ID__/', $object->id, $backtopage); // New method to autoselect project after a New on another form object creation
270  $backtopage = $backtopage.'&projectid='.$object->id; // Old method
271  header("Location: ".$backtopage);
272  exit;
273  } else {
274  header("Location:card.php?id=".$object->id);
275  exit;
276  }
277  } else {
278  $db->rollback();
279  unset($_POST["ref"]);
280  $action = 'create';
281  }
282  } else {
283  $action = 'create';
284  }
285  }
286 
287  if ($action == 'update' && empty(GETPOST('cancel')) && $permissiontoadd) {
288  $error = 0;
289 
290  if (empty($ref)) {
291  $error++;
292  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Ref")), null, 'errors');
293  }
294  if (!GETPOST("title")) {
295  $error++;
296  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("ProjectLabel")), null, 'errors');
297  }
298 
299  $db->begin();
300 
301  if (!$error) {
302  $object->oldcopy = clone $object;
303 
304  $old_start_date = $object->date_start;
305 
306  $object->ref = GETPOST('ref', 'alpha');
307  $object->title = GETPOST('title', 'alphanohtml'); // Do not use 'alpha' here, we want field as it is
308  $object->statut = GETPOST('status', 'int');
309  $object->socid = GETPOST('socid', 'int');
310  $object->description = GETPOST('description', 'restricthtml'); // Do not use 'alpha' here, we want field as it is
311  $object->public = GETPOST('public', 'alpha');
312  $object->date_start = (!GETPOST('projectstart')) ? '' : $date_start;
313  $object->date_end = (!GETPOST('projectend')) ? '' : $date_end;
314  $object->date_start_event = (!GETPOST('date_start_event')) ? '' : $date_start_event;
315  $object->date_end_event = (!GETPOST('date_end_event')) ? '' : $date_end_event;
316  $object->location = $location;
317  if (GETPOSTISSET('opp_amount')) {
318  $object->opp_amount = price2num(GETPOST('opp_amount', 'alpha'));
319  }
320  if (GETPOSTISSET('budget_amount')) {
321  $object->budget_amount = price2num(GETPOST('budget_amount', 'alpha'));
322  }
323  if (GETPOSTISSET('opp_status')) {
324  $object->opp_status = $opp_status;
325  }
326  if (GETPOSTISSET('opp_percent')) {
327  $object->opp_percent = $opp_percent;
328  }
329  $object->usage_opportunity = (GETPOST('usage_opportunity', 'alpha') == 'on' ? 1 : 0);
330  $object->usage_task = (GETPOST('usage_task', 'alpha') == 'on' ? 1 : 0);
331  $object->usage_bill_time = (GETPOST('usage_bill_time', 'alpha') == 'on' ? 1 : 0);
332  $object->usage_organize_event = (GETPOST('usage_organize_event', 'alpha') == 'on' ? 1 : 0);
333 
334  // Fill array 'array_options' with data from add form
335  $ret = $extrafields->setOptionalsFromPost(null, $object, '@GETPOSTISSET');
336  if ($ret < 0) {
337  $error++;
338  }
339  }
340 
341  if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES)) {
342  if ($object->opp_amount && ($object->opp_status <= 0)) {
343  $error++;
344  setEventMessages($langs->trans("ErrorOppStatusRequiredIfAmount"), null, 'errors');
345  }
346  }
347 
348  if (!$error) {
349  $result = $object->update($user);
350  if ($result < 0) {
351  $error++;
352  if ($result == -4) {
353  setEventMessages($langs->trans("ErrorRefAlreadyExists"), null, 'errors');
354  } else {
355  setEventMessages($object->error, $object->errors, 'errors');
356  }
357  } else {
358  // Category association
359  $categories = GETPOST('categories', 'array');
360  $result = $object->setCategories($categories);
361  if ($result < 0) {
362  $error++;
363  setEventMessages($object->error, $object->errors, 'errors');
364  }
365  }
366  }
367 
368  if (!$error) {
369  if (GETPOST("reportdate") && ($object->date_start != $old_start_date)) {
370  $result = $object->shiftTaskDate($old_start_date);
371  if ($result < 0) {
372  $error++;
373  setEventMessages($langs->trans("ErrorShiftTaskDate").':'.$object->error, $object->errors, 'errors');
374  }
375  }
376  }
377 
378  // Check if we must change status
379  if (GETPOST('closeproject')) {
380  $resclose = $object->setClose($user);
381  if ($resclose < 0) {
382  $error++;
383  setEventMessages($langs->trans("FailedToCloseProject").':'.$object->error, $object->errors, 'errors');
384  }
385  }
386 
387 
388  if ($error) {
389  $db->rollback();
390  $action = 'edit';
391  } else {
392  $db->commit();
393 
394  if (GETPOST('socid', 'int') > 0) {
395  $object->fetch_thirdparty(GETPOST('socid', 'int'));
396  } else {
397  unset($object->thirdparty);
398  }
399  }
400  }
401 
402  // Build doc
403  if ($action == 'builddoc' && $permissiontoadd) {
404  // Save last template used to generate document
405  if (GETPOST('model')) {
406  $object->setDocModel($user, GETPOST('model', 'alpha'));
407  }
408 
409  $outputlangs = $langs;
410  if (GETPOST('lang_id', 'aZ09')) {
411  $outputlangs = new Translate("", $conf);
412  $outputlangs->setDefaultLang(GETPOST('lang_id', 'aZ09'));
413  }
414  $result = $object->generateDocument($object->model_pdf, $outputlangs);
415  if ($result <= 0) {
416  setEventMessages($object->error, $object->errors, 'errors');
417  $action = '';
418  }
419  }
420 
421  // Delete file in doc form
422  if ($action == 'remove_file' && $permissiontoadd) {
423  if ($object->id > 0) {
424  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
425 
426  $langs->load("other");
427  $upload_dir = $conf->project->multidir_output[$object->entity];
428  $file = $upload_dir.'/'.GETPOST('file');
429  $ret = dol_delete_file($file, 0, 0, 0, $object);
430  if ($ret) {
431  setEventMessages($langs->trans("FileWasRemoved", GETPOST('file')), null, 'mesgs');
432  } else {
433  setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('file')), null, 'errors');
434  }
435  $action = '';
436  }
437  }
438 
439 
440  if ($action == 'confirm_validate' && $confirm == 'yes' && $permissiontoadd) {
441  $result = $object->setValid($user);
442  if ($result <= 0) {
443  setEventMessages($object->error, $object->errors, 'errors');
444  }
445  }
446 
447  if ($action == 'confirm_close' && $confirm == 'yes' && $permissiontoadd) {
448  $result = $object->setClose($user);
449  if ($result <= 0) {
450  setEventMessages($object->error, $object->errors, 'errors');
451  }
452  }
453 
454  if ($action == 'confirm_reopen' && $confirm == 'yes' && $permissiontoadd) {
455  $result = $object->setValid($user);
456  if ($result <= 0) {
457  setEventMessages($object->error, $object->errors, 'errors');
458  }
459  }
460 
461  if ($action == 'confirm_delete' && $confirm == 'yes' && $permissiontodelete) {
462  $object->fetch($id);
463  $result = $object->delete($user);
464  if ($result > 0) {
465  setEventMessages($langs->trans("RecordDeleted"), null, 'mesgs');
466  header("Location: list.php?restore_lastsearch_values=1");
467  exit;
468  } else {
469  dol_syslog($object->error, LOG_DEBUG);
470  setEventMessages($object->error, $object->errors, 'errors');
471  }
472  }
473 
474  if ($action == 'confirm_clone' && $permissiontoadd && $confirm == 'yes') {
475  $clone_contacts = GETPOST('clone_contacts') ? 1 : 0;
476  $clone_tasks = GETPOST('clone_tasks') ? 1 : 0;
477  $clone_project_files = GETPOST('clone_project_files') ? 1 : 0;
478  $clone_task_files = GETPOST('clone_task_files') ? 1 : 0;
479  $clone_notes = GETPOST('clone_notes') ? 1 : 0;
480  $move_date = GETPOST('move_date') ? 1 : 0;
481  $clone_thirdparty = GETPOST('socid', 'int') ?GETPOST('socid', 'int') : 0;
482 
483  $result = $object->createFromClone($user, $object->id, $clone_contacts, $clone_tasks, $clone_project_files, $clone_task_files, $clone_notes, $move_date, 0, $clone_thirdparty);
484  if ($result <= 0) {
485  setEventMessages($object->error, $object->errors, 'errors');
486  } else {
487  // Load new object
488  $newobject = new Project($db);
489  $newobject->fetch($result);
490  $newobject->fetch_optionals();
491  $newobject->fetch_thirdparty(); // Load new object
492  $object = $newobject;
493  $action = 'edit';
494  $comefromclone = true;
495  }
496  }
497 
498  // Actions to send emails
499  $triggersendname = 'PROJECT_SENTBYMAIL';
500  $paramname = 'id';
501  $autocopy = 'MAIN_MAIL_AUTOCOPY_PROJECT_TO'; // used to know the automatic BCC to add
502  $trackid = 'proj'.$object->id;
503  include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
504 }
505 
506 
507 /*
508  * View
509  */
510 
511 $form = new Form($db);
512 $formfile = new FormFile($db);
513 $formproject = new FormProjets($db);
514 $userstatic = new User($db);
515 
516 $title = $langs->trans("Project").' - '.$object->ref.(!empty($object->thirdparty->name) ? ' - '.$object->thirdparty->name : '').(!empty($object->title) ? ' - '.$object->title : '');
517 if (!empty($conf->global->MAIN_HTML_TITLE) && preg_match('/projectnameonly/', $conf->global->MAIN_HTML_TITLE)) {
518  $title = $object->ref.(!empty($object->thirdparty->name) ? ' - '.$object->thirdparty->name : '').(!empty($object->title) ? ' - '.$object->title : '');
519 }
520 
521 $help_url = "EN:Module_Projects|FR:Module_Projets|ES:M&oacute;dulo_Proyectos|DE:Modul_Projekte";
522 
523 llxHeader("", $title, $help_url);
524 
525 $titleboth = $langs->trans("LeadsOrProjects");
526 $titlenew = $langs->trans("NewLeadOrProject"); // Leads and opportunities by default
527 if (!getDolGlobalInt('PROJECT_USE_OPPORTUNITIES')) {
528  $titleboth = $langs->trans("Projects");
529  $titlenew = $langs->trans("NewProject");
530 }
531 if (getDolGlobalInt('PROJECT_USE_OPPORTUNITIES') == 2) { // 2 = leads only
532  $titleboth = $langs->trans("Leads");
533  $titlenew = $langs->trans("NewLead");
534 }
535 
536 if ($action == 'create' && $user->rights->projet->creer) {
537  /*
538  * Create
539  */
540 
541  $thirdparty = new Societe($db);
542  if ($socid > 0) {
543  $thirdparty->fetch($socid);
544  }
545 
546  print load_fiche_titre($titlenew, '', 'project');
547 
548  print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
549  print '<input type="hidden" name="action" value="add">';
550  print '<input type="hidden" name="token" value="'.newToken().'">';
551  print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
552  print '<input type="hidden" name="backtopageforcancel" value="'.$backtopageforcancel.'">';
553  print '<input type="hidden" name="backtopagejsfields" value="'.$backtopagejsfields.'">';
554  print '<input type="hidden" name="dol_openinpopup" value="'.$dol_openinpopup.'">';
555 
556  print dol_get_fiche_head();
557 
558  print '<table class="border centpercent tableforfieldcreate">';
559 
560  $defaultref = '';
561  $modele = empty($conf->global->PROJECT_ADDON) ? 'mod_project_simple' : $conf->global->PROJECT_ADDON;
562 
563  // Search template files
564  $file = ''; $classname = ''; $filefound = 0;
565  $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
566  foreach ($dirmodels as $reldir) {
567  $file = dol_buildpath($reldir."core/modules/project/".$modele.'.php', 0);
568  if (file_exists($file)) {
569  $filefound = 1;
570  $classname = $modele;
571  break;
572  }
573  }
574 
575  if ($filefound) {
576  $result = dol_include_once($reldir."core/modules/project/".$modele.'.php');
577  $modProject = new $classname;
578 
579  $defaultref = $modProject->getNextValue($thirdparty, $object);
580  }
581 
582  if (is_numeric($defaultref) && $defaultref <= 0) {
583  $defaultref = '';
584  }
585 
586  // Ref
587  $suggestedref = (GETPOST("ref") ? GETPOST("ref") : $defaultref);
588  print '<tr><td class="titlefieldcreate"><span class="fieldrequired">'.$langs->trans("Ref").'</span></td><td class><input class="maxwidth150onsmartphone" type="text" name="ref" value="'.dol_escape_htmltag($suggestedref).'">';
589  if ($suggestedref) {
590  print ' '.$form->textwithpicto('', $langs->trans("YouCanCompleteRef", $suggestedref));
591  }
592  print '</td></tr>';
593 
594  // Label
595  print '<tr><td><span class="fieldrequired">'.$langs->trans("Label").'</span></td><td><input class="width500 maxwidth150onsmartphone" type="text" name="title" value="'.dol_escape_htmltag(GETPOST("title", 'alphanohtml')).'" autofocus></td></tr>';
596 
597  // Usage (opp, task, bill time, ...)
598  if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES) || empty($conf->global->PROJECT_HIDE_TASKS) || isModEnabled('eventorganization')) {
599  print '<tr><td class="tdtop">';
600  print $langs->trans("Usage");
601  print '</td>';
602  print '<td>';
603  if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES)) {
604  print '<input type="checkbox" id="usage_opportunity" name="usage_opportunity"'.(GETPOSTISSET('usage_opportunity') ? (GETPOST('usage_opportunity', 'alpha') ? ' checked="checked"' : '') : ' checked="checked"').'"> ';
605  $htmltext = $langs->trans("ProjectFollowOpportunity");
606  print '<label for="usage_opportunity">'.$form->textwithpicto($langs->trans("ProjectFollowOpportunity"), $htmltext).'</label>';
607  print '<script>';
608  print '$( document ).ready(function() {
609  jQuery("#usage_opportunity").change(function() {
610  if (jQuery("#usage_opportunity").prop("checked")) {
611  console.log("Show opportunities fields");
612  jQuery(".classuseopportunity").show();
613  } else {
614  console.log("Hide opportunities fields "+jQuery("#usage_opportunity").prop("checked"));
615  jQuery(".classuseopportunity").hide();
616  }
617  });
618  ';
619  if (GETPOSTISSET('usage_opportunity') && !GETPOST('usage_opportunity')) {
620  print 'jQuery(".classuseopportunity").hide();';
621  }
622  print '});';
623  print '</script>';
624  print '<br>';
625  }
626  if (empty($conf->global->PROJECT_HIDE_TASKS)) {
627  print '<input type="checkbox" id="usage_task" name="usage_task"'.(GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') ? ' checked="checked"' : '') : ' checked="checked"').'"> ';
628  $htmltext = $langs->trans("ProjectFollowTasks");
629  print '<label for="usage_task">'.$form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext).'</label>';
630  print '<script>';
631  print '$( document ).ready(function() {
632  jQuery("#usage_task").change(function() {
633  if (jQuery("#usage_task").prop("checked")) {
634  console.log("Show task fields");
635  jQuery(".classusetask").show();
636  } else {
637  console.log("Hide tasks fields "+jQuery("#usage_task").prop("checked"));
638  jQuery(".classusetask").hide();
639  }
640  });
641  ';
642  if (GETPOSTISSET('usage_task') && !GETPOST('usage_task')) {
643  print 'jQuery(".classusetask").hide();';
644  }
645  print '});';
646  print '</script>';
647  print '<br>';
648  }
649  if (empty($conf->global->PROJECT_HIDE_TASKS) && !empty($conf->global->PROJECT_BILL_TIME_SPENT)) {
650  print '<input type="checkbox" id="usage_bill_time" name="usage_bill_time"'.(GETPOSTISSET('usage_bill_time') ? (GETPOST('usage_bill_time', 'alpha') ? ' checked="checked"' : '') : '').'"> ';
651  $htmltext = $langs->trans("ProjectBillTimeDescription");
652  print '<label for="usage_bill_time">'.$form->textwithpicto($langs->trans("BillTime"), $htmltext).'</label>';
653  print '<script>';
654  print '$( document ).ready(function() {
655  jQuery("#usage_bill_time").change(function() {
656  if (jQuery("#usage_bill_time").prop("checked")) {
657  console.log("Show bill time fields");
658  jQuery(".classusebilltime").show();
659  } else {
660  console.log("Hide bill time fields "+jQuery("#usage_bill_time").prop("checked"));
661  jQuery(".classusebilltime").hide();
662  }
663  });
664  ';
665  if (GETPOSTISSET('usage_bill_time') && !GETPOST('usage_bill_time')) {
666  print 'jQuery(".classusebilltime").hide();';
667  }
668  print '});';
669  print '</script>';
670  print '<br>';
671  }
672  if (isModEnabled('eventorganization')) {
673  print '<input type="checkbox" id="usage_organize_event" name="usage_organize_event"'.(GETPOSTISSET('usage_organize_event') ? (GETPOST('usage_organize_event', 'alpha') ? ' checked="checked"' : '') :'').'"> ';
674  $htmltext = $langs->trans("EventOrganizationDescriptionLong");
675  print '<label for="usage_organize_event">'.$form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext).'</label>';
676  print '<script>';
677  print '$( document ).ready(function() {
678  jQuery("#usage_organize_event").change(function() {
679  if (jQuery("#usage_organize_event").prop("checked")) {
680  console.log("Show organize event fields");
681  jQuery(".classuseorganizeevent").show();
682  } else {
683  console.log("Hide organize event fields "+jQuery("#usage_organize_event").prop("checked"));
684  jQuery(".classuseorganizeevent").hide();
685  }
686  });
687  ';
688  if (!GETPOST('usage_organize_event')) {
689  print 'jQuery(".classuseorganizeevent").hide();';
690  }
691  print '});';
692  print '</script>';
693  }
694  print '</td>';
695  print '</tr>';
696  }
697 
698  // Thirdparty
699  if (isModEnabled('societe')) {
700  print '<tr><td>';
701  print (empty($conf->global->PROJECT_THIRDPARTY_REQUIRED) ? '' : '<span class="fieldrequired">');
702  print $langs->trans("ThirdParty");
703  print (empty($conf->global->PROJECT_THIRDPARTY_REQUIRED) ? '' : '</span>');
704  print '</td><td class="maxwidthonsmartphone">';
705  $filter = '';
706  if (!empty($conf->global->PROJECT_FILTER_FOR_THIRDPARTY_LIST)) {
707  $filter = $conf->global->PROJECT_FILTER_FOR_THIRDPARTY_LIST;
708  }
709  $text = img_picto('', 'company').$form->select_company(GETPOST('socid', 'int'), 'socid', $filter, 'SelectThirdParty', 1, 0, array(), 0, 'minwidth300 widthcentpercentminusxx maxwidth500');
710  if (empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS) && empty($conf->dol_use_jmobile)) {
711  $texthelp = $langs->trans("IfNeedToUseOtherObjectKeepEmpty");
712  print $form->textwithtooltip($text.' '.img_help(), $texthelp, 1);
713  } else {
714  print $text;
715  }
716  if (!GETPOSTISSET('backtopage')) {
717  $url = '/societe/card.php?action=create&client=3&fournisseur=0&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create');
718  $newbutton = '<span class="fa fa-plus-circle valignmiddle paddingleft" title="'.$langs->trans("AddThirdParty").'"></span>';
719  // TODO @LDR Implement this
720  if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) {
721  $tmpbacktopagejsfields = 'addthirdparty:socid,search_socid';
722  print dolButtonToOpenUrlInDialogPopup('addthirdparty', $langs->transnoentitiesnoconv('AddThirdParty'), $newbutton, $url, '', '', '', $tmpbacktopagejsfields);
723  } else {
724  print ' <a href="'.DOL_URL_ROOT.$url.'">'.$newbutton.'</a>';
725  }
726  }
727  print '</td></tr>';
728  }
729 
730  // Status
731  if ($status != '') {
732  print '<tr><td>'.$langs->trans("Status").'</td><td>';
733  print '<input type="hidden" name="status" value="'.$status.'">';
734  print $object->LibStatut($status, 4);
735  print '</td></tr>';
736  }
737 
738  // Visibility
739  print '<tr><td>'.$langs->trans("Visibility").'</td><td class="maxwidthonsmartphone">';
740  $array = array();
741  if (empty($conf->global->PROJECT_DISABLE_PRIVATE_PROJECT)) {
742  $array[0] = $langs->trans("PrivateProject");
743  }
744  if (empty($conf->global->PROJECT_DISABLE_PUBLIC_PROJECT)) {
745  $array[1] = $langs->trans("SharedProject");
746  }
747 
748  if (count($array) > 0) {
749  print $form->selectarray('public', $array, GETPOST('public'), 0, 0, 0, '', 0, 0, 0, '', '', 1);
750  } else {
751  print '<input type="hidden" name="public" id="public" value="'.GETPOST('public').'">';
752 
753  if (GETPOST('public') == 0) {
754  print img_picto($langs->trans('PrivateProject'), 'private', 'class="paddingrightonly"');
755  print $langs->trans("PrivateProject");
756  } else {
757  print img_picto($langs->trans('SharedProject'), 'world', 'class="paddingrightonly"');
758  print $langs->trans("SharedProject");
759  }
760  }
761  print '</td></tr>';
762 
763  if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES)) {
764  // Opportunity status
765  print '<tr class="classuseopportunity"><td><span class="fieldrequired">'.$langs->trans("OpportunityStatus").'</span></td>';
766  print '<td class="maxwidthonsmartphone">';
767  print $formproject->selectOpportunityStatus('opp_status', GETPOSTISSET('opp_status') ? GETPOST('opp_status') : $object->opp_status, 1, 0, 0, 0, '', 0, 1);
768 
769  // Opportunity probability
770  print ' <input class="width50 right" type="text" id="opp_percent" name="opp_percent" title="'.dol_escape_htmltag($langs->trans("OpportunityProbability")).'" value="'.dol_escape_htmltag(GETPOSTISSET('opp_percent') ? GETPOST('opp_percent') : '').'"><span class="hideonsmartphone"> %</span>';
771  print '<input type="hidden" name="opp_percent_not_set" id="opp_percent_not_set" value="'.dol_escape_htmltag(GETPOSTISSET('opp_percent') ? '0' : '1').'">';
772  print '</td>';
773  print '</tr>';
774 
775  // Opportunity amount
776  print '<tr class="classuseopportunity"><td>'.$langs->trans("OpportunityAmount").'</td>';
777  print '<td><input class="width75 right" type="text" name="opp_amount" value="'.dol_escape_htmltag(GETPOSTISSET('opp_amount') ? GETPOST('opp_amount') : '').'">';
778  print ' '.$langs->getCurrencySymbol($conf->currency);
779  print '</td>';
780  print '</tr>';
781  }
782 
783  // Budget
784  print '<tr><td>'.$langs->trans("Budget").'</td>';
785  print '<td><input class="width75 right" type="text" name="budget_amount" value="'.dol_escape_htmltag(GETPOSTISSET('budget_amount') ? GETPOST('budget_amount') : '').'">';
786  print ' '.$langs->getCurrencySymbol($conf->currency);
787  print '</td>';
788  print '</tr>';
789 
790  // Date project
791  print '<tr><td>'.$langs->trans("Date").(isModEnabled('eventorganization') ? ' <span class="classuseorganizeevent">('.$langs->trans("Project").')</span>' : '').'</td><td>';
792  print $form->selectDate(($date_start ? $date_start : ''), 'projectstart', 0, 0, 0, '', 1, 0);
793  print ' <span class="opacitymedium"> '.$langs->trans("to").' </span> ';
794  print $form->selectDate(($date_end ? $date_end : -1), 'projectend', 0, 0, 0, '', 1, 0);
795  print '</td></tr>';
796 
797  if (isModEnabled('eventorganization')) {
798  // Date event
799  print '<tr class="classuseorganizeevent"><td>'.$langs->trans("Date").' ('.$langs->trans("Event").')</td><td>';
800  print $form->selectDate(($date_start_event ? $date_start_event : -1), 'date_start_event', 1, 1, 1, '', 1, 0);
801  print ' <span class="opacitymedium"> '.$langs->trans("to").' </span> ';
802  print $form->selectDate(($date_end_event ? $date_end_event : -1), 'date_end_event', 1, 1, 1, '', 1, 0);
803  print '</td></tr>';
804 
805  // Location
806  print '<tr class="classuseorganizeevent"><td>'.$langs->trans("Location").'</td>';
807  print '<td><input class="minwidth300 maxwidth500" type="text" name="location" value="'.dol_escape_htmltag($location).'"></td>';
808  print '</tr>';
809  }
810 
811  // Description
812  print '<tr><td class="tdtop">'.$langs->trans("Description").'</td>';
813  print '<td>';
814  $doleditor = new DolEditor('description', GETPOST("description", 'restricthtml'), '', 90, 'dolibarr_notes', '', false, true, getDolGlobalString('FCKEDITOR_ENABLE_SOCIETE'), ROWS_3, '90%');
815  $doleditor->Create();
816  print '</td></tr>';
817 
818  if (isModEnabled('categorie')) {
819  // Categories
820  print '<tr><td>'.$langs->trans("Categories").'</td><td colspan="3">';
821  $cate_arbo = $form->select_all_categories(Categorie::TYPE_PROJECT, '', 'parent', 64, 0, 1);
822  $arrayselected = GETPOST('categories', 'array');
823  print img_picto('', 'category', 'class="pictofixedwidth"').$form->multiselectarray('categories', $cate_arbo, $arrayselected, '', 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0);
824  print "</td></tr>";
825  }
826 
827  // Other options
828  $parameters = array();
829  $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
830  print $hookmanager->resPrint;
831  if (empty($reshook)) {
832  print $object->showOptionals($extrafields, 'create');
833  }
834 
835  print '</table>';
836 
837  print dol_get_fiche_end();
838 
839  print $form->buttonsSaveCancel('CreateDraft');
840 
841  print '</form>';
842 
843  // Change probability from status or role of project
844  // Set also dependencies between use taks and bill time
845  print '<script type="text/javascript">
846  jQuery(document).ready(function() {
847  function change_percent()
848  {
849  var element = jQuery("#opp_status option:selected");
850  var defaultpercent = element.attr("defaultpercent");
851  /*if (jQuery("#opp_percent_not_set").val() == "") */
852  jQuery("#opp_percent").val(defaultpercent);
853  }
854 
855  /*init_myfunc();*/
856  jQuery("#opp_status").change(function() {
857  change_percent();
858  });
859 
860  jQuery("#usage_task").change(function() {
861  console.log("We click on usage task "+jQuery("#usage_task").is(":checked"));
862  if (! jQuery("#usage_task").is(":checked")) {
863  jQuery("#usage_bill_time").prop("checked", false);
864  }
865  });
866 
867  jQuery("#usage_bill_time").change(function() {
868  console.log("We click on usage to bill time");
869  if (jQuery("#usage_bill_time").is(":checked")) {
870  jQuery("#usage_task").prop("checked", true);
871  }
872  });
873  });
874  </script>';
875 } elseif ($object->id > 0) {
876  /*
877  * Show or edit
878  */
879 
880  $res = $object->fetch_optionals();
881 
882  // To verify role of users
883  $userAccess = $object->restrictedProjectArea($user, 'read');
884  $userWrite = $object->restrictedProjectArea($user, 'write');
885  $userDelete = $object->restrictedProjectArea($user, 'delete');
886  //print "userAccess=".$userAccess." userWrite=".$userWrite." userDelete=".$userDelete;
887 
888 
889  // Confirmation validation
890  if ($action == 'validate') {
891  print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ValidateProject'), $langs->trans('ConfirmValidateProject'), 'confirm_validate', '', 0, 1);
892  }
893  // Confirmation close
894  if ($action == 'close') {
895  print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id, $langs->trans("CloseAProject"), $langs->trans("ConfirmCloseAProject"), "confirm_close", '', '', 1);
896  }
897  // Confirmation reopen
898  if ($action == 'reopen') {
899  print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id, $langs->trans("ReOpenAProject"), $langs->trans("ConfirmReOpenAProject"), "confirm_reopen", '', '', 1);
900  }
901  // Confirmation delete
902  if ($action == 'delete') {
903  $text = $langs->trans("ConfirmDeleteAProject");
904  $task = new Task($db);
905  $taskarray = $task->getTasksArray(0, 0, $object->id, 0, 0);
906  $nboftask = count($taskarray);
907  if ($nboftask) {
908  $text .= '<br>'.img_warning().' '.$langs->trans("ThisWillAlsoRemoveTasks", $nboftask);
909  }
910  print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id, $langs->trans("DeleteAProject"), $text, "confirm_delete", '', '', 1);
911  }
912 
913  // Clone confirmation
914  if ($action == 'clone') {
915  $formquestion = array(
916  'text' => $langs->trans("ConfirmClone"),
917  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 maxwidth250')),
918  array('type' => 'checkbox', 'name' => 'clone_contacts', 'label' => $langs->trans("CloneContacts"), 'value' => true),
919  array('type' => 'checkbox', 'name' => 'clone_tasks', 'label' => $langs->trans("CloneTasks"), 'value' => true),
920  array('type' => 'checkbox', 'name' => 'move_date', 'label' => $langs->trans("CloneMoveDate"), 'value' => true),
921  array('type' => 'checkbox', 'name' => 'clone_notes', 'label' => $langs->trans("CloneNotes"), 'value' => true),
922  array('type' => 'checkbox', 'name' => 'clone_project_files', 'label' => $langs->trans("CloneProjectFiles"), 'value' => false),
923  array('type' => 'checkbox', 'name' => 'clone_task_files', 'label' => $langs->trans("CloneTaskFiles"), 'value' => false)
924  );
925 
926  print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id, $langs->trans("ToClone"), $langs->trans("ConfirmCloneProject"), "confirm_clone", $formquestion, '', 1, 400, 590);
927  }
928 
929 
930  print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
931  print '<input type="hidden" name="token" value="'.newToken().'">';
932  print '<input type="hidden" name="action" value="update">';
933  print '<input type="hidden" name="id" value="'.$object->id.'">';
934  print '<input type="hidden" name="comefromclone" value="'.$comefromclone.'">';
935 
936  $head = project_prepare_head($object);
937 
938  if ($action == 'edit' && $userWrite > 0) {
939  print dol_get_fiche_head($head, 'project', $langs->trans("Project"), 0, ($object->public ? 'projectpub' : 'project'));
940 
941  print '<table class="border centpercent">';
942 
943  // Ref
944  $suggestedref = $object->ref;
945  print '<tr><td class="titlefield fieldrequired">'.$langs->trans("Ref").'</td>';
946  print '<td><input size="25" name="ref" value="'.$suggestedref.'">';
947  print ' '.$form->textwithpicto('', $langs->trans("YouCanCompleteRef", $suggestedref));
948  print '</td></tr>';
949 
950  // Label
951  print '<tr><td class="fieldrequired">'.$langs->trans("Label").'</td>';
952  print '<td><input class="quatrevingtpercent" name="title" value="'.dol_escape_htmltag($object->title).'"></td></tr>';
953 
954  // Status
955  print '<tr><td class="fieldrequired">'.$langs->trans("Status").'</td><td>';
956  print '<select class="flat" name="status" id="status">';
957  foreach ($object->statuts_short as $key => $val) {
958  print '<option value="'.$key.'"'.((GETPOSTISSET('status') ? GETPOST('status') : $object->statut) == $key ? ' selected="selected"' : '').'>'.$langs->trans($val).'</option>';
959  }
960  print '</select>';
961  print ajax_combobox('status');
962  print '</td></tr>';
963 
964  // Usage
965  if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES) || empty($conf->global->PROJECT_HIDE_TASKS) || isModEnabled('eventorganization')) {
966  print '<tr><td class="tdtop">';
967  print $langs->trans("Usage");
968  print '</td>';
969  print '<td>';
970  if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES)) {
971  print '<input type="checkbox" id="usage_opportunity" name="usage_opportunity"'.(GETPOSTISSET('usage_opportunity') ? (GETPOST('usage_opportunity', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_opportunity ? ' checked="checked"' : '')).'> ';
972  $htmltext = $langs->trans("ProjectFollowOpportunity");
973  print '<label for="usage_opportunity">'.$form->textwithpicto($langs->trans("ProjectFollowOpportunity"), $htmltext).'</label>';
974  print '<script>';
975  print '$( document ).ready(function() {
976  jQuery("#usage_opportunity").change(function() {
977  set_usage_opportunity();
978  });
979 
980  set_usage_opportunity();
981 
982  function set_usage_opportunity() {
983  console.log("set_usage_opportunity");
984  if (jQuery("#usage_opportunity").prop("checked")) {
985  console.log("Show opportunities fields");
986  jQuery(".classuseopportunity").show();
987  } else {
988  console.log("Hide opportunities fields "+jQuery("#usage_opportunity").prop("checked"));
989  jQuery(".classuseopportunity").hide();
990  }
991  }
992  });';
993  print '</script>';
994  print '<br>';
995  }
996  if (empty($conf->global->PROJECT_HIDE_TASKS)) {
997  print '<input type="checkbox" id="usage_task" name="usage_task"' . (GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_task ? ' checked="checked"' : '')) . '> ';
998  $htmltext = $langs->trans("ProjectFollowTasks");
999  print '<label for="usage_task">'.$form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext).'</label>';
1000  print '<script>';
1001  print '$( document ).ready(function() {
1002  jQuery("#usage_task").change(function() {
1003  set_usage_task();
1004  });
1005 
1006  set_usage_task();
1007 
1008  function set_usage_task() {
1009  console.log("set_usage_task");
1010  if (jQuery("#usage_task").prop("checked")) {
1011  console.log("Show task fields");
1012  jQuery(".classusetask").show();
1013  } else {
1014  console.log("Hide task fields "+jQuery("#usage_task").prop("checked"));
1015  jQuery(".classusetask").hide();
1016  }
1017  }
1018  });';
1019  print '</script>';
1020  print '<br>';
1021  }
1022  if (empty($conf->global->PROJECT_HIDE_TASKS) && !empty($conf->global->PROJECT_BILL_TIME_SPENT)) {
1023  print '<input type="checkbox" id="usage_bill_time" name="usage_bill_time"' . (GETPOSTISSET('usage_bill_time') ? (GETPOST('usage_bill_time', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_bill_time ? ' checked="checked"' : '')) . '> ';
1024  $htmltext = $langs->trans("ProjectBillTimeDescription");
1025  print '<label for="usage_bill_time">'.$form->textwithpicto($langs->trans("BillTime"), $htmltext).'</label>';
1026  print '<script>';
1027  print '$( document ).ready(function() {
1028  jQuery("#usage_bill_time").change(function() {
1029  set_usage_bill_time();
1030  });
1031 
1032  set_usage_bill_time();
1033 
1034  function set_usage_bill_time() {
1035  console.log("set_usage_bill_time");
1036  if (jQuery("#usage_bill_time").prop("checked")) {
1037  console.log("Show bill time fields");
1038  jQuery(".classusebilltime").show();
1039  } else {
1040  console.log("Hide bill time fields "+jQuery("#usage_bill_time").prop("checked"));
1041  jQuery(".classusebilltime").hide();
1042  }
1043  }
1044  });';
1045  print '</script>';
1046  print '<br>';
1047  }
1048  if (isModEnabled('eventorganization')) {
1049  print '<input type="checkbox" id="usage_organize_event" name="usage_organize_event"'. (GETPOSTISSET('usage_organize_event') ? (GETPOST('usage_organize_event', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_organize_event ? ' checked="checked"' : '')) . '> ';
1050  $htmltext = $langs->trans("EventOrganizationDescriptionLong");
1051  print '<label for="usage_organize_event">'.$form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext).'</label>';
1052  print '<script>';
1053  print '$( document ).ready(function() {
1054  jQuery("#usage_organize_event").change(function() {
1055  set_usage_event();
1056  });
1057 
1058  set_usage_event();
1059 
1060  function set_usage_event() {
1061  console.log("set_usage_event");
1062  if (jQuery("#usage_organize_event").prop("checked")) {
1063  console.log("Show organize event fields");
1064  jQuery(".classuseorganizeevent").show();
1065  } else {
1066  console.log("Hide organize event fields "+jQuery("#usage_organize_event").prop("checked"));
1067  jQuery(".classuseorganizeevent").hide();
1068  }
1069  }
1070  });';
1071  print '</script>';
1072  }
1073  print '</td></tr>';
1074  }
1075  print '</td></tr>';
1076 
1077  // Thirdparty
1078  if (isModEnabled('societe')) {
1079  print '<tr><td>';
1080  print (empty($conf->global->PROJECT_THIRDPARTY_REQUIRED) ? '' : '<span class="fieldrequired">');
1081  print $langs->trans("ThirdParty");
1082  print (empty($conf->global->PROJECT_THIRDPARTY_REQUIRED) ? '' : '</span>');
1083  print '</td><td>';
1084  $filter = '';
1085  if (!empty($conf->global->PROJECT_FILTER_FOR_THIRDPARTY_LIST)) {
1086  $filter = $conf->global->PROJECT_FILTER_FOR_THIRDPARTY_LIST;
1087  }
1088  $text = img_picto('', 'company', 'class="pictofixedwidth"');
1089  $text .= $form->select_company($object->thirdparty->id, 'socid', $filter, 'None', 1, 0, array(), 0, 'minwidth300');
1090  if (empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS) && empty($conf->dol_use_jmobile)) {
1091  $texthelp = $langs->trans("IfNeedToUseOtherObjectKeepEmpty");
1092  print $form->textwithtooltip($text.' '.img_help(), $texthelp, 1, 0, '', '', 2);
1093  } else {
1094  print $text;
1095  }
1096  print '</td></tr>';
1097  }
1098 
1099  // Visibility
1100  print '<tr><td>'.$langs->trans("Visibility").'</td><td>';
1101  $array = array();
1102  if (empty($conf->global->PROJECT_DISABLE_PRIVATE_PROJECT)) {
1103  $array[0] = $langs->trans("PrivateProject");
1104  }
1105  if (empty($conf->global->PROJECT_DISABLE_PUBLIC_PROJECT)) {
1106  $array[1] = $langs->trans("SharedProject");
1107  }
1108 
1109  if (count($array) > 0) {
1110  print $form->selectarray('public', $array, $object->public, 0, 0, 0, '', 0, 0, 0, '', '', 1);
1111  } else {
1112  print '<input type="hidden" id="public" name="public" value="'.$object->public.'">';
1113 
1114  if ($object->public == 0) {
1115  print img_picto($langs->trans('PrivateProject'), 'private', 'class="paddingrightonly"');
1116  print $langs->trans("PrivateProject");
1117  } else {
1118  print img_picto($langs->trans('SharedProject'), 'world', 'class="paddingrightonly"');
1119  print $langs->trans("SharedProject");
1120  }
1121  }
1122  print '</td></tr>';
1123 
1124  if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES)) {
1125  $classfortr = ($object->usage_opportunity ? '' : ' hideobject');
1126  // Opportunity status
1127  print '<tr class="classuseopportunity'.$classfortr.'"><td>'.$langs->trans("OpportunityStatus").'</td>';
1128  print '<td>';
1129  print '<div>';
1130  print $formproject->selectOpportunityStatus('opp_status', $object->opp_status, 1, 0, 0, 0, 'minwidth150 inline-block valignmiddle', 1, 1);
1131 
1132  // Opportunity probability
1133  print ' <input class="width50 right" type="text" id="opp_percent" name="opp_percent" title="'.dol_escape_htmltag($langs->trans("OpportunityProbability")).'" value="'.(GETPOSTISSET('opp_percent') ? GETPOST('opp_percent') : (strcmp($object->opp_percent, '') ?vatrate($object->opp_percent) : '')).'"> %';
1134  print '<span id="oldopppercent" class="opacitymedium"></span>';
1135  print '</div>';
1136 
1137  print '<div id="divtocloseproject" class="inline-block valign clearboth paddingtop" style="display: none;">';
1138  print '<input type="checkbox" id="inputcloseproject" name="closeproject" />';
1139  print '<label for="inputcloseproject">';
1140  print $form->textwithpicto($langs->trans("AlsoCloseAProject"), $langs->trans("AlsoCloseAProjectTooltip")).'</label>';
1141  print ' </div>';
1142 
1143  print '</td>';
1144  print '</tr>';
1145 
1146  // Opportunity amount
1147  print '<tr class="classuseopportunity'.$classfortr.'"><td>'.$langs->trans("OpportunityAmount").'</td>';
1148  print '<td><input class="width75 right" type="text" name="opp_amount" value="'.(GETPOSTISSET('opp_amount') ? GETPOST('opp_amount') : (strcmp($object->opp_amount, '') ? price2num($object->opp_amount) : '')).'">';
1149  print $langs->getCurrencySymbol($conf->currency);
1150  print '</td>';
1151  print '</tr>';
1152  }
1153 
1154  // Budget
1155  print '<tr><td>'.$langs->trans("Budget").'</td>';
1156  print '<td><input class="width75 right" type="text" name="budget_amount" value="'.(GETPOSTISSET('budget_amount') ? GETPOST('budget_amount') : (strcmp($object->budget_amount, '') ? price2num($object->budget_amount) : '')).'">';
1157  print $langs->getCurrencySymbol($conf->currency);
1158  print '</td>';
1159  print '</tr>';
1160 
1161  // Date project
1162  print '<tr><td>'.$langs->trans("Date").(isModEnabled('eventorganization') ? ' <span class="classuseorganizeevent">('.$langs->trans("Project").')</span>' : '').'</td><td>';
1163  print $form->selectDate($object->date_start ? $object->date_start : -1, 'projectstart', 0, 0, 0, '', 1, 0);
1164  print ' <span class="opacitymedium"> '.$langs->trans("to").' </span> ';
1165  print $form->selectDate($object->date_end ? $object->date_end : -1, 'projectend', 0, 0, 0, '', 1, 0);
1166  $object->getLinesArray(null, 0);
1167  if (!empty($object->usage_task) && !empty($object->lines)) {
1168  print ' <span id="divreportdate" class="hidden">&nbsp; &nbsp; <input type="checkbox" class="valignmiddle" id="reportdate" name="reportdate" value="yes" ';
1169  if ($comefromclone) {
1170  print 'checked ';
1171  }
1172  print '/><label for="reportdate" class="valignmiddle opacitymedium">'.$langs->trans("ProjectReportDate").'</label></span>';
1173  }
1174  print '</td></tr>';
1175 
1176  if (isModEnabled('eventorganization')) {
1177  // Date event
1178  print '<tr class="classuseorganizeevent"><td>'.$langs->trans("Date").' ('.$langs->trans("Event").')</td><td>';
1179  print $form->selectDate(($date_start_event ? $date_start_event : ($object->date_start_event ? $object->date_start_event : -1)), 'date_start_event', 1, 1, 1, '', 1, 0);
1180  print ' <span class="opacitymedium"> '.$langs->trans("to").' </span> ';
1181  print $form->selectDate(($date_end_event ? $date_end_event : ($object->date_end_event ? $object->date_end_event : -1)), 'date_end_event', 1, 1, 1, '', 1, 0);
1182  print '</td></tr>';
1183 
1184  // Location
1185  print '<tr class="classuseorganizeevent"><td>'.$langs->trans("Location").'</td>';
1186  print '<td><input class="minwidth300 maxwidth500" type="text" name="location" value="'.dol_escape_htmltag(GETPOSTISSET('location') ? GETPOST('location') : $object->location).'"></td>';
1187  print '</tr>';
1188  }
1189 
1190  // Description
1191  print '<tr><td class="tdtop">'.$langs->trans("Description").'</td>';
1192  print '<td>';
1193  $doleditor = new DolEditor('description', $object->description, '', 90, 'dolibarr_notes', '', false, true, getDolGlobalInt('FCKEDITOR_ENABLE_SOCIETE'), ROWS_3, '90%');
1194  $doleditor->Create();
1195  print '</td></tr>';
1196 
1197  // Tags-Categories
1198  if (isModEnabled('categorie')) {
1199  print '<tr><td>'.$langs->trans("Categories").'</td><td>';
1200  $cate_arbo = $form->select_all_categories(Categorie::TYPE_PROJECT, '', 'parent', 64, 0, 1);
1201  $c = new Categorie($db);
1202  $cats = $c->containing($object->id, Categorie::TYPE_PROJECT);
1203  foreach ($cats as $cat) {
1204  $arrayselected[] = $cat->id;
1205  }
1206  print img_picto('', 'category', 'class="pictofixedwidth"').$form->multiselectarray('categories', $cate_arbo, $arrayselected, 0, 0, 'quatrevingtpercent widthcentpercentminusx', 0, '0');
1207  print "</td></tr>";
1208  }
1209 
1210  // Other options
1211  $parameters = array();
1212  $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1213  print $hookmanager->resPrint;
1214  if (empty($reshook)) {
1215  print $object->showOptionals($extrafields, 'edit');
1216  }
1217 
1218  print '</table>';
1219  } else {
1220  print dol_get_fiche_head($head, 'project', $langs->trans("Project"), -1, ($object->public ? 'projectpub' : 'project'));
1221 
1222  // Project card
1223 
1224  $linkback = '<a href="'.DOL_URL_ROOT.'/projet/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
1225 
1226  $morehtmlref = '<div class="refidno">';
1227  // Title
1228  $morehtmlref .= dol_escape_htmltag($object->title);
1229  $morehtmlref .= '<br>';
1230  // Thirdparty
1231  if (!empty($object->thirdparty->id) && $object->thirdparty->id > 0) {
1232  $morehtmlref .= $object->thirdparty->getNomUrl(1, 'project');
1233  }
1234  $morehtmlref .= '</div>';
1235 
1236  // Define a complementary filter for search of next/prev ref.
1237  if (empty($user->rights->projet->all->lire)) {
1238  $objectsListId = $object->getProjectsAuthorizedForUser($user, 0, 0);
1239  $object->next_prev_filter = " rowid IN (".$db->sanitize(count($objectsListId) ? join(',', array_keys($objectsListId)) : '0').")";
1240  }
1241 
1242  dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
1243 
1244  print '<div class="fichecenter">';
1245  print '<div class="fichehalfleft">';
1246  print '<div class="underbanner clearboth"></div>';
1247 
1248  print '<table class="border tableforfield centpercent">';
1249 
1250  // Usage
1251  if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES) || empty($conf->global->PROJECT_HIDE_TASKS) || isModEnabled('eventorganization')) {
1252  print '<tr><td class="tdtop">';
1253  print $langs->trans("Usage");
1254  print '</td>';
1255  print '<td>';
1256  if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES)) {
1257  print '<input type="checkbox" disabled name="usage_opportunity"'.(GETPOSTISSET('usage_opportunity') ? (GETPOST('usage_opportunity', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_opportunity ? ' checked="checked"' : '')).'> ';
1258  $htmltext = $langs->trans("ProjectFollowOpportunity");
1259  print $form->textwithpicto($langs->trans("ProjectFollowOpportunity"), $htmltext);
1260  print '<br>';
1261  }
1262  if (empty($conf->global->PROJECT_HIDE_TASKS)) {
1263  print '<input type="checkbox" disabled name="usage_task"'.(GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_task ? ' checked="checked"' : '')).'> ';
1264  $htmltext = $langs->trans("ProjectFollowTasks");
1265  print $form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext);
1266  print '<br>';
1267  }
1268  if (empty($conf->global->PROJECT_HIDE_TASKS) && !empty($conf->global->PROJECT_BILL_TIME_SPENT)) {
1269  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"' : '')).'> ';
1270  $htmltext = $langs->trans("ProjectBillTimeDescription");
1271  print $form->textwithpicto($langs->trans("BillTime"), $htmltext);
1272  print '<br>';
1273  }
1274 
1275  if (isModEnabled('eventorganization')) {
1276  print '<input type="checkbox" disabled name="usage_organize_event"'.(GETPOSTISSET('usage_organize_event') ? (GETPOST('usage_organize_event', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_organize_event ? ' checked="checked"' : '')).'> ';
1277  $htmltext = $langs->trans("EventOrganizationDescriptionLong");
1278  print $form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext);
1279  }
1280  print '</td></tr>';
1281  }
1282 
1283  // Visibility
1284  print '<tr><td class="titlefield">'.$langs->trans("Visibility").'</td><td>';
1285  if ($object->public) {
1286  print img_picto($langs->trans('SharedProject'), 'world', 'class="paddingrightonly"');
1287  print $langs->trans('SharedProject');
1288  } else {
1289  print img_picto($langs->trans('PrivateProject'), 'private', 'class="paddingrightonly"');
1290  print $langs->trans('PrivateProject');
1291  }
1292  print '</td></tr>';
1293 
1294  if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES) && !empty($object->usage_opportunity)) {
1295  // Opportunity status
1296  print '<tr><td>'.$langs->trans("OpportunityStatus").'</td><td>';
1297  $code = dol_getIdFromCode($db, $object->opp_status, 'c_lead_status', 'rowid', 'code');
1298  if ($code) {
1299  print $langs->trans("OppStatus".$code);
1300  }
1301 
1302  // Opportunity percent
1303  print ' <span title="'.$langs->trans("OpportunityProbability").'"> / ';
1304  if (strcmp($object->opp_percent, '')) {
1305  print price($object->opp_percent, 0, $langs, 1, 0).' %';
1306  }
1307  print '</span></td></tr>';
1308 
1309  // Opportunity Amount
1310  print '<tr><td>'.$langs->trans("OpportunityAmount").'</td><td>';
1311  if (strcmp($object->opp_amount, '')) {
1312  print '<span class="amount">'.price($object->opp_amount, 0, $langs, 1, 0, -1, $conf->currency).'</span>';
1313  if (strcmp($object->opp_percent, '')) {
1314  print ' &nbsp; &nbsp; &nbsp; <span title="'.dol_escape_htmltag($langs->trans('OpportunityWeightedAmount')).'"><span class="opacitymedium">'.$langs->trans("Weighted").'</span>: <span class="amount">'.price($object->opp_amount * $object->opp_percent / 100, 0, $langs, 1, 0, -1, $conf->currency).'</span></span>';
1315  }
1316  }
1317  print '</td></tr>';
1318  }
1319 
1320  // Budget
1321  print '<tr><td>'.$langs->trans("Budget").'</td><td>';
1322  if (!is_null($object->budget_amount) && strcmp($object->budget_amount, '')) {
1323  print '<span class="amount">'.price($object->budget_amount, 0, $langs, 1, 0, 0, $conf->currency).'</span>';
1324  }
1325  print '</td></tr>';
1326 
1327  // Date start - end project
1328  print '<tr><td>'.$langs->trans("Dates").'</td><td>';
1329  $start = dol_print_date($object->date_start, 'day');
1330  print ($start ? $start : '?');
1331  $end = dol_print_date($object->date_end, 'day');
1332  print ' <span class="opacitymedium">-</span> ';
1333  print ($end ? $end : '?');
1334  if ($object->hasDelay()) {
1335  print img_warning("Late");
1336  }
1337  print '</td></tr>';
1338 
1339  // Other attributes
1340  $cols = 2;
1341  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
1342 
1343  print '</table>';
1344 
1345  print '</div>';
1346  print '<div class="fichehalfright">';
1347  print '<div class="underbanner clearboth"></div>';
1348 
1349  print '<table class="border tableforfield centpercent">';
1350 
1351  // Description
1352  print '<td class="titlefield tdtop">'.$langs->trans("Description").'</td><td>';
1353  print dol_htmlentitiesbr($object->description);
1354  print '</td></tr>';
1355 
1356  // Categories
1357  if (isModEnabled('categorie')) {
1358  print '<tr><td class="valignmiddle">'.$langs->trans("Categories").'</td><td>';
1359  print $form->showCategories($object->id, Categorie::TYPE_PROJECT, 1);
1360  print "</td></tr>";
1361  }
1362 
1363  print '</table>';
1364 
1365  print '</div>';
1366  print '</div>';
1367 
1368  print '<div class="clearboth"></div>';
1369  }
1370 
1371  print dol_get_fiche_end();
1372 
1373  if ($action == 'edit' && $userWrite > 0) {
1374  print $form->buttonsSaveCancel();
1375  }
1376 
1377  print '</form>';
1378 
1379  // Set also dependencies between use taks and bill time
1380  print '<script type="text/javascript">
1381  jQuery(document).ready(function() {
1382  jQuery("#usage_task").change(function() {
1383  console.log("We click on usage task "+jQuery("#usage_task").is(":checked"));
1384  if (! jQuery("#usage_task").is(":checked")) {
1385  jQuery("#usage_bill_time").prop("checked", false);
1386  }
1387  });
1388 
1389  jQuery("#usage_bill_time").change(function() {
1390  console.log("We click on usage to bill time");
1391  if (jQuery("#usage_bill_time").is(":checked")) {
1392  jQuery("#usage_task").prop("checked", true);
1393  }
1394  });
1395 
1396  jQuery("#projectstart").change(function() {
1397  console.log("We modify the start date");
1398  jQuery("#divreportdate").show();
1399  });
1400  });
1401  </script>';
1402 
1403  // Change probability from status
1404  if (!empty($conf->use_javascript_ajax) && !empty($conf->global->PROJECT_USE_OPPORTUNITIES)) {
1405  // Default value to close or not when we set opp to 'WON'.
1406  $defaultcheckedwhenoppclose = 1;
1407  if (empty($conf->global->PROJECT_HIDE_TASKS)) {
1408  $defaultcheckedwhenoppclose = 0;
1409  }
1410 
1411  print '<!-- Javascript to manage opportunity status change -->';
1412  print '<script type="text/javascript">
1413  jQuery(document).ready(function() {
1414  function change_percent()
1415  {
1416  var element = jQuery("#opp_status option:selected");
1417  var defaultpercent = element.attr("defaultpercent");
1418  var defaultcloseproject = '.((int) $defaultcheckedwhenoppclose).';
1419  var elemcode = element.attr("elemcode");
1420  var oldpercent = \''.dol_escape_js($object->opp_percent).'\';
1421 
1422  console.log("We select "+elemcode);
1423 
1424  /* Define if checkbox to close is checked or not */
1425  var closeproject = 0;
1426  if (elemcode == \'LOST\') closeproject = 1;
1427  if (elemcode == \'WON\') closeproject = defaultcloseproject;
1428  if (closeproject) jQuery("#inputcloseproject").prop("checked", true);
1429  else jQuery("#inputcloseproject").prop("checked", false);
1430 
1431  /* Make the close project checkbox visible or not */
1432  console.log("closeproject="+closeproject);
1433  if (elemcode == \'WON\' || elemcode == \'LOST\')
1434  {
1435  jQuery("#divtocloseproject").show();
1436  }
1437  else
1438  {
1439  jQuery("#divtocloseproject").hide();
1440  }
1441 
1442  /* Change percent with default percent (defaultpercent) if new status (defaultpercent) is higher than current (jQuery("#opp_percent").val()) */
1443  if (oldpercent != \'\' && (parseFloat(defaultpercent) < parseFloat(oldpercent)))
1444  {
1445  console.log("oldpercent="+oldpercent+" defaultpercent="+defaultpercent+" def < old");
1446  if (jQuery("#opp_percent").val() != \'\' && oldpercent != \'\') {
1447  jQuery("#oldopppercent").text(\' - '.dol_escape_js($langs->transnoentities("PreviousValue")).': \'+price2numjs(oldpercent)+\' %\');
1448  }
1449 
1450  if (parseFloat(oldpercent) != 100 && elemcode != \'LOST\') { jQuery("#opp_percent").val(oldpercent); }
1451  else { jQuery("#opp_percent").val(price2numjs(defaultpercent)); }
1452  } else {
1453  console.log("oldpercent="+oldpercent+" defaultpercent="+defaultpercent);
1454  if (jQuery("#opp_percent").val() == \'\' || (parseFloat(jQuery("#opp_percent").val()) < parseFloat(defaultpercent))) {
1455  if (jQuery("#opp_percent").val() != \'\' && oldpercent != \'\') {
1456  jQuery("#oldopppercent").text(\' - '.dol_escape_js($langs->transnoentities("PreviousValue")).': \'+price2numjs(oldpercent)+\' %\');
1457  }
1458  jQuery("#opp_percent").val(price2numjs(defaultpercent));
1459  }
1460  }
1461  }
1462 
1463  jQuery("#opp_status").change(function() {
1464  change_percent();
1465  });
1466  });
1467  </script>';
1468  }
1469 
1470 
1471  /*
1472  * Actions Buttons
1473  */
1474 
1475  print '<div class="tabsAction">';
1476  $parameters = array();
1477  $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been
1478  // modified by hook
1479  if (empty($reshook)) {
1480  if ($action != "edit" && $action != 'presend') {
1481  // Create event
1482  /*if (isModEnabled('agenda') && !empty($conf->global->MAIN_ADD_EVENT_ON_ELEMENT_CARD)) // Add hidden condition because this is not a
1483  // "workflow" action so should appears somewhere else on
1484  // page.
1485  {
1486  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>';
1487  }*/
1488 
1489  // Send
1490  if (empty($user->socid)) {
1491  if ($object->statut != Project::STATUS_CLOSED) {
1492  print dolGetButtonAction('', $langs->trans('SendMail'), 'default', $_SERVER["PHP_SELF"].'?action=presend&token='.newToken().'&id='.$object->id.'&mode=init#formmailbeforetitle', '');
1493  }
1494  }
1495 
1496  // Accounting Report
1497  /*
1498  $accouting_module_activated = isModEnabled('comptabilite') || isModEnabled('accounting');
1499  if ($accouting_module_activated && $object->statut != Project::STATUS_DRAFT) {
1500  $start = dol_getdate((int) $object->date_start);
1501  $end = dol_getdate((int) $object->date_end);
1502  $url = DOL_URL_ROOT.'/compta/accounting-files.php?projectid='.$object->id;
1503  if (!empty($object->date_start)) $url .= '&amp;date_startday='.$start['mday'].'&amp;date_startmonth='.$start['mon'].'&amp;date_startyear='.$start['year'];
1504  if (!empty($object->date_end)) $url .= '&amp;date_stopday='.$end['mday'].'&amp;date_stopmonth='.$end['mon'].'&amp;date_stopyear='.$end['year'];
1505  print dolGetButtonAction('', $langs->trans('ExportAccountingReportButtonLabel'), 'default', $url, '');
1506  }
1507  */
1508 
1509  // Back to draft
1510  if (!getDolGlobalString('MAIN_DISABLEDRAFTSTATUS') && !getDolGlobalString('MAIN_DISABLEDRAFTSTATUS_PROJECT')) {
1511  if ($object->statut != Project::STATUS_DRAFT && $user->hasRight('projet', 'creer')) {
1512  if ($userWrite > 0) {
1513  print dolGetButtonAction('', $langs->trans('SetToDraft'), 'default', $_SERVER["PHP_SELF"].'?action=confirm_setdraft&amp;confirm=yes&amp;token='.newToken().'&amp;id='.$object->id, '');
1514  } else {
1515  print dolGetButtonAction($langs->trans('NotOwnerOfProject'), $langs->trans('SetToDraft'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
1516  }
1517  }
1518  }
1519 
1520  // Modify
1521  if ($object->statut != Project::STATUS_CLOSED && $user->hasRight('projet', 'creer')) {
1522  if ($userWrite > 0) {
1523  print dolGetButtonAction('', $langs->trans('Modify'), 'default', $_SERVER["PHP_SELF"].'?action=edit&token='.newToken().'&id='.$object->id, '');
1524  } else {
1525  print dolGetButtonAction($langs->trans('NotOwnerOfProject'), $langs->trans('Modify'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
1526  }
1527  }
1528 
1529  // Validate
1530  if ($object->statut == Project::STATUS_DRAFT && $user->hasRight('projet', 'creer')) {
1531  if ($userWrite > 0) {
1532  print dolGetButtonAction('', $langs->trans('Validate'), 'default', $_SERVER["PHP_SELF"].'?action=validate&amp;token='.newToken().'&amp;id='.$object->id, '');
1533  } else {
1534  print dolGetButtonAction($langs->trans('NotOwnerOfProject'), $langs->trans('Validate'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
1535  }
1536  }
1537 
1538  // Close
1539  if ($object->statut == Project::STATUS_VALIDATED && $user->rights->projet->creer) {
1540  if ($userWrite > 0) {
1541  print dolGetButtonAction('', $langs->trans('Close'), 'default', $_SERVER["PHP_SELF"].'?action=close&amp;token='.newToken().'&amp;id='.$object->id, '');
1542  } else {
1543  print dolGetButtonAction($langs->trans('NotOwnerOfProject'), $langs->trans('Close'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
1544  }
1545  }
1546 
1547  // Reopen
1548  if ($object->statut == Project::STATUS_CLOSED && $user->rights->projet->creer) {
1549  if ($userWrite > 0) {
1550  print dolGetButtonAction('', $langs->trans('ReOpen'), 'default', $_SERVER["PHP_SELF"].'?action=reopen&amp;token='.newToken().'&amp;id='.$object->id, '');
1551  } else {
1552  print dolGetButtonAction($langs->trans('NotOwnerOfProject'), $langs->trans('ReOpen'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
1553  }
1554  }
1555 
1556  // Buttons Create
1557  if (empty($conf->global->PROJECT_HIDE_CREATE_OBJECT_BUTTON)) {
1558  $arrayforbutaction = array(
1559  10 => array('lang'=>'propal', 'enabled'=>isModEnabled("propal"), 'perm'=>$user->hasRight('propal', 'creer'), 'label' => 'AddProp', 'url'=>'/comm/propal/card.php?action=create&amp;projectid='.$object->id.'&amp;socid='.$object->socid),
1560  20 => array('lang'=>'orders', 'enabled'=>isModEnabled("commande"), 'perm'=>$user->hasRight('commande', 'creer'), 'label' => 'CreateOrder', 'url'=>'/commande/card.php?action=create&amp;projectid='.$object->id.'&amp;socid='.$object->socid),
1561  30 => array('lang'=>'bills', 'enabled'=>isModEnabled("facture"), 'perm'=>$user->hasRight('facture', 'creer'), 'label' => 'CreateBill', 'url'=>'/compta/facture/card.php?action=create&amp;projectid='.$object->id.'&amp;socid='.$object->socid),
1562  40 => array('lang'=>'supplier_proposal', 'enabled'=>isModEnabled("supplier_proposal"), 'perm'=>$user->hasRight('supplier_proposal', 'creer'), 'label' => 'AddSupplierProposal', 'url'=>'/supplier_proposal/card.php?action=create&amp;projectid='.$object->id.'&amp;socid='.$object->socid),
1563  50 => array('lang'=>'suppliers', 'enabled'=>isModEnabled("supplier_order"), 'perm'=>$user->hasRight('fournisseur', 'commande', 'creer'), 'label' => 'AddSupplierOrder', 'url'=>'/fourn/commande/card.php?action=create&amp;projectid='.$object->id.'&amp;socid='.$object->socid),
1564  60 => array('lang'=>'suppliers', 'enabled'=>isModEnabled("supplier_invoice"), 'perm'=>$user->hasRight('fournisseur', 'facture', 'creer'), 'label' => 'AddSupplierInvoice', 'url'=>'/fourn/facture/card.php?action=create&amp;projectid='.$object->id.'&amp;socid='.$object->socid),
1565  70 => array('lang'=>'interventions', 'enabled'=>isModEnabled("ficheinter"), 'perm'=>$user->hasRight('fichinter', 'creer'), 'label' => 'AddIntervention', 'url'=>'/fichinter/card.php?action=create&amp;projectid='.$object->id.'&amp;socid='.$object->socid),
1566  80 => array('lang'=>'contrats', 'enabled'=>isModEnabled("contrat"), 'perm'=>$user->hasRight('contrat', 'creer'), 'label' => 'AddContract', 'url'=>'/contrat/card.php?action=create&amp;projectid='.$object->id.'&amp;socid='.$object->socid),
1567  90 => array('lang'=>'trips', 'enabled'=>isModEnabled("expensereport"), 'perm'=>$user->hasRight('expensereport', 'creer'), 'label' => 'AddTrip', 'url'=>'/expensereport/card.php?action=create&amp;projectid='.$object->id.'&amp;socid='.$object->socid),
1568  100 => array('lang'=>'donations', 'enabled'=>isModEnabled("don"), 'perm'=>$user->hasRight('don', 'creer'), 'label' => 'AddDonation', 'url'=>'/don/card.php?action=create&amp;projectid='.$object->id.'&amp;socid='.$object->socid),
1569  );
1570 
1571  $params = array('backtopage' => $_SERVER["PHP_SELF"].'?id='.$object->id);
1572 
1573  print dolGetButtonAction($langs->trans("Create"), '', 'default', $arrayforbutaction, '', 1, $params);
1574  }
1575 
1576  // Clone
1577  if ($user->hasRight('projet', 'creer')) {
1578  if ($userWrite > 0) {
1579  print dolGetButtonAction('', $langs->trans('ToClone'), 'default', $_SERVER["PHP_SELF"].'?action=clone&amp;token='.newToken().'&amp;id='.$object->id, '');
1580  } else {
1581  print dolGetButtonAction($langs->trans('NotOwnerOfProject'), $langs->trans('ToClone'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
1582  }
1583  }
1584 
1585  // Delete
1586  if ($user->hasRight('projet', 'supprimer') || ($object->statut == Project::STATUS_DRAFT && $user->hasRight('projet', 'creer'))) {
1587  if ($userDelete > 0 || ($object->statut == Project::STATUS_DRAFT && $user->hasRight('projet', 'creer'))) {
1588  print dolGetButtonAction('', $langs->trans('Delete'), 'delete', $_SERVER["PHP_SELF"].'?action=delete&token='.newToken().'&id='.$object->id, '');
1589  } else {
1590  print dolGetButtonAction($langs->trans('NotOwnerOfProject'), $langs->trans('Delete'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
1591  }
1592  }
1593  }
1594  }
1595 
1596  print "</div>";
1597 
1598  if (GETPOST('modelselected')) {
1599  $action = 'presend';
1600  }
1601 
1602  if ($action != 'presend') {
1603  print '<div class="fichecenter"><div class="fichehalfleft">';
1604  print '<a name="builddoc"></a>'; // ancre
1605 
1606  /*
1607  * Generated documents
1608  */
1609  $filename = dol_sanitizeFileName($object->ref);
1610  $filedir = $conf->project->multidir_output[$object->entity]."/".dol_sanitizeFileName($object->ref);
1611  $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
1612  $genallowed = ($user->hasRight('projet', 'lire') && $userAccess > 0);
1613  $delallowed = ($user->hasRight('projet', 'creer') && $userWrite > 0);
1614 
1615  print $formfile->showdocuments('project', $filename, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 0, 0, '', '', '', '', '', $object);
1616 
1617  print '</div><div class="fichehalfright">';
1618 
1619  $MAXEVENT = 10;
1620 
1621  $morehtmlcenter = dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT.'/projet/messaging.php?id='.$object->id);
1622 
1623  // List of actions on element
1624  include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
1625  $formactions = new FormActions($db);
1626  $somethingshown = $formactions->showactions($object, 'project', 0, 1, '', $MAXEVENT, '', $morehtmlcenter);
1627 
1628  print '</div></div>';
1629  }
1630 
1631  // Presend form
1632  $modelmail = 'project';
1633  $defaulttopic = 'SendProjectRef';
1634  $diroutput = $conf->project->multidir_output[$object->entity];
1635  $autocopy = 'MAIN_MAIL_AUTOCOPY_PROJECT_TO'; // used to know the automatic BCC to add
1636  $trackid = 'proj'.$object->id;
1637 
1638  include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
1639 
1640  // Hook to add more things on page
1641  $parameters = array();
1642  $reshook = $hookmanager->executeHooks('mainCardTabAddMore', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1643 } else {
1644  print $langs->trans("RecordNotFound");
1645 }
1646 
1647 // End of page
1648 llxFooter();
1649 $db->close();
if(GETPOST('button_removefilter_x', 'alpha')||GETPOST('button_removefilter.x', 'alpha')||GETPOST('button_removefilter', 'alpha')) if(GETPOST('button_search_x', 'alpha')||GETPOST('button_search.x', 'alpha')||GETPOST('button_search', 'alpha')) if($action=="save" &&empty($cancel)) $help_url
View.
Definition: agenda.php:118
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.
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:449
if(!defined('NOREQUIRESOC')) if(!defined('NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined('NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined('NOREQUIREAJAX')) llxHeader()
Empty header.
Definition: wrapper.php:56
llxFooter()
Empty footer.
Definition: wrapper.php:70
Class to manage categories.
Class to manage a WYSIWYG editor.
Class to manage standard extra fields.
Class to manage building of HTML components.
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 building of HTML components.
Class to manage projects.
const STATUS_VALIDATED
Open/Validated status.
const STATUS_CLOSED
Closed status.
const STATUS_DRAFT
Draft status.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage tasks.
Definition: task.class.php:40
Class to manage translations.
Class to manage Dolibarr users.
Definition: user.class.php:48
$parameters
Actions.
Definition: card.php:83
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
Definition: files.lib.php:1334
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.
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...
vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0, $html=0)
Return a string with VAT rate label formated for view output Used into pdf and HTML pages.
load_fiche_titre($titre, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
img_help($usehelpcursor=1, $usealttitle=1)
Show help logo with cursor "?".
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0)
Show tabs of a record.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dolGetButtonTitle($label, $helpText='', $iconClass='fa fa-file', $url='', $id='', $status=1, $params=array())
Function dolGetButtonTitle : this kind of buttons are used in title in list.
dolButtonToOpenUrlInDialogPopup($name, $label, $buttonstring, $url, $disabled='', $morecss='classlink button bordertransp', $jsonopen='', $backtopagejsfields='', $accesskey='')
Return HTML code to output a button to open a dialog popup box.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
setEventMessage($mesgs, $style='mesgs', $noduplicate=0)
Set event message in dol_events session object.
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.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
if(!function_exists('dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into javascript code.
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='')
Return an id or code from a code or id.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
dolGetButtonAction($label, $text='', $actionType='default', $url='', $id='', $userRight=1, $params=array())
Function dolGetButtonAction.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
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...
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
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...
project_prepare_head(Project $project, $moreparam='')
Prepare array with list of tabs.
Definition: project.lib.php:39
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=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.