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