dolibarr 23.0.3
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 jQuery("#opp_percent").val(defaultpercent);
996 }
997
998 /*init_myfunc();*/
999 jQuery("#opp_status").change(function() {
1000 change_percent();
1001 });
1002
1003 jQuery("#usage_task").change(function() {
1004 console.log("We click on usage task "+jQuery("#usage_task").is(":checked"));
1005 if (! jQuery("#usage_task").is(":checked")) {
1006 jQuery("#usage_bill_time").prop("checked", false);
1007 }
1008 });
1009
1010 jQuery("#usage_bill_time").change(function() {
1011 console.log("We click on usage to bill time");
1012 if (jQuery("#usage_bill_time").is(":checked")) {
1013 jQuery("#usage_task").prop("checked", true);
1014 }
1015 });
1016 });
1017 </script>';
1018} elseif ($object->id > 0) {
1019 /*
1020 * Show or edit
1021 */
1022
1023 $res = $object->fetch_optionals();
1024
1025 // To verify role of users
1026 $userAccess = $object->restrictedProjectArea($user, 'read');
1027 $userWrite = $object->restrictedProjectArea($user, 'write');
1028 $userDelete = $object->restrictedProjectArea($user, 'delete');
1029 //print "userAccess=".$userAccess." userWrite=".$userWrite." userDelete=".$userDelete;
1030
1031 $formconfirm = "" ;
1032
1033 // Confirmation validation
1034 if ($action == 'validate') {
1035 $text = $langs->trans('ConfirmValidateProject');
1036 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ValidateProject'), $text, 'confirm_validate', '', 0, 1);
1037 }
1038 // Confirmation close
1039 if ($action == 'close') {
1040 $text = $langs->trans("ConfirmCloseAProject");
1041 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id, $langs->trans("CloseAProject"), $text, "confirm_close", '', '', 1);
1042 }
1043 // Confirmation reopen
1044 if ($action == 'reopen') {
1045 $text = $langs->trans("ConfirmReOpenAProject");
1046 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id, $langs->trans("ReOpenAProject"), $text, "confirm_reopen", '', '', 1);
1047 }
1048 // Confirmation delete
1049 if ($action == 'delete') {
1050 $text = $langs->trans("ConfirmDeleteAProject");
1051 $task = new Task($db);
1052 $taskarray = $task->getTasksArray(null, null, $object->id, 0, 0);
1053 $nboftask = count($taskarray);
1054 if ($nboftask) {
1055 $text .= '<br>'.img_warning().' '.$langs->trans("ThisWillAlsoRemoveTasks", $nboftask);
1056 }
1057 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id, $langs->trans("DeleteAProject"), $text, "confirm_delete", '', '', 1);
1058 }
1059
1060 // Clone confirmation
1061 if ($action == 'clone') {
1062 $text = $langs->trans("ConfirmCloneProject");
1063 $formquestion = array(
1064 'text' => $langs->trans("ConfirmClone"),
1065 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')),
1066 1 => array('type' => 'checkbox', 'name' => 'clone_contacts', 'label' => $langs->trans("CloneContacts"), 'value' => true),
1067 2 => array('type' => 'checkbox', 'name' => 'clone_tasks', 'label' => $langs->trans("CloneTasks"), 'value' => true),
1068 3 => array('type' => 'checkbox', 'name' => 'move_date', 'label' => $langs->trans("CloneMoveDate"), 'value' => true),
1069 4 => array('type' => 'checkbox', 'name' => 'clone_notes', 'label' => $langs->trans("CloneNotes"), 'value' => true),
1070 5 => array('type' => 'checkbox', 'name' => 'clone_project_files', 'label' => $langs->trans("CloneProjectFiles"), 'value' => false),
1071 6 => array('type' => 'checkbox', 'name' => 'clone_task_files', 'label' => $langs->trans("CloneTaskFiles"), 'value' => false)
1072 );
1073
1074 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id, $langs->trans("ToClone"), $text, "confirm_clone", $formquestion, '', 1, 400, 590);
1075 }
1076
1077 // Call Hook formConfirm
1078 $parameters = array('formConfirm' => $formconfirm);
1079 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1080 if (empty($reshook)) {
1081 $formconfirm .= $hookmanager->resPrint;
1082 } elseif ($reshook > 0) {
1083 $formconfirm = $hookmanager->resPrint;
1084 }
1085
1086 // Print form confirm
1087 print $formconfirm;
1088
1089
1090 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
1091 print '<input type="hidden" name="token" value="'.newToken().'">';
1092 print '<input type="hidden" name="action" value="update">';
1093 print '<input type="hidden" name="id" value="'.$object->id.'">';
1094 print '<input type="hidden" name="comefromclone" value="'.$comefromclone.'">';
1095
1096 $head = project_prepare_head($object);
1097
1098 if ($action == 'edit' && $userWrite > 0) {
1099 print dol_get_fiche_head($head, 'project', $langs->trans("Project"), 0, ($object->public ? 'projectpub' : 'project'));
1100
1101 print '<table class="border centpercent">';
1102
1103 // Ref
1104 $suggestedref = $object->ref;
1105 print '<tr><td class="titlefield fieldrequired">'.$langs->trans("Ref").'</td>';
1106 print '<td><input class="width200" name="ref" value="'.$suggestedref.'">';
1107 print ' '.$form->textwithpicto('', $langs->trans("YouCanCompleteRef", $suggestedref));
1108 print '</td></tr>';
1109
1110 // Label
1111 print '<tr><td class="fieldrequired">'.$langs->trans("Label").'</td>';
1112 print '<td><input class="quatrevingtpercent" name="title" value="'.dol_escape_htmltag($object->title).'"></td></tr>';
1113
1114 // Status
1115 print '<tr><td class="fieldrequired">'.$langs->trans("Status").'</td><td>';
1116 print '<select class="flat" name="status" id="status">';
1117 $statuses = $object->labelStatusShort;
1118 if (getDolGlobalString('MAIN_DISABLEDRAFTSTATUS') || getDolGlobalString('MAIN_DISABLEDRAFTSTATUS_PROJECT')) {
1119 unset($statuses[$object::STATUS_DRAFT]);
1120 }
1121 foreach ($statuses as $key => $val) {
1122 print '<option value="'.$key.'"'.((GETPOSTISSET('status') ? GETPOST('status') : $object->status) == $key ? ' selected="selected"' : '').'>'.$langs->trans($val).'</option>';
1123 }
1124 print '</select>';
1125 print ajax_combobox('status');
1126 print '</td></tr>';
1127
1128 // Parent
1129 if (getDolGlobalInt('PROJECT_ENABLE_SUB_PROJECT')) {
1130 print '<tr><td>'.$langs->trans("Parent").'</td><td class="maxwidthonsmartphone">';
1131 print img_picto('', 'project', 'class="pictofixedwidth"');
1132 $formproject->select_projects(-1, (string) $object->fk_project, 'fk_project', 64, 0, 1, 1, 0, 0, 0, '', 0, 0, '', '', '');
1133 print '</td></tr>';
1134 }
1135
1136 // Usage
1137 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES') || !getDolGlobalString('PROJECT_HIDE_TASKS') || isModEnabled('eventorganization')) {
1138 print '<tr><td class="tdtop">';
1139 print $langs->trans("Usage");
1140 print '</td>';
1141 print '<td>';
1142 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) {
1143 print '<input type="checkbox" id="usage_opportunity" name="usage_opportunity"'.(GETPOSTISSET('usage_opportunity') ? (GETPOST('usage_opportunity', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_opportunity ? ' checked="checked"' : '')).'> ';
1144 $htmltext = $langs->trans("ProjectFollowOpportunity");
1145 print '<label for="usage_opportunity">'.$form->textwithpicto($langs->trans("ProjectFollowOpportunity"), $htmltext).'</label>';
1146 print '<script>';
1147 print '$( document ).ready(function() {
1148 jQuery("#usage_opportunity").change(function() {
1149 set_usage_opportunity();
1150 });
1151
1152 set_usage_opportunity();
1153
1154 function set_usage_opportunity() {
1155 console.log("set_usage_opportunity");
1156 if (jQuery("#usage_opportunity").prop("checked")) {
1157 console.log("Show opportunities fields");
1158 jQuery(".classuseopportunity").show();
1159 } else {
1160 console.log("Hide opportunities fields "+jQuery("#usage_opportunity").prop("checked"));
1161 jQuery(".classuseopportunity").hide();
1162 }
1163 }
1164 });';
1165 print '</script>';
1166 print '<br>';
1167 }
1168 if (!getDolGlobalString('PROJECT_HIDE_TASKS')) {
1169 print '<input type="checkbox" id="usage_task" name="usage_task"' . (GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_task ? ' checked="checked"' : '')) . '> ';
1170 $htmltext = $langs->trans("ProjectFollowTasks");
1171 print '<label for="usage_task">'.$form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext).'</label>';
1172 print '<script>';
1173 print '$( document ).ready(function() {
1174 jQuery("#usage_task").change(function() {
1175 set_usage_task();
1176 });
1177
1178 set_usage_task();
1179
1180 function set_usage_task() {
1181 console.log("set_usage_task");
1182 if (jQuery("#usage_task").prop("checked")) {
1183 console.log("Show task fields");
1184 jQuery(".classusetask").show();
1185 } else {
1186 console.log("Hide task fields "+jQuery("#usage_task").prop("checked"));
1187 jQuery(".classusetask").hide();
1188 }
1189 }
1190 });';
1191 print '</script>';
1192 print '<br>';
1193 }
1194 if (!getDolGlobalString('PROJECT_HIDE_TASKS') && getDolGlobalString('PROJECT_BILL_TIME_SPENT')) {
1195 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"' : '')) . '> ';
1196 $htmltext = $langs->trans("ProjectBillTimeDescription");
1197 print '<label for="usage_bill_time">'.$form->textwithpicto($langs->trans("BillTime"), $htmltext).'</label>';
1198 print '<script>';
1199 print '$( document ).ready(function() {
1200 jQuery("#usage_bill_time").change(function() {
1201 set_usage_bill_time();
1202 });
1203
1204 set_usage_bill_time();
1205
1206 function set_usage_bill_time() {
1207 console.log("set_usage_bill_time");
1208 if (jQuery("#usage_bill_time").prop("checked")) {
1209 console.log("Show bill time fields");
1210 jQuery(".classusebilltime").show();
1211 } else {
1212 console.log("Hide bill time fields "+jQuery("#usage_bill_time").prop("checked"));
1213 jQuery(".classusebilltime").hide();
1214 }
1215 }
1216 });';
1217 print '</script>';
1218 print '<br>';
1219 }
1220 if (isModEnabled('eventorganization')) {
1221 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"' : '')) . '> ';
1222 $htmltext = $langs->trans("EventOrganizationDescriptionLong");
1223 print '<label for="usage_organize_event">'.$form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext).'</label>';
1224 print '<script>';
1225 print '$( document ).ready(function() {
1226 jQuery("#usage_organize_event").change(function() {
1227 set_usage_event();
1228 });
1229
1230 set_usage_event();
1231
1232 function set_usage_event() {
1233 console.log("set_usage_event");
1234 if (jQuery("#usage_organize_event").prop("checked")) {
1235 console.log("Show organize event fields");
1236 jQuery(".classuseorganizeevent").show();
1237 } else {
1238 console.log("Hide organize event fields "+jQuery("#usage_organize_event").prop("checked"));
1239 jQuery(".classuseorganizeevent").hide();
1240 }
1241 }
1242 });';
1243 print '</script>';
1244 }
1245 print '</td></tr>';
1246 }
1247 print '</td></tr>';
1248
1249 // Thirdparty
1250 if (isModEnabled('societe')) {
1251 print '<tr><td>';
1252 print(!getDolGlobalString('PROJECT_THIRDPARTY_REQUIRED') ? '' : '<span class="fieldrequired">');
1253 print $langs->trans("ThirdParty");
1254 print(!getDolGlobalString('PROJECT_THIRDPARTY_REQUIRED') ? '' : '</span>');
1255 print '</td><td>';
1256 $filter = '';
1257 if (getDolGlobalString('PROJECT_FILTER_FOR_THIRDPARTY_LIST')) {
1258 $filter = getDolGlobalString('PROJECT_FILTER_FOR_THIRDPARTY_LIST');
1259 }
1260 $text = img_picto('', 'company', 'class="pictofixedwidth"');
1261 $text .= $form->select_company(!empty($object->thirdparty->id) ? $object->thirdparty->id : "", 'socid', $filter, 'None', 1, 0, array(), 0, 'minwidth300');
1262 if (!getDolGlobalString('PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS') && empty($conf->dol_use_jmobile)) {
1263 $texthelp = $langs->trans("IfNeedToUseOtherObjectKeepEmpty");
1264 print $form->textwithtooltip($text.' '.img_help(), $texthelp, 1, 0, '', '', 2);
1265 } else {
1266 print $text;
1267 }
1268 print '</td></tr>';
1269 }
1270
1271 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) {
1272 $classfortr = ($object->usage_opportunity ? '' : ' hideobject');
1273 // Opportunity status
1274 print '<tr class="classuseopportunity'.$classfortr.'"><td>'.$langs->trans("OpportunityStatus").'</td>';
1275 print '<td>';
1276 print '<div>';
1277 print $formproject->selectOpportunityStatus('opp_status', (string) $object->opp_status, 1, 0, 0, 0, 'minwidth150 inline-block valignmiddle', 1, 1);
1278
1279 // Opportunity probability
1280 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) : '')).'"> %';
1281 print '<span id="oldopppercent" class="opacitymedium"></span>';
1282 print '</div>';
1283
1284 print '<div id="divtocloseproject" class="inline-block valign clearboth paddingtop" style="display: none;">';
1285 print '<input type="checkbox" id="inputcloseproject" name="closeproject" class="valignmiddle" />';
1286 print '<label for="inputcloseproject" class="opacitymedium valignmiddle">';
1287 print $form->textwithpicto($langs->trans("AlsoCloseAProject"), $langs->trans("AlsoCloseAProjectTooltip")).'</label>';
1288 print ' </div>';
1289
1290 print '</td>';
1291 print '</tr>';
1292
1293 // Opportunity amount
1294 print '<tr class="classuseopportunity'.$classfortr.'"><td>'.$langs->trans("OpportunityAmount").'</td>';
1295 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) : '')).'">';
1296 print $langs->getCurrencySymbol($conf->currency);
1297 print '</td>';
1298 print '</tr>';
1299 }
1300
1301 // Budget
1302 print '<tr><td>'.$langs->trans("Budget").'</td>';
1303 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) : '')).'">';
1304 print $langs->getCurrencySymbol($conf->currency);
1305 print '</td>';
1306 print '</tr>';
1307
1308 // Date project
1309 print '<tr><td>'.$langs->trans("Date").(isModEnabled('eventorganization') ? ' <span class="classuseorganizeevent">('.$langs->trans("Project").')</span>' : '').'</td><td>';
1310 print $form->selectDate($object->date_start ? $object->date_start : -1, 'projectstart', 0, 0, 0, '', 1, 0);
1311 print ' <span class="opacitymedium"> '.$langs->trans("to").' </span> ';
1312 print $form->selectDate($object->date_end ? $object->date_end : -1, 'projectend', 0, 0, 0, '', 1, 0);
1313 $object->getLinesArray(null, 0);
1314 if (!empty($object->usage_task) && !empty($object->lines)) {
1315 print ' <span id="divreportdate" class="hidden">&nbsp; &nbsp; <input type="checkbox" class="valignmiddle" id="reportdate" name="reportdate" value="yes" ';
1316 if ($comefromclone) {
1317 print 'checked ';
1318 }
1319 print '/><label for="reportdate" class="valignmiddle opacitymedium">'.$langs->trans("ProjectReportDate").'</label></span>';
1320 }
1321 print '</td></tr>';
1322
1323 if (isModEnabled('eventorganization')) {
1324 // Date event
1325 print '<tr class="classuseorganizeevent"><td>'.$langs->trans("Date").' ('.$langs->trans("Event").')</td><td>';
1326 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);
1327 print ' <span class="opacitymedium"> '.$langs->trans("to").' </span> ';
1328 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);
1329 print '</td></tr>';
1330
1331 // Location
1332 print '<tr class="classuseorganizeevent"><td>'.$langs->trans("Location").'</td>';
1333 print '<td><input class="minwidth300 maxwidth500" type="text" name="location" value="'.dol_escape_htmltag(GETPOSTISSET('location') ? GETPOST('location') : $object->location).'"></td>';
1334 print '</tr>';
1335 }
1336
1337 // Description
1338 print '<tr><td class="tdtop">'.$langs->trans("Description").'</td>';
1339 print '<td>';
1340 $doleditor = new DolEditor('description', $object->description, '', 90, 'dolibarr_notes', '', false, true, isModEnabled('fckeditor') && getDolGlobalInt('FCKEDITOR_ENABLE_SOCIETE'), ROWS_3, '90%');
1341 $doleditor->Create();
1342 print '</td></tr>';
1343
1344 // Tags-Categories
1345 if (isModEnabled('category')) {
1346 print '<tr><td>'.$langs->trans("Categories").'</td><td>';
1347 print $form->selectCategories(Categorie::TYPE_PROJECT, 'categories', $object);
1348 print "</td></tr>";
1349 }
1350
1351 // Visibility
1352 print '<tr><td>'.$langs->trans("Visibility").'</td><td>';
1353 $array = array();
1354 if (!getDolGlobalString('PROJECT_DISABLE_PRIVATE_PROJECT')) {
1355 $array[0] = $langs->trans("PrivateProject");
1356 }
1357 if (!getDolGlobalString('PROJECT_DISABLE_PUBLIC_PROJECT')) {
1358 $array[1] = $langs->trans("SharedProject");
1359 }
1360
1361 if (count($array) > 0) {
1362 print $form->selectarray('public', $array, $object->public, 0, 0, 0, '', 0, 0, 0, '', '', 1);
1363 } else {
1364 print '<input type="hidden" id="public" name="public" value="'.$object->public.'">';
1365
1366 if ($object->public == 0) {
1367 print img_picto($langs->trans('PrivateProject'), 'private', 'class="paddingrightonly"');
1368 print $langs->trans("PrivateProject");
1369 } else {
1370 print img_picto($langs->trans('SharedProject'), 'world', 'class="paddingrightonly"');
1371 print $langs->trans("SharedProject");
1372 }
1373 }
1374 print '</td></tr>';
1375
1376 // Other options
1377 $parameters = array();
1378 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1379 print $hookmanager->resPrint;
1380 if (empty($reshook)) {
1381 print $object->showOptionals($extrafields, 'edit');
1382 }
1383
1384 print '</table>';
1385 } else {
1386 print dol_get_fiche_head($head, 'project', $langs->trans("Project"), -1, ($object->public ? 'projectpub' : 'project'), 0, '', '', 0, '', 1);
1387
1388 // Project card
1389
1390 if (!empty($_SESSION['pageforbacktolist']) && !empty($_SESSION['pageforbacktolist']['project'])) {
1391 $tmpurl = $_SESSION['pageforbacktolist']['project'];
1392 $tmpurl = preg_replace('/__SOCID__/', (string) $object->socid, $tmpurl);
1393 $linkback = '<a href="'.$tmpurl.(preg_match('/\?/', $tmpurl) ? '&' : '?'). 'restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
1394 } else {
1395 $linkback = '<a href="'.DOL_URL_ROOT.'/projet/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
1396 }
1397
1398 $morehtmlref = '<div class="refidno">';
1399 // Title
1400 $morehtmlref .= dol_escape_htmltag($object->title);
1401 $morehtmlref .= '<br>';
1402 // Thirdparty
1403 if (!empty($object->thirdparty->id) && $object->thirdparty->id > 0) {
1404 $morehtmlref .= $object->thirdparty->getNomUrl(1, 'project');
1405 }
1406 // Parent
1407 if (getDolGlobalInt('PROJECT_ENABLE_SUB_PROJECT')) {
1408 if (!empty($object->fk_project) && $object->fk_project) {
1409 $parent = new Project($db);
1410 $parent->fetch($object->fk_project);
1411 $morehtmlref .= $langs->trans("Child of").' '.$parent->getNomUrl(1, 'project').' '.$parent->title;
1412 }
1413 }
1414 $morehtmlref .= '</div>';
1415
1416 // Define a complementary filter for search of next/prev ref.
1417 if (!$user->hasRight('projet', 'all', 'lire')) {
1418 $objectsListId = $object->getProjectsAuthorizedForUser($user, 0, 0);
1419 $object->next_prev_filter = "rowid:IN:".$db->sanitize(count($objectsListId) ? implode(',', array_keys($objectsListId)) : '0');
1420 }
1421
1422 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
1423
1424 print '<div class="fichecenter">';
1425 print '<div class="fichehalfleft">';
1426 print '<div class="underbanner clearboth"></div>';
1427
1428 print '<table class="border tableforfield centpercent">';
1429
1430 // Usage
1431 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES') || !getDolGlobalString('PROJECT_HIDE_TASKS') || isModEnabled('eventorganization')) {
1432 print '<tr><td class="tdtop">';
1433 print $langs->trans("Usage");
1434 print '</td>';
1435 print '<td>';
1436 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) {
1437 print '<input type="checkbox" disabled name="usage_opportunity"'.(GETPOSTISSET('usage_opportunity') ? (GETPOST('usage_opportunity', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_opportunity ? ' checked="checked"' : '')).'> ';
1438 $htmltext = $langs->trans("ProjectFollowOpportunity");
1439 print $form->textwithpicto($langs->trans("ProjectFollowOpportunity"), $htmltext);
1440 print '<br>';
1441 }
1442 if (!getDolGlobalString('PROJECT_HIDE_TASKS')) {
1443 print '<input type="checkbox" disabled name="usage_task"'.(GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_task ? ' checked="checked"' : '')).'> ';
1444 $htmltext = $langs->trans("ProjectFollowTasks");
1445 print $form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext);
1446 print '<br>';
1447 }
1448 if (!getDolGlobalString('PROJECT_HIDE_TASKS') && getDolGlobalString('PROJECT_BILL_TIME_SPENT')) {
1449 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"' : '')).'> ';
1450 $htmltext = $langs->trans("ProjectBillTimeDescription");
1451 print $form->textwithpicto($langs->trans("BillTime"), $htmltext);
1452 print '<br>';
1453 }
1454
1455 if (isModEnabled('eventorganization')) {
1456 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"' : '')).'> ';
1457 $htmltext = $langs->trans("EventOrganizationDescriptionLong");
1458 print $form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext);
1459 }
1460 print '</td></tr>';
1461 }
1462
1463 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES') && !empty($object->usage_opportunity)) {
1464 // Opportunity status
1465 print '<tr><td>'.$langs->trans("OpportunityStatus");
1466 if ($action != 'edit_opp_status' && $user->hasRight('projet', 'creer')) {
1467 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>';
1468 }
1469 print '</td><td>';
1470 $html_name_status = ($action == 'edit_opp_status') ? 'opp_status' : 'none';
1471 $html_name_percent = ($action == 'edit_opp_status') ? 'opp_percent' : 'none';
1472 $percent_value = (GETPOSTISSET('opp_percent') ? GETPOSTINT('opp_percent') : (strcmp($object->opp_percent, '') ? vatrate($object->opp_percent) : ''));
1473 $formproject->formOpportunityStatus($_SERVER['PHP_SELF'].'?socid='.$object->id, (string) $object->opp_status, $percent_value, $html_name_status, $html_name_percent);
1474 print '</td></tr>';
1475
1476 // Opportunity Amount
1477 print '<tr><td>'.$langs->trans("OpportunityAmount").'</td><td>';
1478 if (strcmp($object->opp_amount, '')) {
1479 print '<span class="amount">'.price($object->opp_amount, 0, $langs, 1, 0, -1, $conf->currency).'</span>';
1480 if (strcmp($object->opp_percent, '')) {
1481 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>';
1482 }
1483 }
1484 print '</td></tr>';
1485 }
1486
1487 // Budget
1488 print '<tr><td>'.$langs->trans("Budget").'</td><td>';
1489 if (!is_null($object->budget_amount) && strcmp($object->budget_amount, '')) {
1490 print '<span class="amount">'.price($object->budget_amount, 0, $langs, 1, 0, 0, $conf->currency).'</span>';
1491 }
1492 print '</td></tr>';
1493
1494 // Date start - end project
1495 print '<tr><td>'.$langs->trans("Dates").'</td><td>';
1496 $start = dol_print_date($object->date_start, 'day');
1497 print($start ? $start : '?');
1498 $end = dol_print_date($object->date_end, 'day');
1499 print ' <span class="opacitymedium">-</span> ';
1500 print($end ? $end : '?');
1501 if ($object->hasDelay()) {
1502 print img_warning("Late");
1503 }
1504 print '</td></tr>';
1505
1506 // Visibility
1507 print '<tr><td class="titlefield">'.$langs->trans("Visibility").'</td><td>';
1508 if ($object->public) {
1509 print img_picto($langs->trans('SharedProject'), 'world', 'class="paddingrightonly"');
1510 print $langs->trans('SharedProject');
1511 } else {
1512 print img_picto($langs->trans('PrivateProject'), 'private', 'class="paddingrightonly"');
1513 print $langs->trans('PrivateProject');
1514 }
1515 print '</td></tr>';
1516
1517 // Other attributes
1518 $cols = 2;
1519 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
1520
1521 print '</table>';
1522
1523 print '</div>';
1524 print '<div class="fichehalfright">';
1525 print '<div class="underbanner clearboth"></div>';
1526
1527 print '<table class="border tableforfield centpercent">';
1528
1529 // Categories
1530 if (isModEnabled('category')) {
1531 print '<tr><td class="valignmiddle">'.$langs->trans("Categories").'</td><td>';
1532 print $form->showCategories($object->id, Categorie::TYPE_PROJECT, 1);
1533 print "</td></tr>";
1534 }
1535
1536 // Description
1537 print '<tr><td class="titlefield'.($object->description ? ' noborderbottom' : '').'" colspan="2">'.$langs->trans("Description").'</td></tr>';
1538 if ($object->description) {
1539 print '<tr><td class="nottitleforfield" colspan="2">';
1540 print '<div class="longmessagecut">';
1541 print dolPrintHTML($object->description);
1542 print '</div>';
1543 print '</td></tr>';
1544 }
1545
1546 print '</table>';
1547
1548 print '</div>';
1549 print '</div>';
1550
1551 print '<div class="clearboth"></div>';
1552 }
1553
1554 print dol_get_fiche_end();
1555
1556 if ($action == 'edit' && $userWrite > 0) {
1557 print $form->buttonsSaveCancel();
1558 }
1559
1560 print '</form>';
1561
1562 // Set also dependencies between use task and bill time
1563 print '<script type="text/javascript">
1564 jQuery(document).ready(function() {
1565 jQuery("#usage_task").change(function() {
1566 console.log("We click on usage task "+jQuery("#usage_task").is(":checked"));
1567 if (! jQuery("#usage_task").is(":checked")) {
1568 jQuery("#usage_bill_time").prop("checked", false);
1569 }
1570 });
1571
1572 jQuery("#usage_bill_time").change(function() {
1573 console.log("We click on usage to bill time");
1574 if (jQuery("#usage_bill_time").is(":checked")) {
1575 jQuery("#usage_task").prop("checked", true);
1576 }
1577 });
1578
1579 jQuery("#projectstart").change(function() {
1580 console.log("We modify the start date");
1581 jQuery("#divreportdate").show();
1582 });
1583 });
1584 </script>';
1585
1586 // Change probability from status
1587 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) {
1588 // Default value to close or not when we set opp to 'WON'.
1589 $defaultcheckedwhenoppclose = 1;
1590 if (!getDolGlobalString('PROJECT_HIDE_TASKS')) {
1591 $defaultcheckedwhenoppclose = 0;
1592 }
1593
1594 print '<!-- Javascript to manage opportunity status change -->';
1595 print '<script type="text/javascript">
1596 jQuery(document).ready(function() {
1597 function change_percent()
1598 {
1599 var element = jQuery("#opp_status option:selected");
1600 var defaultpercent = element.attr("defaultpercent");
1601 var defaultcloseproject = '.((int) $defaultcheckedwhenoppclose).';
1602 var elemcode = element.attr("elemcode");
1603 var oldpercent = \''.dol_escape_js($object->opp_percent).'\';
1604
1605 console.log("We select "+elemcode);
1606
1607 /* Define if checkbox to close is checked or not */
1608 var closeproject = 0;
1609 if (elemcode == \'LOST\') closeproject = 1;
1610 if (elemcode == \'WON\') closeproject = defaultcloseproject;
1611 if (closeproject) jQuery("#inputcloseproject").prop("checked", true);
1612 else jQuery("#inputcloseproject").prop("checked", false);
1613
1614 /* Make the close project checkbox visible or not */
1615 console.log("closeproject="+closeproject);
1616 if (elemcode == \'WON\' || elemcode == \'LOST\')
1617 {
1618 jQuery("#divtocloseproject").show();
1619 }
1620 else
1621 {
1622 jQuery("#divtocloseproject").hide();
1623 }
1624
1625 /* Change percent with default percent (defaultpercent) if new status (defaultpercent) is higher than current (jQuery("#opp_percent").val()) */
1626 if (oldpercent != \'\' && (parseFloat(defaultpercent) < parseFloat(oldpercent)))
1627 {
1628 console.log("oldpercent="+oldpercent+" defaultpercent="+defaultpercent+" def < old");
1629 if (jQuery("#opp_percent").val() != \'\' && oldpercent != \'\') {
1630 jQuery("#oldopppercent").text(\' - '.dol_escape_js($langs->transnoentities("PreviousValue")).': \'+price2numjs(oldpercent)+\' %\');
1631 }
1632
1633 if (parseFloat(oldpercent) != 100 && elemcode != \'LOST\') { jQuery("#opp_percent").val(oldpercent); }
1634 else { jQuery("#opp_percent").val(price2numjs(defaultpercent)); }
1635 } else {
1636 console.log("oldpercent="+oldpercent+" defaultpercent="+defaultpercent);
1637 if (jQuery("#opp_percent").val() == \'\' || (parseFloat(jQuery("#opp_percent").val()) < parseFloat(defaultpercent))) {
1638 if (jQuery("#opp_percent").val() != \'\' && oldpercent != \'\') {
1639 jQuery("#oldopppercent").text(\' - '.dol_escape_js($langs->transnoentities("PreviousValue")).': \'+price2numjs(oldpercent)+\' %\');
1640 }
1641 jQuery("#opp_percent").val(price2numjs(defaultpercent));
1642 }
1643 }
1644 }
1645
1646 jQuery("#opp_status").change(function() {
1647 change_percent();
1648 });
1649 });
1650 </script>';
1651 }
1652
1653
1654 /*
1655 * Actions Buttons
1656 */
1657
1658 print '<div class="tabsAction">';
1659 $parameters = array();
1660 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been
1661 // modified by hook
1662 if (empty($reshook)) {
1663 if ($action != "edit" && $action != 'presend') {
1664 // Create event
1665 /*if (isModEnabled('agenda') && !empty($conf->global->MAIN_ADD_EVENT_ON_ELEMENT_CARD)) // Add hidden condition because this is not a
1666 // "workflow" action so should appears somewhere else on
1667 // page.
1668 {
1669 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>';
1670 }*/
1671
1672 // Send
1673 if (empty($user->socid)) {
1674 if ($object->status != Project::STATUS_CLOSED) {
1675 print dolGetButtonAction('', $langs->trans('SendMail'), 'email', $_SERVER["PHP_SELF"].'?action=presend&token='.newToken().'&id='.$object->id.'&mode=init#formmailbeforetitle', '');
1676 }
1677 }
1678
1679 // Accounting Report
1680 /*
1681 $accouting_module_activated = isModEnabled('comptabilite') || isModEnabled('accounting');
1682 if ($accouting_module_activated && $object->status != Project::STATUS_DRAFT) {
1683 $start = dol_getdate((int) $object->date_start);
1684 $end = dol_getdate((int) $object->date_end);
1685 $url = DOL_URL_ROOT.'/compta/accounting-files.php?projectid='.$object->id;
1686 if (!empty($object->date_start)) $url .= '&amp;date_startday='.$start['mday'].'&amp;date_startmonth='.$start['mon'].'&amp;date_startyear='.$start['year'];
1687 if (!empty($object->date_end)) $url .= '&amp;date_stopday='.$end['mday'].'&amp;date_stopmonth='.$end['mon'].'&amp;date_stopyear='.$end['year'];
1688 print dolGetButtonAction('', $langs->trans('ExportAccountingReportButtonLabel'), 'default', $url, '');
1689 }
1690 */
1691
1692 // Back to draft
1693 if (!getDolGlobalString('MAIN_DISABLEDRAFTSTATUS') && !getDolGlobalString('MAIN_DISABLEDRAFTSTATUS_PROJECT')) {
1694 if ($object->status != Project::STATUS_DRAFT && $user->hasRight('projet', 'creer')) {
1695 if ($userWrite > 0) {
1696 print dolGetButtonAction('', $langs->trans('SetToDraft'), 'default', $_SERVER["PHP_SELF"].'?action=confirm_setdraft&amp;confirm=yes&amp;token='.newToken().'&amp;id='.$object->id, '');
1697 } else {
1698 print dolGetButtonAction($langs->trans('NotOwnerOfProject'), $langs->trans('SetToDraft'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
1699 }
1700 }
1701 }
1702
1703 // Modify
1704 if ($object->status != Project::STATUS_CLOSED && $user->hasRight('projet', 'creer')) {
1705 if ($userWrite > 0) {
1706 print dolGetButtonAction('', $langs->trans('Modify'), 'default', $_SERVER["PHP_SELF"].'?action=edit&token='.newToken().'&id='.$object->id, '');
1707 } else {
1708 print dolGetButtonAction($langs->trans('NotOwnerOfProject'), $langs->trans('Modify'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
1709 }
1710 }
1711
1712 // Validate
1713 if ($object->status == Project::STATUS_DRAFT && $user->hasRight('projet', 'creer')) {
1714 if ($userWrite > 0) {
1715 //print dolGetButtonAction('', $langs->trans('Validate'), 'default', $_SERVER["PHP_SELF"].'?action=validate&token='.newToken().'&id='.$object->id, '');
1716 print dolGetButtonAction('', $langs->trans('Validate'), 'default', $_SERVER["PHP_SELF"].'?action=confirm_validate&confirm=yes&token='.newToken().'&id='.$object->id, '');
1717 } else {
1718 print dolGetButtonAction($langs->trans('NotOwnerOfProject'), $langs->trans('Validate'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
1719 }
1720 }
1721
1722 // Close
1723 if ($object->status == Project::STATUS_VALIDATED && $user->hasRight('projet', 'creer')) {
1724 if ($userWrite > 0) {
1725 //print dolGetButtonAction('', $langs->trans('Close'), 'default', $_SERVER["PHP_SELF"].'?action=close&amp;token='.newToken().'&amp;id='.$object->id, '');
1726 print dolGetButtonAction('', $langs->trans('Close'), 'default', $_SERVER["PHP_SELF"].'?action=confirm_close&confirm=yes&token='.newToken().'&id='.$object->id, '');
1727 } else {
1728 print dolGetButtonAction($langs->trans('NotOwnerOfProject'), $langs->trans('Close'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
1729 }
1730 }
1731
1732 // Reopen
1733 if ($object->status == Project::STATUS_CLOSED && $user->hasRight('projet', 'creer')) {
1734 if ($userWrite > 0) {
1735 print dolGetButtonAction('', $langs->trans('ReOpen'), 'default', $_SERVER["PHP_SELF"].'?action=reopen&amp;token='.newToken().'&amp;id='.$object->id, '');
1736 } else {
1737 print dolGetButtonAction($langs->trans('NotOwnerOfProject'), $langs->trans('ReOpen'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
1738 }
1739 }
1740
1741
1742 // Buttons Create
1743 if (!getDolGlobalString('PROJECT_HIDE_CREATE_OBJECT_BUTTON')) {
1744 // We check the type of thirdparty
1745 $is_customer_or_prospect = (!empty($object->thirdparty->prospect) || !empty($object->thirdparty->client));
1746 $is_supplier_only= (!empty($object->thirdparty->fournisseur) && !$is_customer_or_prospect);
1747
1748 $arrayforbutaction = array(
1749 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),
1750 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),
1751 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),
1752 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 : '')),
1753 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 : '')),
1754 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 : '')),
1755 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),
1756 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),
1757 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),
1758 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),
1759 );
1760
1761 $params = array('backtopage' => $_SERVER["PHP_SELF"].'?id='.$object->id);
1762 //$params = array('backtopage' => $_SERVER["PHP_SELF"].'?id='.$object->id, 'isDropDown' => true);
1763
1764 print dolGetButtonAction('', $langs->trans("Create"), 'default', $arrayforbutaction, '', 1, $params);
1765 }
1766
1767 // Clone
1768 if ($user->hasRight('projet', 'creer')) {
1769 if ($userWrite > 0) {
1770 print dolGetButtonAction('', $langs->trans('ToClone'), 'default', $_SERVER["PHP_SELF"].'?action=clone&token='.newToken().'&id='.((int) $object->id), '');
1771 } else {
1772 print dolGetButtonAction($langs->trans('NotOwnerOfProject'), $langs->trans('ToClone'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
1773 }
1774 }
1775
1776 // Delete
1777 if ($user->hasRight('projet', 'supprimer') || ($object->status == Project::STATUS_DRAFT && $user->hasRight('projet', 'creer'))) {
1778 if ($userDelete > 0 || ($object->status == Project::STATUS_DRAFT && $user->hasRight('projet', 'creer'))) {
1779 print dolGetButtonAction('', $langs->trans('Delete'), 'delete', $_SERVER["PHP_SELF"].'?action=delete&token='.newToken().'&id='.$object->id, '');
1780 } else {
1781 print dolGetButtonAction($langs->trans('NotOwnerOfProject'), $langs->trans('Delete'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
1782 }
1783 }
1784 }
1785 }
1786
1787 print "</div>";
1788
1789 if (GETPOST('modelselected')) {
1790 $action = 'presend';
1791 }
1792
1793 if ($action != 'presend') {
1794 print '<div class="fichecenter"><div class="fichehalfleft">';
1795 print '<a name="builddoc"></a>'; // ancre
1796
1797 if (getDolGlobalInt('PROJECT_ENABLE_SUB_PROJECT')) {
1798 /*
1799 * Sub-projects (children)
1800 */
1801 $children = $object->getChildren();
1802 if ($children) {
1803 print '<table class="centpercent notopnoleftnoright table-fiche-title">';
1804 print '<tr class="titre"><td class="nobordernopadding valignmiddle col-title">';
1805 print '<div class="titre inline-block">'.$langs->trans('Sub-projects').'</div>';
1806 print '</td></tr></table>';
1807
1808 print '<div class="div-table-responsive-no-min">';
1809 print '<table class="centpercent noborder'.($morecss ? ' '.$morecss : '').'">';
1810 print '<tr class="liste_titre">';
1811 print getTitleFieldOfList('Ref', 0, $_SERVER["PHP_SELF"], '', '', '', '', '', '', '', 1);
1812 print getTitleFieldOfList('Title', 0, $_SERVER["PHP_SELF"], '', '', '', '', '', '', '', 1);
1813 print getTitleFieldOfList('Status', 0, $_SERVER["PHP_SELF"], '', '', '', '', '', '', '', 1);
1814 print '</tr>';
1815 print "\n";
1816
1817 $subproject = new Project($db);
1818 foreach ($children as $child) {
1819 $subproject->fetch($child->rowid);
1820 print '<tr class="oddeven">';
1821 print '<td class="nowraponall">'.$subproject->getNomUrl(1, 'project').'</td>';
1822 print '<td class="nowraponall tdoverflowmax125">'.$child->title.'</td>';
1823 print '<td class="nowraponall">'.$subproject->getLibStatut(5).'</td>';
1824 print '</tr>';
1825 }
1826
1827 print '</table>';
1828 print '</div>';
1829 }
1830 }
1831
1832 /*
1833 * Generated documents
1834 */
1835 $filename = dol_sanitizeFileName($object->ref);
1836 $filedir = $conf->project->multidir_output[$object->entity ?? $conf->entity]."/".dol_sanitizeFileName($object->ref);
1837 $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
1838 $genallowed = ($user->hasRight('projet', 'lire') && $userAccess > 0);
1839 $delallowed = ($user->hasRight('projet', 'creer') && $userWrite > 0);
1840
1841 print $formfile->showdocuments('project', $filename, $filedir, $urlsource, (int) $genallowed, (int) $delallowed, $object->model_pdf, 1, 0, 0, 0, 0, '', '', '', '', '', $object);
1842
1843 print '</div><div class="fichehalfright">';
1844
1845 $MAXEVENT = 10;
1846
1847 $morehtmlcenter = '<div class="nowraponall">';
1848 $morehtmlcenter .= dolGetButtonTitle($langs->trans('FullConversation'), '', 'fa fa-comments imgforviewmode', DOL_URL_ROOT.'/projet/messaging.php?id='.$object->id);
1849 $morehtmlcenter .= dolGetButtonTitle($langs->trans('FullList'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT.'/projet/agenda.php?id='.$object->id);
1850 $morehtmlcenter .= '</div>';
1851
1852 // List of actions on element
1853 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
1854 $formactions = new FormActions($db);
1855 $somethingshown = $formactions->showactions($object, 'project', 0, 1, '', $MAXEVENT, '', $morehtmlcenter);
1856
1857 print '</div></div>';
1858 }
1859
1860 // Presend form
1861 $modelmail = 'project';
1862 $defaulttopic = 'SendProjectRef';
1863 $defaulttopiclang = 'projects';
1864 $diroutput = $conf->project->multidir_output[$object->entity ?? $conf->entity];
1865 $autocopy = 'MAIN_MAIL_AUTOCOPY_PROJECT_TO'; // used to know the automatic BCC to add
1866 $trackid = 'proj'.$object->id;
1867
1868 include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
1869
1870 // Hook to add more things on page
1871 $parameters = array();
1872 $reshook = $hookmanager->executeHooks('mainCardTabAddMore', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1873} else {
1874 recordNotFound('', 0);
1875}
1876
1877// End of page
1878llxFooter();
1879$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.