dolibarr 25.0.0-alpha
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 $object->oldcopy = dol_clone($object, 2); // @phan-suppress-current-line PhanTypeMismatchProperty
143 $result = $object->delete($user);
144 if ($result > 0) {
145 header("Location: index.php");
146 exit;
147 } else {
148 dol_syslog($object->error, LOG_DEBUG);
149 setEventMessages($langs->trans("CantRemoveProject", $langs->transnoentitiesnoconv("ProjectOverview")), null, 'errors');
150 }
151 }
152 }
153
154 if (empty($backtopage) || ($cancel && empty($id))) {
155 if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) {
156 if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) {
157 $backtopage = $backurlforlist;
158 } else {
159 $backtopage = DOL_URL_ROOT.'/projet/card.php?id='.((!empty($id) && $id > 0) ? $id : '__ID__');
160 }
161 }
162 }
163
164 if ($cancel) {
165 if (!empty($backtopageforcancel)) {
166 header("Location: ".$backtopageforcancel);
167 exit;
168 } elseif (!empty($backtopage)) {
169 header("Location: ".$backtopage);
170 exit;
171 }
172 $action = '';
173 }
174
175 include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; // Must be 'include', not 'include_once'
176
177 // Action setdraft object
178 if ($action == 'confirm_setdraft' && $confirm == 'yes' && $permissiontoadd) {
179 $result = $object->setStatut($object::STATUS_DRAFT, null, '', 'PROJECT_MODIFY');
180 if ($result >= 0) {
181 // Nothing else done
182 } else {
183 $error++;
184 setEventMessages($object->error, $object->errors, 'errors');
185 }
186 $action = '';
187
188 // For backward compatibility
189 $object->statut = $object::STATUS_DRAFT; // this is already set for $object->status by $object->setStatut()
190 }
191
192 // Action add
193 if ($action == 'add' && $permissiontoadd) {
194 $error = 0;
195 if (!GETPOST('ref')) {
196 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Ref")), null, 'errors');
197 $error++;
198 }
199 if (!GETPOST('title')) {
200 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("ProjectLabel")), null, 'errors');
201 $error++;
202 }
203
204 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) {
205 if (GETPOST('usage_opportunity') != '' && !(GETPOST('opp_status') > 0)) {
206 $error++;
207 setEventMessages($langs->trans("ErrorOppStatusRequiredIfUsage"), null, 'errors');
208 }
209 if (GETPOST('opp_amount') != '' && !(GETPOST('opp_status') > 0)) {
210 $error++;
211 setEventMessages($langs->trans("ErrorOppStatusRequiredIfAmount"), null, 'errors');
212 }
213 }
214
215 // Create with status validated immediately
216 if (getDolGlobalString('PROJECT_CREATE_NO_DRAFT') && !$error) {
218 }
219
220 if (!$error) {
221 $error = 0;
222
223 $db->begin();
224
225 $object->ref = GETPOST('ref', 'alphanohtml');
226 $object->fk_project = GETPOSTINT('fk_project');
227 $object->title = GETPOST('title', 'alphanohtml');
228 $object->socid = GETPOSTINT('socid');
229 $object->description = GETPOST('description', 'restricthtml'); // Do not use 'alpha' here, we want field as it is
230 $object->public = GETPOSTINT('public') ? 1 : 0;
231 $object->opp_amount = GETPOSTFLOAT('opp_amount');
232 $object->budget_amount = GETPOSTFLOAT('budget_amount');
233 $object->date_c = dol_now();
234 $object->date_start = $date_start;
235 $object->date_end = $date_end;
236 $object->date_start_event = $date_start_event;
237 $object->date_end_event = $date_end_event;
238 $object->location = $location;
239 $object->status = $status;
240 $object->opp_status = $opp_status;
241 $object->opp_percent = $opp_percent;
242 $object->usage_opportunity = (GETPOST('usage_opportunity', 'alpha') == 'on' ? 1 : 0);
243 $object->usage_task = (GETPOST('usage_task', 'alpha') == 'on' ? 1 : 0);
244 $object->usage_bill_time = (GETPOST('usage_bill_time', 'alpha') == 'on' ? 1 : 0);
245 $object->usage_organize_event = (GETPOST('usage_organize_event', 'alpha') == 'on' ? 1 : 0);
246
247 // Fill array 'array_options' with data from add form
248 $ret = $extrafields->setOptionalsFromPost(null, $object);
249 if ($ret < 0) {
250 $error++;
251 }
252
253 if (!$error) {
254 $result = $object->create($user);
255 if ($result > 0) {
256 // Add myself as Owner Contact Selected in the form
257 $typeofcontact = GETPOST('typeofcontact');
258 $result = $object->add_contact($user->id, $typeofcontact, 'internal');
259
260 // -3 means type not found (renamed, de-activated or deleted), so don't prevent creation if it has been the case
261 if ($result == -3) {
262 setEventMessage('ErrorPROJECTLEADERRoleMissingRestoreIt', 'errors');
263 $error++;
264 } elseif ($result < 0) {
265 $langs->load("errors");
266 setEventMessages($object->error, $object->errors, 'errors');
267 $error++;
268 }
269 } else {
270 $langs->load("errors");
271 setEventMessages($object->error, $object->errors, 'errors');
272 $error++;
273 }
274 }
275 if (!$error && !empty($object->id) > 0) {
276 // Category association
277 $categories = GETPOST('categories', 'array:int');
278 $result = $object->setCategories($categories);
279 if ($result < 0) {
280 $langs->load("errors");
281 setEventMessages($object->error, $object->errors, 'errors');
282 $error++;
283 }
284 }
285
286 if (!$error) {
287 $db->commit();
288
289 if (!empty($backtopage)) {
290 $backtopage = preg_replace('/--IDFORBACKTOPAGE--|__ID__/', (string) $object->id, $backtopage); // New method to autoselect project after a New on another form object creation
291 $backtopage = $backtopage.'&projectid='.$object->id; // Old method
292 header("Location: ".$backtopage);
293 exit;
294 } else {
295 header("Location:card.php?id=".$object->id);
296 exit;
297 }
298 } else {
299 $db->rollback();
300 unset($_POST["ref"]);
301 $action = 'create';
302 }
303 } else {
304 $action = 'create';
305 }
306 }
307
308 if ($action == 'update' && empty(GETPOST('cancel')) && $permissiontoadd) {
309 if (empty($ref)) {
310 $error++;
311 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Ref")), null, 'errors');
312 }
313 if (!GETPOST("title")) {
314 $error++;
315 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("ProjectLabel")), null, 'errors');
316 }
317
318 $db->begin();
319 $old_start_date = 0;
320 if (!$error) {
321 $object->oldcopy = clone $object; // @phan-suppress-current-line PhanTypeMismatchProperty
322
323 $old_start_date = $object->date_start;
324
325 $object->ref = GETPOST('ref', 'alpha');
326 $object->fk_project = GETPOSTINT('fk_project');
327 $object->title = GETPOST('title', 'alphanohtml'); // Do not use 'alpha' here, we want field as it is
328 $object->status = GETPOSTINT('status');
329 $object->socid = GETPOSTINT('socid');
330 $object->description = GETPOST('description', 'restricthtml'); // Do not use 'alpha' here, we want field as it is
331 $object->public = GETPOSTINT('public') ? 1 : 0;
332 $object->date_start = (!GETPOST('projectstart')) ? '' : $date_start;
333 $object->date_end = (!GETPOST('projectend')) ? '' : $date_end;
334 $object->date_start_event = (!GETPOST('date_start_event')) ? '' : $date_start_event;
335 $object->date_end_event = (!GETPOST('date_end_event')) ? '' : $date_end_event;
336 $object->location = $location;
337 if (GETPOSTISSET('opp_amount')) {
338 $object->opp_amount = price2num(GETPOST('opp_amount', 'alpha'));
339 }
340 if (GETPOSTISSET('budget_amount')) {
341 $object->budget_amount = price2num(GETPOST('budget_amount', 'alpha'));
342 }
343 if (GETPOSTISSET('opp_status')) {
344 $object->opp_status = $opp_status;
345 }
346 if (GETPOSTISSET('opp_percent')) {
347 $object->opp_percent = $opp_percent;
348 }
349 $object->usage_opportunity = (GETPOST('usage_opportunity', 'alpha') == 'on' ? 1 : 0);
350 $object->usage_task = (GETPOST('usage_task', 'alpha') == 'on' ? 1 : 0);
351 $object->usage_bill_time = (GETPOST('usage_bill_time', 'alpha') == 'on' ? 1 : 0);
352 $object->usage_organize_event = (GETPOST('usage_organize_event', 'alpha') == 'on' ? 1 : 0);
353
354 // Fill array 'array_options' with data from add form
355 $ret = $extrafields->setOptionalsFromPost(null, $object, '@GETPOSTISSET');
356 if ($ret < 0) {
357 $error++;
358 }
359 }
360
361 // If opportunities are used and the customer is not yet a customer
362 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES') && $object->usage_opportunity) {
363 if ($object->opp_amount && ($object->opp_status <= 0)) {
364 $error++;
365 setEventMessages($langs->trans("ErrorOppStatusRequiredIfAmount"), null, 'errors');
366 }
367
368 if (!$error && !is_null($object->thirdparty) && ((int) $object->thirdparty->client == 0 || (int) $object->thirdparty->client == 2)) { // If not yet customer
369 // Get ID of the special opportunity status code 'WON'
370 $idoppstatuswon = (int) dol_getIdFromCode($db, 'WON', 'c_lead_status', 'code', 'rowid');
371
372 if ($object->opp_status == $idoppstatuswon) {
373 // Switch the thirdparty into a customer (only if thirdparty exists)
374 if (!empty($object->thirdparty) && !empty($object->thirdparty->id)) {
375 $object->thirdparty->setAsCustomer();
376 }
377 }
378 }
379 }
380
381 if (!$error) {
382 $result = $object->update($user);
383 if ($result < 0) {
384 $error++;
385 if ($result == -4) {
386 setEventMessages($langs->trans("ErrorRefAlreadyExists"), null, 'errors');
387 } else {
388 setEventMessages($object->error, $object->errors, 'errors');
389 }
390 } else {
391 // Category association
392 $categories = GETPOST('categories', 'array:int');
393 $result = $object->setCategories($categories);
394 if ($result < 0) {
395 $error++;
396 setEventMessages($object->error, $object->errors, 'errors');
397 }
398 }
399 }
400
401 if (!$error) {
402 if (GETPOST("reportdate") && ($object->date_start != $old_start_date)) {
403 $result = $object->shiftTaskDate((int) $old_start_date);
404 if ($result < 0) {
405 $error++;
406 setEventMessages($langs->trans("ErrorShiftTaskDate").':'.$object->error, $object->errors, 'errors');
407 }
408 }
409 }
410
411 // Check if we must change status of project
412 if (GETPOST('closeproject')) {
413 $resclose = $object->setClose($user);
414 if ($resclose < 0) {
415 $error++;
416 setEventMessages($langs->trans("FailedToCloseProject").':'.$object->error, $object->errors, 'errors');
417 }
418 }
419
420
421 if ($error) {
422 $db->rollback();
423 $action = 'edit';
424 } else {
425 $db->commit();
426
427 if (GETPOSTINT('socid') > 0) {
428 $object->fetch_thirdparty(GETPOSTINT('socid'));
429 } else {
430 unset($object->thirdparty);
431 }
432 }
433 }
434
435 // Set opportunity status
436 if ($action == 'set_opp_status' && $user->hasRight('projet', 'creer')) {
437 if (GETPOSTISSET('opp_status')) {
438 $object->opp_status = $opp_status;
439 }
440 if (GETPOSTISSET('opp_percent')) {
441 $object->opp_percent = $opp_percent;
442 }
443
444 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) {
445 if ($object->opp_amount && ($object->opp_status <= 0)) {
446 $error++;
447 setEventMessages($langs->trans("ErrorOppStatusRequiredIfAmount"), null, 'errors');
448 }
449 }
450
451 if (!$error) {
452 $db->begin();
453
454 $result = $object->update($user);
455 if ($result < 0) {
456 $error++;
457 if ($result == -4) {
458 setEventMessages($langs->trans("ErrorRefAlreadyExists"), null, 'errors');
459 } else {
460 setEventMessages($object->error, $object->errors, 'errors');
461 }
462 }
463
464 // If opportunities are used and the customer is not yet a customer
465 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES') && $object->usage_opportunity && !is_null($object->thirdparty)) {
466 if ((int) $object->thirdparty->client == 0 || (int) $object->thirdparty->client == 2) { // If not yet customer
467 // Get ID of the special opportunity status code 'WON'
468 $idoppstatuswon = (int) dol_getIdFromCode($db, 'WON', 'c_lead_status', 'code', 'rowid');
469
470 if (!$error && $object->opp_status == $idoppstatuswon) {
471 // Switch the thirdparty into a customer (only if thirdparty exists)
472 if (!empty($object->thirdparty) && !empty($object->thirdparty->id)) {
473 $object->thirdparty->setAsCustomer();
474 }
475 }
476 }
477 }
478
479 if ($error) {
480 $db->rollback();
481 $action = 'edit';
482 } else {
483 $db->commit();
484 }
485 } else {
486 $action = 'edit';
487 }
488 }
489
490 // Build doc
491 if ($action == 'builddoc' && $permissiontoadd) {
492 // Save last template used to generate document
493 if (GETPOST('model')) {
494 $object->setDocModel($user, GETPOST('model', 'alpha'));
495 }
496
497 $outputlangs = $langs;
498 if (GETPOST('lang_id', 'aZ09')) {
499 $outputlangs = new Translate("", $conf);
500 $outputlangs->setDefaultLang(GETPOST('lang_id', 'aZ09'));
501 }
502 $result = $object->generateDocument($object->model_pdf, $outputlangs);
503 if ($result <= 0) {
504 setEventMessages($object->error, $object->errors, 'errors');
505 $action = '';
506 } else {
507 setEventMessages($langs->trans("FileGenerated"), null, 'mesgs');
508 }
509 }
510
511 // Delete file in doc form
512 if ($action == 'remove_file' && $permissiontoadd) {
513 if ($object->id > 0) {
514 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
515
516 $langs->load("other");
517 $upload_dir = $conf->project->multidir_output[$object->entity ?? $conf->entity];
518 $file = $upload_dir.'/'.GETPOST('file');
519 $ret = dol_delete_file($file, 1, 0, 0, $object);
520 if ($ret) {
521 setEventMessages($langs->trans("FileWasRemoved", GETPOST('file')), null, 'mesgs');
522 } else {
523 setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('file')), null, 'errors');
524 }
525 $action = '';
526 }
527 }
528
529
530 if ($action == 'confirm_validate' && $confirm == 'yes' && $permissiontoadd) {
531 $result = $object->setValid($user);
532 if ($result <= 0) {
533 setEventMessages($object->error, $object->errors, 'errors');
534 }
535 }
536
537 if ($action == 'confirm_close' && $confirm == 'yes' && $permissiontoadd) {
538 $result = $object->setClose($user);
539 if ($result <= 0) {
540 setEventMessages($object->error, $object->errors, 'errors');
541 }
542 }
543
544 if ($action == 'confirm_reopen' && $confirm == 'yes' && $permissiontoadd) {
545 $result = $object->setValid($user);
546 if ($result <= 0) {
547 setEventMessages($object->error, $object->errors, 'errors');
548 }
549 }
550
551 if ($action == 'confirm_delete' && $confirm == 'yes' && $permissiontodelete) {
552 $object->fetch($id);
553 $object->oldcopy = dol_clone($object, 2); // @phan-suppress-current-line PhanTypeMismatchProperty
554 $result = $object->delete($user);
555 if ($result > 0) {
556 setEventMessages($langs->trans("RecordDeleted"), null, 'mesgs');
557
558 if (!empty($_SESSION['pageforbacktolist']) && !empty($_SESSION['pageforbacktolist']['project'])) {
559 $tmpurl = $_SESSION['pageforbacktolist']['project'];
560 $tmpurl = preg_replace('/__SOCID__/', (string) $object->socid, $tmpurl);
561 $urlback = $tmpurl.(preg_match('/\?/', $tmpurl) ? '&' : '?'). 'restore_lastsearch_values=1';
562 } else {
563 $urlback = DOL_URL_ROOT.'/projet/list.php?restore_lastsearch_values=1';
564 }
565
566 header("Location: ".$urlback);
567 exit;
568 } else {
569 dol_syslog($object->error, LOG_DEBUG);
570 setEventMessages($object->error, $object->errors, 'errors');
571 }
572 }
573
574 if ($action == 'confirm_clone' && $permissiontoadd && $confirm == 'yes') {
575 $clone_contacts = GETPOST('clone_contacts') ? 1 : 0;
576 $clone_tasks = GETPOST('clone_tasks') ? 1 : 0;
577 $clone_project_files = GETPOST('clone_project_files') ? 1 : 0;
578 $clone_task_files = GETPOST('clone_task_files') ? 1 : 0;
579 $clone_notes = GETPOST('clone_notes') ? 1 : 0;
580 $move_date = GETPOST('move_date') ? 1 : 0;
581 $clone_thirdparty = GETPOSTINT('socid') ? GETPOSTINT('socid') : 0;
582
583 $result = $object->createFromClone($user, $object->id, $clone_contacts, $clone_tasks, $clone_project_files, $clone_task_files, $clone_notes, $move_date, 0, $clone_thirdparty);
584 if ($result <= 0) {
585 setEventMessages($object->error, $object->errors, 'errors');
586 } else {
587 // Load new object
588 $newobject = new Project($db);
589 $newobject->fetch($result);
590
591 setEventMessages($langs->trans("ProjectCreatedInDolibarr", $newobject->ref), null, 'mesgs');
592
593 header('Location: '.$_SERVER['PHP_SELF'].'?id='.$result.'&action=edit&comefromclone=1');
594 exit;
595 }
596 }
597
598 // Quick edit for extrafields
599 if ($action == 'update_extras' && $permissiontoeditextra) {
600 $object->oldcopy = dol_clone($object, 2); // @phan-suppress-current-line PhanTypeMismatchProperty
601
602 $attribute_name = GETPOST('attribute', 'aZ09');
603
604 // Fill array 'array_options' with data from update form
605 $ret = $extrafields->setOptionalsFromPost(null, $object, $attribute_name);
606 if ($ret < 0) {
607 $error++;
608 }
609
610 if (!$error) {
611 $result = $object->updateExtraField($attribute_name, 'PROJECT_MODIFY');
612 if ($result < 0) {
613 setEventMessages($object->error, $object->errors, 'errors');
614 $error++;
615 }
616 }
617
618 if ($error) {
619 $action = 'edit_extras';
620 }
621 }
622
623 // Actions when printing a doc from card
624 include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
625
626 // Actions to send emails
627 $triggersendname = 'PROJECT_SENTBYMAIL';
628 $paramname = 'id';
629 $autocopy = 'MAIN_MAIL_AUTOCOPY_PROJECT_TO'; // used to know the automatic BCC to add
630 $trackid = 'proj'.$object->id;
631 include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
632}
633
634
635/*
636 * View
637 */
638
639$form = new Form($db);
640$formfile = new FormFile($db);
641$formproject = new FormProjets($db);
642$userstatic = new User($db);
643
644$title = $langs->trans("Project").' - '.$object->ref.(!empty($object->thirdparty->name) ? ' - '.$object->thirdparty->name : '').(!empty($object->title) ? ' - '.$object->title : '');
645if (getDolGlobalString('MAIN_HTML_TITLE') && preg_match('/projectnameonly/', getDolGlobalString('MAIN_HTML_TITLE'))) {
646 $title = $object->ref.(!empty($object->thirdparty->name) ? ' - '.$object->thirdparty->name : '').(!empty($object->title) ? ' - '.$object->title : '');
647}
648
649$help_url = "EN:Module_Projects|FR:Module_Projets|ES:M&oacute;dulo_Proyectos|DE:Modul_Projekte";
650
651llxHeader("", $title, $help_url, '', 0, 0, '', '', '', 'mod-project page-card');
652
653$titleboth = $langs->trans("LeadsOrProjects");
654$titlenew = $langs->trans("NewLeadOrProject"); // Leads and opportunities by default
655if (!getDolGlobalInt('PROJECT_USE_OPPORTUNITIES')) {
656 $titleboth = $langs->trans("Projects");
657 $titlenew = $langs->trans("NewProject");
658}
659if (getDolGlobalInt('PROJECT_USE_OPPORTUNITIES') == 2) { // 2 = leads only
660 $titleboth = $langs->trans("Leads");
661 $titlenew = $langs->trans("NewLead");
662}
663
664if ($action == 'create' && $user->hasRight('projet', 'creer')) {
665 /*
666 * Create
667 */
668
669 $thirdparty = new Societe($db);
670 if ($socid > 0) {
671 $thirdparty->fetch($socid);
672 }
673
674 print load_fiche_titre($titlenew, '', 'project');
675
676 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
677 print '<input type="hidden" name="action" value="add">';
678 print '<input type="hidden" name="token" value="'.newToken().'">';
679 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
680 print '<input type="hidden" name="backtopageforcancel" value="'.$backtopageforcancel.'">';
681 print '<input type="hidden" name="dol_openinpopup" value="'.$dol_openinpopup.'">';
682
683 print dol_get_fiche_head();
684
685 print '<table class="border centpercent tableforfieldcreate">';
686
687 $defaultref = '';
688 $modele = getDolGlobalString('PROJECT_ADDON', 'mod_project_simple');
689
690 // Search template files
691 $file = '';
692 $classname = '';
693 $reldir = '';
694 $filefound = 0;
695 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
696 foreach ($dirmodels as $reldir) {
697 $file = dol_buildpath($reldir."core/modules/project/".$modele.'.php', 0);
698 if (file_exists($file)) {
699 $filefound = 1;
700 $classname = $modele;
701 break;
702 }
703 }
704
705 if ($filefound && !empty($classname)) {
706 $result = dol_include_once($reldir."core/modules/project/".$modele.'.php');
707 if (class_exists($classname)) {
708 $modProject = new $classname();
709 '@phan-var-force ModeleNumRefProjects $modProject';
710 $defaultref = $modProject->getNextValue($thirdparty, $object);
711 }
712 }
713
714 if (is_numeric($defaultref) && $defaultref <= 0) {
715 $defaultref = '';
716 }
717
718 // Ref
719 $suggestedref = (GETPOST("ref") ? GETPOST("ref") : $defaultref);
720 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).'">';
721 if ($suggestedref) {
722 print ' '.$form->textwithpicto('', $langs->trans("YouCanCompleteRef", $suggestedref));
723 }
724 print '</td></tr>';
725
726 // Label
727 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>';
728
729 // Parent
730 if (getDolGlobalInt('PROJECT_ENABLE_SUB_PROJECT')) {
731 print '<tr><td>'.$langs->trans("Parent").'</td><td class="maxwidthonsmartphone">';
732 print img_picto('', 'project', 'class="pictofixedwidth"');
733 $formproject->select_projects(-1, '', 'fk_project', 64, 0, 1, 1, 0, 0, 0, '', 0, 0, '', '', '');
734 print '</td></tr>';
735 }
736
737 // Usage (opp, task, bill time, ...)
738 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES') || !getDolGlobalString('PROJECT_HIDE_TASKS') || isModEnabled('eventorganization')) {
739 print '<tr><td class="tdtop">';
740 print $langs->trans("Usage");
741 print '</td>';
742 print '<td>';
743 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) {
744 print '<input type="checkbox" id="usage_opportunity" name="usage_opportunity"'.(GETPOSTISSET('usage_opportunity') ? (GETPOST('usage_opportunity', 'alpha') ? ' checked="checked"' : '') : ' checked="checked"').'> ';
745 $htmltext = $langs->trans("ProjectFollowOpportunity");
746 print '<label for="usage_opportunity">'.$form->textwithpicto($langs->trans("ProjectFollowOpportunity"), $htmltext).'</label>';
747 print '<script>';
748 print '$( document ).ready(function() {
749 jQuery("#usage_opportunity").change(function() {
750 if (jQuery("#usage_opportunity").prop("checked")) {
751 console.log("Show opportunities fields");
752 jQuery(".classuseopportunity").show();
753 } else {
754 console.log("Hide opportunities fields "+jQuery("#usage_opportunity").prop("checked"));
755 jQuery(".classuseopportunity").hide();
756 }
757 });
758 ';
759 if (GETPOSTISSET('usage_opportunity') && !GETPOST('usage_opportunity')) {
760 print 'jQuery(".classuseopportunity").hide();';
761 }
762 print '});';
763 print '</script>';
764 print '<br>';
765 }
766 if (!getDolGlobalString('PROJECT_HIDE_TASKS')) {
767 print '<input type="checkbox" id="usage_task" name="usage_task"'.(GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') ? ' checked="checked"' : '') : ' checked="checked"').'> ';
768 $htmltext = $langs->trans("ProjectFollowTasks");
769 print '<label for="usage_task">'.$form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext).'</label>';
770 print '<script>';
771 print '$( document ).ready(function() {
772 jQuery("#usage_task").change(function() {
773 if (jQuery("#usage_task").prop("checked")) {
774 console.log("Show task fields");
775 jQuery(".classusetask").show();
776 } else {
777 console.log("Hide tasks fields "+jQuery("#usage_task").prop("checked"));
778 jQuery(".classusetask").hide();
779 }
780 });
781 ';
782 if (GETPOSTISSET('usage_task') && !GETPOST('usage_task')) {
783 print 'jQuery(".classusetask").hide();';
784 }
785 print '});';
786 print '</script>';
787 print '<br>';
788 }
789 if (!getDolGlobalString('PROJECT_HIDE_TASKS') && getDolGlobalString('PROJECT_BILL_TIME_SPENT')) {
790 print '<input type="checkbox" id="usage_bill_time" name="usage_bill_time"'.(GETPOSTISSET('usage_bill_time') ? (GETPOST('usage_bill_time', 'alpha') ? ' checked="checked"' : '') : '').'> ';
791 $htmltext = $langs->trans("ProjectBillTimeDescription");
792 print '<label for="usage_bill_time">'.$form->textwithpicto($langs->trans("BillTime"), $htmltext).'</label>';
793 print '<script>';
794 print '$( document ).ready(function() {
795 jQuery("#usage_bill_time").change(function() {
796 if (jQuery("#usage_bill_time").prop("checked")) {
797 console.log("Show bill time fields");
798 jQuery(".classusebilltime").show();
799 } else {
800 console.log("Hide bill time fields "+jQuery("#usage_bill_time").prop("checked"));
801 jQuery(".classusebilltime").hide();
802 }
803 });
804 ';
805 if (GETPOSTISSET('usage_bill_time') && !GETPOST('usage_bill_time')) {
806 print 'jQuery(".classusebilltime").hide();';
807 }
808 print '});';
809 print '</script>';
810 print '<br>';
811 }
812 if (isModEnabled('eventorganization')) {
813 print '<input type="checkbox" id="usage_organize_event" name="usage_organize_event"'.(GETPOSTISSET('usage_organize_event') ? (GETPOST('usage_organize_event', 'alpha') ? ' checked="checked"' : '') : '').'"> ';
814 $htmltext = $langs->trans("EventOrganizationDescriptionLong");
815 print '<label for="usage_organize_event">'.$form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext).'</label>';
816 print '<script>';
817 print '$( document ).ready(function() {
818 jQuery("#usage_organize_event").change(function() {
819 if (jQuery("#usage_organize_event").prop("checked")) {
820 console.log("Show organize event fields");
821 jQuery(".classuseorganizeevent").show();
822 } else {
823 console.log("Hide organize event fields "+jQuery("#usage_organize_event").prop("checked"));
824 jQuery(".classuseorganizeevent").hide();
825 }
826 });
827 ';
828 if (!GETPOST('usage_organize_event')) {
829 print 'jQuery(".classuseorganizeevent").hide();';
830 }
831 print '});';
832 print '</script>';
833 }
834 print '</td>';
835 print '</tr>';
836 }
837
838 // Thirdparty
839 if (isModEnabled('societe')) {
840 print '<tr><td>';
841 print(!getDolGlobalString('PROJECT_THIRDPARTY_REQUIRED') ? '' : '<span class="fieldrequired">');
842 print $langs->trans("ThirdParty");
843 print(!getDolGlobalString('PROJECT_THIRDPARTY_REQUIRED') ? '' : '</span>');
844 print '</td><td class="maxwidthonsmartphone">';
845 $filter = '';
846 if (getDolGlobalString('PROJECT_FILTER_FOR_THIRDPARTY_LIST')) {
847 $filter = getDolGlobalString('PROJECT_FILTER_FOR_THIRDPARTY_LIST');
848 }
849 $text = img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company(GETPOSTINT('socid'), 'socid', $filter, 'SelectThirdParty', 1, 0, array(), 0, 'minwidth300 widthcentpercentminusxx maxwidth500');
850 if (!getDolGlobalString('PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS') && empty($conf->dol_use_jmobile)) {
851 $texthelp = $langs->trans("IfNeedToUseOtherObjectKeepEmpty");
852 print $form->textwithtooltip($text.' '.img_help(), $texthelp, 1);
853 } else {
854 print $text;
855 }
856 if (!GETPOSTISSET('backtopage')) {
857 $url = '/societe/card.php?action=create&customer=3&fournisseur=0&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create');
858 $newbutton = '<span class="fa fa-plus-circle valignmiddle paddingleft" title="'.$langs->trans("AddThirdParty").'"></span>';
859 // TODO @LDR Implement this
860 if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) {
861 $jsonclose = 'TODO Not yet implemented';
862 print dolButtonToOpenUrlInDialogPopup('addthirdparty', $langs->transnoentitiesnoconv('AddThirdParty'), $newbutton, $url, '', '', '', $jsonclose);
863 } else {
864 print ' <a href="'.DOL_URL_ROOT.$url.'">'.$newbutton.'</a>';
865 }
866 }
867 print '</td></tr>';
868 }
869
870 // Status
871 if ($status != '') {
872 print '<tr><td>'.$langs->trans("Status").'</td><td>';
873 print '<input type="hidden" name="status" value="'.$status.'">';
874 print $object->LibStatut($status, 4);
875 print '</td></tr>';
876 }
877
878 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) {
879 // Opportunity status
880 print '<tr class="classuseopportunity"><td><span class="fieldrequired">'.$langs->trans("OpportunityStatus").'</span></td>';
881 print '<td class="maxwidthonsmartphone">';
882 print $formproject->selectOpportunityStatus('opp_status', GETPOSTISSET('opp_status') ? GETPOST('opp_status') : $object->opp_status, 1, 0, 0, 0, '', 0, 1);
883
884 // Opportunity probability
885 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>';
886 print '<input type="hidden" name="opp_percent_not_set" id="opp_percent_not_set" value="'.dol_escape_htmltag(GETPOSTISSET('opp_percent') ? '0' : '1').'">';
887 print '</td>';
888 print '</tr>';
889
890 // Opportunity amount
891 print '<tr class="classuseopportunity"><td>'.$langs->trans("OpportunityAmount").'</td>';
892 print '<td><input class="width75 right" type="text" name="opp_amount" value="'.dol_escape_htmltag(GETPOSTISSET('opp_amount') ? GETPOST('opp_amount') : '').'">';
893 print ' '.$langs->getCurrencySymbol($conf->currency);
894 print '</td>';
895 print '</tr>';
896 }
897
898 // Budget
899 print '<tr><td>'.$langs->trans("Budget").'</td>';
900 print '<td><input class="width75 right" type="text" name="budget_amount" value="'.dol_escape_htmltag(GETPOSTISSET('budget_amount') ? GETPOST('budget_amount') : '').'">';
901 print ' '.$langs->getCurrencySymbol($conf->currency);
902 print '</td>';
903 print '</tr>';
904
905 // Date project
906 print '<tr><td>'.$langs->trans("Date").(isModEnabled('eventorganization') ? ' <span class="classuseorganizeevent">('.$langs->trans("Project").')</span>' : '').'</td><td>';
907 print $form->selectDate(($date_start ? $date_start : ''), 'projectstart', 0, 0, 0, '', 1, 0);
908 print ' <span class="opacitymedium"> '.$langs->trans("to").' </span> ';
909 print $form->selectDate(($date_end ? $date_end : -1), 'projectend', 0, 0, 0, '', 1, 0);
910 print '</td></tr>';
911
912 if (isModEnabled('eventorganization')) {
913 // Date event
914 print '<tr class="classuseorganizeevent"><td>'.$langs->trans("Date").' ('.$langs->trans("Event").')</td><td>';
915 print $form->selectDate(($date_start_event ? $date_start_event : -1), 'date_start_event', 1, 1, 1, '', 1, 0);
916 print ' <span class="opacitymedium"> '.$langs->trans("to").' </span> ';
917 print $form->selectDate(($date_end_event ? $date_end_event : -1), 'date_end_event', 1, 1, 1, '', 1, 0);
918 print '</td></tr>';
919
920 // Location
921 print '<tr class="classuseorganizeevent"><td>'.$langs->trans("Location").'</td>';
922 print '<td><input class="minwidth300 maxwidth500" type="text" name="location" value="'.dol_escape_htmltag($location).'"></td>';
923 print '</tr>';
924 }
925
926 // Description
927 print '<tr><td class="tdtop">'.$langs->trans("Description").'</td>';
928 print '<td>';
929 $doleditor = new DolEditor('description', GETPOST("description", 'restricthtml'), '', 90, 'dolibarr_notes', '', false, true, isModEnabled('fckeditor') && getDolGlobalString('FCKEDITOR_ENABLE_SOCIETE'), ROWS_3, '90%');
930 $doleditor->Create();
931 print '</td></tr>';
932
933 if (isModEnabled('category')) {
934 // Categories
935 print '<tr><td>'.$langs->trans("Categories").'</td><td colspan="3">';
936 print $form->selectCategories(Categorie::TYPE_PROJECT, 'categories', $object);
937 print "</td></tr>";
938 }
939
940 // Visibility
941 print '<tr><td>'.$langs->trans("Visibility").'</td><td class="maxwidthonsmartphone">';
942 $array = array();
943 if (!getDolGlobalString('PROJECT_DISABLE_PRIVATE_PROJECT')) {
944 $array[0] = $langs->trans("PrivateProject");
945 }
946 if (!getDolGlobalString('PROJECT_DISABLE_PUBLIC_PROJECT')) {
947 $array[1] = $langs->trans("SharedProject");
948 }
949
950 if (count($array) > 0) {
951 print $form->selectarray('public', $array, GETPOSTINT('public') ? 1 : 0, 0, 0, 0, '', 0, 0, 0, '', 'minwidth200', 1);
952 } else {
953 print '<input type="hidden" name="public" id="public" value="'.(GETPOSTINT('public') ? 1 : 0).'">';
954
955 if (GETPOSTINT('public') == 0) {
956 print img_picto($langs->trans('PrivateProject'), 'private', 'class="paddingrightonly"');
957 print $langs->trans("PrivateProject");
958 } else {
959 print img_picto($langs->trans('SharedProject'), 'world', 'class="paddingrightonly"');
960 print $langs->trans("SharedProject");
961 }
962 }
963 print '</td></tr>';
964
965 // Selection of Owner contact type
966 print '<tr><td class="tdtop">'.$langs->trans("ProjectContactTypeManager").'</td>';
967 print '<td>';
968 $contactList = $object->liste_type_contact('internal', 'position', 1);
969 $typeofcontact = GETPOST('typeofcontact') ? GETPOST('typeofcontact') : 'PROJECTLEADER';
970 print $form->selectarray('typeofcontact', $contactList, $typeofcontact, 0, 0, 0, '', 0, 0, 0, '', 'minwidth200', 1);
971 print '</td></tr>';
972
973 // Other options
974 $parameters = array();
975 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
976 print $hookmanager->resPrint;
977 if (empty($reshook)) {
978 print $object->showOptionals($extrafields, 'create');
979 }
980
981 print '</table>';
982
983 print dol_get_fiche_end();
984
985 print $form->buttonsSaveCancel('CreateDraft');
986
987 print '</form>';
988
989 // Change probability from status or role of project
990 // Set also dependencies between use task and bill time
991 print '<script type="text/javascript">
992 jQuery(document).ready(function() {
993 function change_percent()
994 {
995 var element = jQuery("#opp_status option:selected");
996 var defaultpercent = element.attr("defaultpercent");
997 /*if (jQuery("#opp_percent_not_set").val() == "") */
998 /* defaultpercent is the raw DB value (double(5,2), ie "100.00"), so normalize it */
999 jQuery("#opp_percent").val(parseFloat(defaultpercent));
1000 }
1001
1002 /*init_myfunc();*/
1003 jQuery("#opp_status").change(function() {
1004 change_percent();
1005 });
1006
1007 jQuery("#usage_task").change(function() {
1008 console.log("We click on usage task "+jQuery("#usage_task").is(":checked"));
1009 if (! jQuery("#usage_task").is(":checked")) {
1010 jQuery("#usage_bill_time").prop("checked", false);
1011 }
1012 });
1013
1014 jQuery("#usage_bill_time").change(function() {
1015 console.log("We click on usage to bill time");
1016 if (jQuery("#usage_bill_time").is(":checked")) {
1017 jQuery("#usage_task").prop("checked", true);
1018 }
1019 });
1020 });
1021 </script>';
1022} elseif ($object->id > 0) {
1023 /*
1024 * Show or edit
1025 */
1026
1027 $res = $object->fetch_optionals();
1028
1029 // To verify role of users
1030 $userAccess = $object->restrictedProjectArea($user, 'read');
1031 $userWrite = $object->restrictedProjectArea($user, 'write');
1032 $userDelete = $object->restrictedProjectArea($user, 'delete');
1033 //print "userAccess=".$userAccess." userWrite=".$userWrite." userDelete=".$userDelete;
1034
1035 $formconfirm = "" ;
1036
1037 // Confirmation validation
1038 if ($action == 'validate') {
1039 $text = $langs->trans('ConfirmValidateProject');
1040 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ValidateProject'), $text, 'confirm_validate', '', 0, 1);
1041 }
1042 // Confirmation close
1043 if ($action == 'close') {
1044 $text = $langs->trans("ConfirmCloseAProject");
1045 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id, $langs->trans("CloseAProject"), $text, "confirm_close", '', '', 1);
1046 }
1047 // Confirmation reopen
1048 if ($action == 'reopen') {
1049 $text = $langs->trans("ConfirmReOpenAProject");
1050 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id, $langs->trans("ReOpenAProject"), $text, "confirm_reopen", '', '', 1);
1051 }
1052 // Confirmation delete
1053 if ($action == 'delete') {
1054 $text = $langs->trans("ConfirmDeleteAProject");
1055 $task = new Task($db);
1056 $taskarray = $task->getTasksArray(null, null, $object->id, 0, 0);
1057 $nboftask = count($taskarray);
1058 if ($nboftask) {
1059 $text .= '<br>'.img_warning().' '.$langs->trans("ThisWillAlsoRemoveTasks", $nboftask);
1060 }
1061 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id, $langs->trans("DeleteAProject"), $text, "confirm_delete", '', '', 1);
1062 }
1063
1064 // Clone confirmation
1065 if ($action == 'clone') {
1066 $text = $langs->trans("ConfirmCloneProject");
1067 $formquestion = array(
1068 'text' => $langs->trans("ConfirmClone"),
1069 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')),
1070 1 => array('type' => 'checkbox', 'name' => 'clone_contacts', 'label' => $langs->trans("CloneContacts"), 'value' => true),
1071 2 => array('type' => 'checkbox', 'name' => 'clone_tasks', 'label' => $langs->trans("CloneTasks"), 'value' => true),
1072 3 => array('type' => 'checkbox', 'name' => 'move_date', 'label' => $langs->trans("CloneMoveDate"), 'value' => true),
1073 4 => array('type' => 'checkbox', 'name' => 'clone_notes', 'label' => $langs->trans("CloneNotes"), 'value' => true),
1074 5 => array('type' => 'checkbox', 'name' => 'clone_project_files', 'label' => $langs->trans("CloneProjectFiles"), 'value' => false),
1075 6 => array('type' => 'checkbox', 'name' => 'clone_task_files', 'label' => $langs->trans("CloneTaskFiles"), 'value' => false)
1076 );
1077
1078 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id, $langs->trans("ToClone"), $text, "confirm_clone", $formquestion, '', 1, 0, 600);
1079 }
1080
1081 // Call Hook formConfirm
1082 $parameters = array('formConfirm' => $formconfirm);
1083 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1084 if (empty($reshook)) {
1085 $formconfirm .= $hookmanager->resPrint;
1086 } elseif ($reshook > 0) {
1087 $formconfirm = $hookmanager->resPrint;
1088 }
1089
1090 // Print form confirm
1091 print $formconfirm;
1092
1093
1094 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
1095 print '<input type="hidden" name="token" value="'.newToken().'">';
1096 print '<input type="hidden" name="action" value="update">';
1097 print '<input type="hidden" name="id" value="'.$object->id.'">';
1098 print '<input type="hidden" name="comefromclone" value="'.$comefromclone.'">';
1099
1100 $head = project_prepare_head($object);
1101
1102 if ($action == 'edit' && $userWrite > 0) {
1103 print dol_get_fiche_head($head, 'project', $langs->trans("Project"), 0, ($object->public ? 'projectpub' : 'project'));
1104
1105 print '<table class="border centpercent">';
1106
1107 // Ref
1108 $suggestedref = $object->ref;
1109 print '<tr><td class="titlefield fieldrequired">'.$langs->trans("Ref").'</td>';
1110 print '<td><input class="width200" name="ref" value="'.$suggestedref.'">';
1111 print ' '.$form->textwithpicto('', $langs->trans("YouCanCompleteRef", $suggestedref));
1112 print '</td></tr>';
1113
1114 // Label
1115 print '<tr><td class="fieldrequired">'.$langs->trans("Label").'</td>';
1116 print '<td><input class="quatrevingtpercent" name="title" value="'.dol_escape_htmltag($object->title).'"></td></tr>';
1117
1118 // Status
1119 print '<tr><td class="fieldrequired">'.$langs->trans("Status").'</td><td>';
1120 print '<select class="flat" name="status" id="status">';
1121 $statuses = $object->labelStatusShort;
1122 if (getDolGlobalString('MAIN_DISABLEDRAFTSTATUS') || getDolGlobalString('MAIN_DISABLEDRAFTSTATUS_PROJECT')) {
1123 unset($statuses[$object::STATUS_DRAFT]);
1124 }
1125 foreach ($statuses as $key => $val) {
1126 print '<option value="'.$key.'"'.((GETPOSTISSET('status') ? GETPOST('status') : $object->status) == $key ? ' selected="selected"' : '').'>'.$langs->trans($val).'</option>';
1127 }
1128 print '</select>';
1129 print ajax_combobox('status');
1130 print '</td></tr>';
1131
1132 // Parent
1133 if (getDolGlobalInt('PROJECT_ENABLE_SUB_PROJECT')) {
1134 print '<tr><td>'.$langs->trans("Parent").'</td><td class="maxwidthonsmartphone">';
1135 print img_picto('', 'project', 'class="pictofixedwidth"');
1136 $formproject->select_projects(-1, (string) $object->fk_project, 'fk_project', 64, 0, 1, 1, 0, 0, 0, '', 0, 0, '', '', '');
1137 print '</td></tr>';
1138 }
1139
1140 // Usage
1141 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES') || !getDolGlobalString('PROJECT_HIDE_TASKS') || isModEnabled('eventorganization')) {
1142 print '<tr><td class="tdtop">';
1143 print $langs->trans("Usage");
1144 print '</td>';
1145 print '<td>';
1146 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) {
1147 print '<input type="checkbox" id="usage_opportunity" name="usage_opportunity"'.(GETPOSTISSET('usage_opportunity') ? (GETPOST('usage_opportunity', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_opportunity ? ' checked="checked"' : '')).'> ';
1148 $htmltext = $langs->trans("ProjectFollowOpportunity");
1149 print '<label for="usage_opportunity">'.$form->textwithpicto($langs->trans("ProjectFollowOpportunity"), $htmltext).'</label>';
1150 print '<script>';
1151 print '$( document ).ready(function() {
1152 jQuery("#usage_opportunity").change(function() {
1153 set_usage_opportunity();
1154 });
1155
1156 set_usage_opportunity();
1157
1158 function set_usage_opportunity() {
1159 console.log("set_usage_opportunity");
1160 if (jQuery("#usage_opportunity").prop("checked")) {
1161 console.log("Show opportunities fields");
1162 jQuery(".classuseopportunity").show();
1163 } else {
1164 console.log("Hide opportunities fields "+jQuery("#usage_opportunity").prop("checked"));
1165 jQuery(".classuseopportunity").hide();
1166 }
1167 }
1168 });';
1169 print '</script>';
1170 print '<br>';
1171 }
1172 if (!getDolGlobalString('PROJECT_HIDE_TASKS')) {
1173 print '<input type="checkbox" id="usage_task" name="usage_task"' . (GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_task ? ' checked="checked"' : '')) . '> ';
1174 $htmltext = $langs->trans("ProjectFollowTasks");
1175 print '<label for="usage_task">'.$form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext).'</label>';
1176 print '<script>';
1177 print '$( document ).ready(function() {
1178 jQuery("#usage_task").change(function() {
1179 set_usage_task();
1180 });
1181
1182 set_usage_task();
1183
1184 function set_usage_task() {
1185 console.log("set_usage_task");
1186 if (jQuery("#usage_task").prop("checked")) {
1187 console.log("Show task fields");
1188 jQuery(".classusetask").show();
1189 } else {
1190 console.log("Hide task fields "+jQuery("#usage_task").prop("checked"));
1191 jQuery(".classusetask").hide();
1192 }
1193 }
1194 });';
1195 print '</script>';
1196 print '<br>';
1197 }
1198 if (!getDolGlobalString('PROJECT_HIDE_TASKS') && getDolGlobalString('PROJECT_BILL_TIME_SPENT')) {
1199 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"' : '')) . '> ';
1200 $htmltext = $langs->trans("ProjectBillTimeDescription");
1201 print '<label for="usage_bill_time">'.$form->textwithpicto($langs->trans("BillTime"), $htmltext).'</label>';
1202 print '<script>';
1203 print '$( document ).ready(function() {
1204 jQuery("#usage_bill_time").change(function() {
1205 set_usage_bill_time();
1206 });
1207
1208 set_usage_bill_time();
1209
1210 function set_usage_bill_time() {
1211 console.log("set_usage_bill_time");
1212 if (jQuery("#usage_bill_time").prop("checked")) {
1213 console.log("Show bill time fields");
1214 jQuery(".classusebilltime").show();
1215 } else {
1216 console.log("Hide bill time fields "+jQuery("#usage_bill_time").prop("checked"));
1217 jQuery(".classusebilltime").hide();
1218 }
1219 }
1220 });';
1221 print '</script>';
1222 print '<br>';
1223 }
1224 if (isModEnabled('eventorganization')) {
1225 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"' : '')) . '> ';
1226 $htmltext = $langs->trans("EventOrganizationDescriptionLong");
1227 print '<label for="usage_organize_event">'.$form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext).'</label>';
1228 print '<script>';
1229 print '$( document ).ready(function() {
1230 jQuery("#usage_organize_event").change(function() {
1231 set_usage_event();
1232 });
1233
1234 set_usage_event();
1235
1236 function set_usage_event() {
1237 console.log("set_usage_event");
1238 if (jQuery("#usage_organize_event").prop("checked")) {
1239 console.log("Show organize event fields");
1240 jQuery(".classuseorganizeevent").show();
1241 } else {
1242 console.log("Hide organize event fields "+jQuery("#usage_organize_event").prop("checked"));
1243 jQuery(".classuseorganizeevent").hide();
1244 }
1245 }
1246 });';
1247 print '</script>';
1248 }
1249 print '</td></tr>';
1250 }
1251 print '</td></tr>';
1252
1253 // Thirdparty
1254 if (isModEnabled('societe')) {
1255 print '<tr><td>';
1256 print(!getDolGlobalString('PROJECT_THIRDPARTY_REQUIRED') ? '' : '<span class="fieldrequired">');
1257 print $langs->trans("ThirdParty");
1258 print(!getDolGlobalString('PROJECT_THIRDPARTY_REQUIRED') ? '' : '</span>');
1259 print '</td><td>';
1260 $filter = '';
1261 if (getDolGlobalString('PROJECT_FILTER_FOR_THIRDPARTY_LIST')) {
1262 $filter = getDolGlobalString('PROJECT_FILTER_FOR_THIRDPARTY_LIST');
1263 }
1264 $text = img_picto('', 'company', 'class="pictofixedwidth"');
1265 $text .= $form->select_company(!empty($object->thirdparty->id) ? $object->thirdparty->id : "", 'socid', $filter, 'None', 1, 0, array(), 0, 'minwidth300');
1266 if (!getDolGlobalString('PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS') && empty($conf->dol_use_jmobile)) {
1267 $texthelp = $langs->trans("IfNeedToUseOtherObjectKeepEmpty");
1268 print $form->textwithtooltip($text.' '.img_help(), $texthelp, 1, 0, '', '', 2);
1269 } else {
1270 print $text;
1271 }
1272 print '</td></tr>';
1273 }
1274
1275 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) {
1276 $classfortr = ($object->usage_opportunity ? '' : ' hideobject');
1277 // Opportunity status
1278 print '<tr class="classuseopportunity'.$classfortr.'"><td>'.$langs->trans("OpportunityStatus").'</td>';
1279 print '<td>';
1280 print '<div>';
1281 print $formproject->selectOpportunityStatus('opp_status', (string) $object->opp_status, 1, 0, 0, 0, 'minwidth150 inline-block valignmiddle', 1, 1);
1282
1283 // Opportunity probability
1284 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) : '')).'"> %';
1285 print '<span id="oldopppercent" class="opacitymedium"></span>';
1286 print '</div>';
1287
1288 print '<div id="divtocloseproject" class="inline-block valign clearboth paddingtop" style="display: none;">';
1289 print '<input type="checkbox" id="inputcloseproject" name="closeproject" class="valignmiddle" />';
1290 print '<label for="inputcloseproject" class="opacitymedium valignmiddle">';
1291 print $form->textwithpicto($langs->trans("AlsoCloseAProject"), $langs->trans("AlsoCloseAProjectTooltip"));
1292 print '</label>';
1293 print ' </div>';
1294
1295 print '</td>';
1296 print '</tr>';
1297
1298 // Opportunity amount
1299 print '<tr class="classuseopportunity'.$classfortr.' "><td>'.$langs->trans("OpportunityAmount").'</td>';
1300 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) : '')).'">';
1301 print '<span class="opacitymedium">'.$langs->getCurrencySymbol($conf->currency).'</span>';
1302 print '</td>';
1303 print '</tr>';
1304 }
1305
1306 // Budget
1307 print '<tr><td>'.$langs->trans("Budget").'</td>';
1308 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) : '')).'">';
1309 print '<span class="opacitymedium">'.$langs->getCurrencySymbol($conf->currency).'</span>';
1310 print '</td>';
1311 print '</tr>';
1312
1313 // Date project
1314 print '<tr><td>'.$langs->trans("Date").(isModEnabled('eventorganization') ? ' <span class="classuseorganizeevent">('.$langs->trans("Project").')</span>' : '').'</td><td>';
1315 print $form->selectDate($object->date_start ? $object->date_start : -1, 'projectstart', 0, 0, 0, '', 1, 0);
1316 print ' <span class="opacitymedium"> '.$langs->trans("to").' </span> ';
1317 print $form->selectDate($object->date_end ? $object->date_end : -1, 'projectend', 0, 0, 0, '', 1, 0);
1318 $object->getLinesArray(null, 0);
1319 if (!empty($object->usage_task) && !empty($object->lines)) {
1320 print ' <span id="divreportdate" class="hidden">&nbsp; &nbsp; <input type="checkbox" class="valignmiddle" id="reportdate" name="reportdate" value="yes" ';
1321 if ($comefromclone) {
1322 print 'checked ';
1323 }
1324 print '/><label for="reportdate" class="valignmiddle opacitymedium">'.$langs->trans("ProjectReportDate").'</label></span>';
1325 }
1326 print '</td></tr>';
1327
1328 if (isModEnabled('eventorganization')) {
1329 // Date event
1330 print '<tr class="classuseorganizeevent"><td>'.$langs->trans("Date").' ('.$langs->trans("Event").')</td><td>';
1331 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);
1332 print ' <span class="opacitymedium"> '.$langs->trans("to").' </span> ';
1333 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);
1334 print '</td></tr>';
1335
1336 // Location
1337 print '<tr class="classuseorganizeevent"><td>'.$langs->trans("Location").'</td>';
1338 print '<td><input class="minwidth300 maxwidth500" type="text" name="location" value="'.dol_escape_htmltag(GETPOSTISSET('location') ? GETPOST('location') : $object->location).'"></td>';
1339 print '</tr>';
1340 }
1341
1342 // Description
1343 print '<tr><td class="tdtop">'.$langs->trans("Description").'</td>';
1344 print '<td>';
1345 $doleditor = new DolEditor('description', $object->description, '', 90, 'dolibarr_notes', '', false, true, isModEnabled('fckeditor') && getDolGlobalInt('FCKEDITOR_ENABLE_SOCIETE'), ROWS_3, '90%');
1346 $doleditor->Create();
1347 print '</td></tr>';
1348
1349 // Tags-Categories
1350 if (isModEnabled('category')) {
1351 print '<tr><td>'.$langs->trans("Categories").'</td><td>';
1352 print $form->selectCategories(Categorie::TYPE_PROJECT, 'categories', $object);
1353 print "</td></tr>";
1354 }
1355
1356 // Visibility
1357 print '<tr><td>'.$langs->trans("Visibility").'</td><td>';
1358 $array = array();
1359 if (!getDolGlobalString('PROJECT_DISABLE_PRIVATE_PROJECT')) {
1360 $array[0] = $langs->trans("PrivateProject");
1361 }
1362 if (!getDolGlobalString('PROJECT_DISABLE_PUBLIC_PROJECT')) {
1363 $array[1] = $langs->trans("SharedProject");
1364 }
1365
1366 if (count($array) > 0) {
1367 print $form->selectarray('public', $array, $object->public, 0, 0, 0, '', 0, 0, 0, '', '', 1);
1368 } else {
1369 print '<input type="hidden" id="public" name="public" value="'.$object->public.'">';
1370
1371 if ($object->public == 0) {
1372 print img_picto($langs->trans('PrivateProject'), 'private', 'class="paddingrightonly"');
1373 print $langs->trans("PrivateProject");
1374 } else {
1375 print img_picto($langs->trans('SharedProject'), 'world', 'class="paddingrightonly"');
1376 print $langs->trans("SharedProject");
1377 }
1378 }
1379 print '</td></tr>';
1380
1381 // Other options
1382 $parameters = array();
1383 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1384 print $hookmanager->resPrint;
1385 if (empty($reshook)) {
1386 print $object->showOptionals($extrafields, 'edit');
1387 }
1388
1389 print '</table>';
1390 } else {
1391 print dol_get_fiche_head($head, 'project', $langs->trans("Project"), -1, ($object->public ? 'projectpub' : 'project'), 0, '', '', 0, '', 1);
1392
1393 // Project card
1394
1395 if (!empty($_SESSION['pageforbacktolist']) && !empty($_SESSION['pageforbacktolist']['project'])) {
1396 $tmpurl = $_SESSION['pageforbacktolist']['project'];
1397 $tmpurl = preg_replace('/__SOCID__/', (string) $object->socid, $tmpurl);
1398 $linkback = '<a href="'.$tmpurl.(preg_match('/\?/', $tmpurl) ? '&' : '?'). 'restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
1399 } else {
1400 $linkback = '<a href="'.DOL_URL_ROOT.'/projet/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
1401 }
1402
1403 $morehtmlref = '<div class="refidno">';
1404 // Title
1405 $morehtmlref .= dol_escape_htmltag($object->title);
1406 $morehtmlref .= '<br>';
1407 // Thirdparty
1408 if (!empty($object->thirdparty->id) && $object->thirdparty->id > 0) {
1409 $morehtmlref .= $object->thirdparty->getNomUrl(1, 'project');
1410 }
1411 // Parent
1412 if (getDolGlobalInt('PROJECT_ENABLE_SUB_PROJECT')) {
1413 if (!empty($object->fk_project) && $object->fk_project) {
1414 $parent = new Project($db);
1415 $parent->fetch($object->fk_project);
1416 $morehtmlref .= $langs->trans("Child of").' '.$parent->getNomUrl(1, 'project').' '.$parent->title;
1417 }
1418 }
1419 $morehtmlref .= '</div>';
1420
1421 // Define a complementary filter for search of next/prev ref.
1422 if (!$user->hasRight('projet', 'all', 'lire')) {
1423 $objectsListId = $object->getProjectsAuthorizedForUser($user, 0, 0);
1424 $object->next_prev_filter = "rowid:IN:".$db->sanitize(count($objectsListId) ? implode(',', array_keys($objectsListId)) : '0');
1425 }
1426
1427 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
1428
1429 print '<div class="fichecenter">';
1430 print '<div class="fichehalfleft">';
1431 print '<div class="underbanner clearboth"></div>';
1432
1433 print '<table class="border tableforfield centpercent">';
1434
1435 // Usage
1436 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES') || !getDolGlobalString('PROJECT_HIDE_TASKS') || isModEnabled('eventorganization')) {
1437 print '<tr><td class="tdtop">';
1438 print $langs->trans("Usage");
1439 print '</td>';
1440 print '<td>';
1441 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) {
1442 print '<input type="checkbox" disabled name="usage_opportunity"'.(GETPOSTISSET('usage_opportunity') ? (GETPOST('usage_opportunity', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_opportunity ? ' checked="checked"' : '')).'> ';
1443 $htmltext = $langs->trans("ProjectFollowOpportunity");
1444 print $form->textwithpicto($langs->trans("ProjectFollowOpportunity"), $htmltext);
1445 print '<br>';
1446 }
1447 if (!getDolGlobalString('PROJECT_HIDE_TASKS')) {
1448 print '<input type="checkbox" disabled name="usage_task"'.(GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_task ? ' checked="checked"' : '')).'> ';
1449 $htmltext = $langs->trans("ProjectFollowTasks");
1450 print $form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext);
1451 print '<br>';
1452 }
1453 if (!getDolGlobalString('PROJECT_HIDE_TASKS') && getDolGlobalString('PROJECT_BILL_TIME_SPENT')) {
1454 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"' : '')).'> ';
1455 $htmltext = $langs->trans("ProjectBillTimeDescription");
1456 print $form->textwithpicto($langs->trans("BillTime"), $htmltext);
1457 print '<br>';
1458 }
1459
1460 if (isModEnabled('eventorganization')) {
1461 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"' : '')).'> ';
1462 $htmltext = $langs->trans("EventOrganizationDescriptionLong");
1463 print $form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext);
1464 }
1465 print '</td></tr>';
1466 }
1467
1468 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES') && !empty($object->usage_opportunity)) {
1469 // Opportunity status
1470 print '<tr><td>';
1471 print $form->editfieldkey("OpportunityStatus", '_opp_status', (string) $object->opp_status, $object, (int) $user->hasRight('projet', 'creer'), 'string');
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 print $formproject->formOpportunityStatus($_SERVER['PHP_SELF'].'?socid='.$object->id, (string) $object->opp_status, $percent_value, $html_name_status, $html_name_percent, '', 1);
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'), $langs->trans('ToClone'), 'clone', $_SERVER["PHP_SELF"].'?action=clone&token='.newToken().'&id='.((int) $object->id), '', true, array('attr' => array('class' => 'reposition')));
1777 } else {
1778 print dolGetButtonAction($langs->trans('NotOwnerOfProject'), $langs->trans('ToClone'), 'clone', $_SERVER['PHP_SELF']. '#', '', false, array('attr' => array('class' => 'reposition')));
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'), $langs->trans('Delete'), 'delete', $_SERVER["PHP_SELF"].'?action=delete&token='.newToken().'&id='.$object->id, '', true, array('attr' => array('class' => 'reposition')))."\n";
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='', $placeholder='')
Convert a html select field into an ajax combobox.
Definition ajax.lib.php:477
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:
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.
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.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_eval($s, $returnvalue=1, $hideerrors=1, $onlysimplestring='1')
Replace eval function to add more security.
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.
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).
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.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
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.
Definition html.lib.php:540
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.
Definition html.lib.php:435
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.
Definition html.lib.php:738
getTitleFieldOfList($name, $thead=0, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $disablesortlink=0, $tooltip='', $forcenowrapcolumntitle=0)
Get title line of an array.
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Definition html.lib.php:181
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.