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