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