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