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