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