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