card.php 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037
  1. <?php
  2. /* Copyright (C) 2001-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  3. * Copyright (C) 2004-2015 Laurent Destailleur <eldy@users.sourceforge.net>
  4. * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@capnetworks.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. /**
  20. * \file htdocs/projet/card.php
  21. * \ingroup projet
  22. * \brief Project card
  23. */
  24. require '../main.inc.php';
  25. require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
  26. require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
  27. require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
  28. require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
  29. require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
  30. require_once DOL_DOCUMENT_ROOT.'/core/modules/project/modules_project.php';
  31. require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
  32. $langs->load("projects");
  33. $langs->load('companies');
  34. $id=GETPOST('id','int');
  35. $ref=GETPOST('ref','alpha');
  36. $action=GETPOST('action','alpha');
  37. $backtopage=GETPOST('backtopage','alpha');
  38. $cancel=GETPOST('cancel','alpha');
  39. $status=GETPOST('status','int');
  40. $opp_status=GETPOST('opp_status','int');
  41. $opp_percent=price2num(GETPOST('opp_percent','alpha'));
  42. if ($id == '' && $ref == '' && ($action != "create" && $action != "add" && $action != "update" && ! $_POST["cancel"])) accessforbidden();
  43. $mine = GETPOST('mode')=='mine' ? 1 : 0;
  44. //if (! $user->rights->projet->all->lire) $mine=1; // Special for projects
  45. // Initialize technical object to manage hooks of thirdparties. Note that conf->hooks_modules contains array array
  46. $hookmanager->initHooks(array('projectcard','globalcard'));
  47. $object = new Project($db);
  48. $extrafields = new ExtraFields($db);
  49. // Load object
  50. //include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Can't use generic include because when creating a project, ref is defined and we dont want error if fetch fails from ref.
  51. if ($id > 0 || ! empty($ref))
  52. {
  53. $ret = $object->fetch($id,$ref); // If we create project, ref may be defined into POST but record does not yet exists into database
  54. if ($ret > 0) {
  55. $object->fetch_thirdparty();
  56. $id=$object->id;
  57. }
  58. }
  59. // Security check
  60. $socid=GETPOST('socid');
  61. if ($user->societe_id > 0) $socid=$user->societe_id;
  62. $result = restrictedArea($user, 'projet', $object->id,'projet&project');
  63. // fetch optionals attributes and labels
  64. $extralabels=$extrafields->fetch_name_optionals_label($object->table_element);
  65. $date_start=dol_mktime(0,0,0,GETPOST('projectstartmonth','int'),GETPOST('projectstartday','int'),GETPOST('projectstartyear','int'));
  66. $date_end=dol_mktime(0,0,0,GETPOST('projectendmonth','int'),GETPOST('projectendday','int'),GETPOST('projectendyear','int'));
  67. /*
  68. * Actions
  69. */
  70. $parameters=array('id'=>$socid, 'objcanvas'=>$objcanvas);
  71. $reshook=$hookmanager->executeHooks('doActions',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
  72. if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
  73. if (empty($reshook))
  74. {
  75. // Cancel
  76. if ($cancel)
  77. {
  78. if (GETPOST("comefromclone")==1)
  79. {
  80. $result=$object->delete($user);
  81. if ($result > 0)
  82. {
  83. header("Location: index.php");
  84. exit;
  85. }
  86. else
  87. {
  88. dol_syslog($object->error,LOG_DEBUG);
  89. setEventMessages($langs->trans("CantRemoveProject"), null, 'errors');
  90. }
  91. }
  92. if ($backtopage)
  93. {
  94. header("Location: ".$backtopage);
  95. exit;
  96. }
  97. $action = '';
  98. }
  99. if ($action == 'add' && $user->rights->projet->creer)
  100. {
  101. $error=0;
  102. if (empty($_POST["ref"]))
  103. {
  104. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Ref")), null, 'errors');
  105. $error++;
  106. }
  107. if (empty($_POST["title"]))
  108. {
  109. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
  110. $error++;
  111. }
  112. if (! $error)
  113. {
  114. $error=0;
  115. $db->begin();
  116. $object->ref = GETPOST('ref','alpha');
  117. $object->title = GETPOST('title'); // Do not use 'alpha' here, we want field as it is
  118. $object->socid = GETPOST('socid','int');
  119. $object->description = GETPOST('description'); // Do not use 'alpha' here, we want field as it is
  120. $object->public = GETPOST('public','alpha');
  121. $object->opp_amount = price2num(GETPOST('opp_amount'));
  122. $object->budget_amount = price2num(GETPOST('budget_amount'));
  123. $object->datec=dol_now();
  124. $object->date_start=$date_start;
  125. $object->date_end=$date_end;
  126. $object->statuts = $status;
  127. $object->opp_status = $opp_status;
  128. $object->opp_percent = $opp_percent;
  129. // Fill array 'array_options' with data from add form
  130. $ret = $extrafields->setOptionalsFromPost($extralabels,$object);
  131. if ($ret < 0) $error++;
  132. $result = $object->create($user);
  133. if (! $error && $result > 0)
  134. {
  135. // Add myself as project leader
  136. $result = $object->add_contact($user->id, 'PROJECTLEADER', 'internal');
  137. if ($result < 0)
  138. {
  139. $langs->load("errors");
  140. setEventMessages($langs->trans($object->error), null, 'errors');
  141. $error++;
  142. }
  143. }
  144. else
  145. {
  146. $langs->load("errors");
  147. setEventMessages($langs->trans($object->error), null, 'errors');
  148. $error++;
  149. }
  150. if (! $error)
  151. {
  152. $db->commit();
  153. if ($backtopage)
  154. {
  155. header("Location: ".$backtopage.'&projectid='.$object->id);
  156. exit;
  157. }
  158. else
  159. {
  160. header("Location:card.php?id=".$object->id);
  161. exit;
  162. }
  163. }
  164. else
  165. {
  166. $db->rollback();
  167. $action = 'create';
  168. }
  169. }
  170. else
  171. {
  172. $action = 'create';
  173. }
  174. }
  175. if ($action == 'update' && ! $_POST["cancel"] && $user->rights->projet->creer)
  176. {
  177. $error=0;
  178. if (empty($ref))
  179. {
  180. $error++;
  181. //$_GET["id"]=$_POST["id"]; // We return on the project card
  182. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Ref")), null, 'errors');
  183. }
  184. if (empty($_POST["title"]))
  185. {
  186. $error++;
  187. //$_GET["id"]=$_POST["id"]; // We return on the project card
  188. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
  189. }
  190. $db->begin();
  191. if (! $error)
  192. {
  193. $object->oldcopy = clone $object;
  194. $old_start_date = $object->date_start;
  195. $object->ref = GETPOST('ref','alpha');
  196. $object->title = GETPOST('title'); // Do not use 'alpha' here, we want field as it is
  197. $object->socid = GETPOST('socid','int');
  198. $object->description = GETPOST('description'); // Do not use 'alpha' here, we want field as it is
  199. $object->public = GETPOST('public','alpha');
  200. $object->date_start = empty($_POST["projectstart"])?'':$date_start;
  201. $object->date_end = empty($_POST["projectend"])?'':$date_end;
  202. if (isset($_POST['opp_amount'])) $object->opp_amount = price2num(GETPOST('opp_amount'));
  203. if (isset($_POST['budget_amount'])) $object->budget_amount= price2num(GETPOST('budget_amount'));
  204. if (isset($_POST['opp_status'])) $object->opp_status = $opp_status;
  205. if (isset($_POST['opp_percent'])) $object->opp_percent = $opp_percent;
  206. // Fill array 'array_options' with data from add form
  207. $ret = $extrafields->setOptionalsFromPost($extralabels,$object);
  208. if ($ret < 0) $error++;
  209. }
  210. if ($object->opp_amount && ($object->opp_status <= 0))
  211. {
  212. $error++;
  213. setEventMessages($langs->trans("ErrorOppStatusRequiredIfAmount"), null, 'errors');
  214. }
  215. if (! $error)
  216. {
  217. $result=$object->update($user);
  218. if ($result < 0)
  219. {
  220. $error++;
  221. setEventMessages($object->error, $object->errors,'errors');
  222. }
  223. }
  224. if (! $error)
  225. {
  226. if (GETPOST("reportdate") && ($object->date_start!=$old_start_date))
  227. {
  228. $result=$object->shiftTaskDate($old_start_date);
  229. if ($result < 0)
  230. {
  231. $error++;
  232. setEventMessages($langs->trans("ErrorShiftTaskDate").':'.$object->error, $langs->trans("ErrorShiftTaskDate").':'.$object->errors, 'errors');
  233. }
  234. }
  235. }
  236. if ($error)
  237. {
  238. $db->rollback();
  239. $action='edit';
  240. }
  241. else
  242. {
  243. $db->commit();
  244. if (GETPOST('socid','int') > 0) $object->fetch_thirdparty(GETPOST('socid','int'));
  245. else unset($object->thirdparty);
  246. }
  247. }
  248. // Build doc
  249. if ($action == 'builddoc' && $user->rights->projet->creer)
  250. {
  251. // Save last template used to generate document
  252. if (GETPOST('model')) $object->setDocModel($user, GETPOST('model','alpha'));
  253. $outputlangs = $langs;
  254. if (GETPOST('lang_id'))
  255. {
  256. $outputlangs = new Translate("",$conf);
  257. $outputlangs->setDefaultLang(GETPOST('lang_id'));
  258. }
  259. $result= $object->generateDocument($object->modelpdf, $outputlangs);
  260. if ($result <= 0)
  261. {
  262. setEventMessages($object->error, $object->errors, 'errors');
  263. $action='';
  264. }
  265. }
  266. // Delete file in doc form
  267. if ($action == 'remove_file' && $user->rights->projet->creer)
  268. {
  269. require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
  270. if ($object->id > 0)
  271. {
  272. $langs->load("other");
  273. $upload_dir = $conf->projet->dir_output . "/";
  274. $urlfile=GETPOST('urlfile','alpha');
  275. $file = $upload_dir . '/' . $filetodelete;
  276. $ret=dol_delete_file($file);
  277. if ($ret) setEventMessages($langs->trans("FileWasRemoved", $urlfile), null, 'mesgs');
  278. else setEventMessages($langs->trans("ErrorFailToDeleteFile", $urlfile), null, 'errors');
  279. }
  280. }
  281. if ($action == 'confirm_validate' && GETPOST('confirm') == 'yes')
  282. {
  283. $result = $object->setValid($user);
  284. if ($result <= 0)
  285. {
  286. setEventMessages($object->error, $object->errors, 'errors');
  287. }
  288. }
  289. if ($action == 'confirm_close' && GETPOST('confirm') == 'yes')
  290. {
  291. $result = $object->setClose($user);
  292. if ($result <= 0)
  293. {
  294. setEventMessages($object->error, $object->errors, 'errors');
  295. }
  296. }
  297. if ($action == 'confirm_reopen' && GETPOST('confirm') == 'yes')
  298. {
  299. $result = $object->setValid($user);
  300. if ($result <= 0)
  301. {
  302. setEventMessages($object->error, $object->errors, 'errors');
  303. }
  304. }
  305. if ($action == 'confirm_delete' && GETPOST("confirm") == "yes" && $user->rights->projet->supprimer)
  306. {
  307. $object->fetch($id);
  308. $result=$object->delete($user);
  309. if ($result > 0)
  310. {
  311. setEventMessages($langs->trans("RecordDeleted"), null, 'mesgs');
  312. header("Location: index.php");
  313. exit;
  314. }
  315. else
  316. {
  317. dol_syslog($object->error,LOG_DEBUG);
  318. setEventMessages($object->error, $object->errors, 'errors');
  319. }
  320. }
  321. if ($action == 'confirm_clone' && $user->rights->projet->creer && GETPOST('confirm') == 'yes')
  322. {
  323. $clone_contacts=GETPOST('clone_contacts')?1:0;
  324. $clone_tasks=GETPOST('clone_tasks')?1:0;
  325. $clone_project_files = GETPOST('clone_project_files') ? 1 : 0;
  326. $clone_task_files = GETPOST('clone_task_files') ? 1 : 0;
  327. $clone_notes=GETPOST('clone_notes')?1:0;
  328. $move_date=GETPOST('move_date')?1:0;
  329. $result=$object->createFromClone($object->id,$clone_contacts,$clone_tasks,$clone_project_files,$clone_task_files,$clone_notes,$move_date);
  330. if ($result <= 0)
  331. {
  332. setEventMessages($object->error, $object->errors, 'errors');
  333. }
  334. else
  335. {
  336. $object->fetch($result); // Load new object
  337. $action='edit';
  338. $comefromclone=true;
  339. }
  340. }
  341. }
  342. /*
  343. * View
  344. */
  345. $form = new Form($db);
  346. $formfile = new FormFile($db);
  347. $formproject = new FormProjets($db);
  348. $userstatic = new User($db);
  349. $title=$langs->trans("Project").' - '.$object->ref.($object->thirdparty->name?' - '.$object->thirdparty->name:'').($object->title?' - '.$object->title:'');
  350. if (! empty($conf->global->MAIN_HTML_TITLE) && preg_match('/projectnameonly/',$conf->global->MAIN_HTML_TITLE)) $title=$object->ref.($object->thirdparty->name?' - '.$object->thirdparty->name:'').($object->title?' - '.$object->title:'');
  351. $help_url="EN:Module_Projects|FR:Module_Projets|ES:M&oacute;dulo_Proyectos";
  352. llxHeader("",$title,$help_url);
  353. if ($action == 'create' && $user->rights->projet->creer)
  354. {
  355. /*
  356. * Create
  357. */
  358. $thirdparty=new Societe($db);
  359. if ($socid > 0) $thirdparty->fetch($socid);
  360. print load_fiche_titre($langs->trans("NewProject"), '', 'title_project');
  361. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  362. print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
  363. print '<input type="hidden" name="action" value="add">';
  364. print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
  365. dol_fiche_head();
  366. print '<table class="border" width="100%">';
  367. $defaultref='';
  368. $modele = empty($conf->global->PROJECT_ADDON)?'mod_project_simple':$conf->global->PROJECT_ADDON;
  369. // Search template files
  370. $file=''; $classname=''; $filefound=0;
  371. $dirmodels=array_merge(array('/'),(array) $conf->modules_parts['models']);
  372. foreach($dirmodels as $reldir)
  373. {
  374. $file=dol_buildpath($reldir."core/modules/project/".$modele.'.php',0);
  375. if (file_exists($file))
  376. {
  377. $filefound=1;
  378. $classname = $modele;
  379. break;
  380. }
  381. }
  382. if ($filefound)
  383. {
  384. $result=dol_include_once($reldir."core/modules/project/".$modele.'.php');
  385. $modProject = new $classname;
  386. $defaultref = $modProject->getNextValue($thirdparty,$object);
  387. }
  388. if (is_numeric($defaultref) && $defaultref <= 0) $defaultref='';
  389. // Ref
  390. $suggestedref=($_POST["ref"]?$_POST["ref"]:$defaultref);
  391. print '<tr><td class="titlefieldcreate"><span class="fieldrequired">'.$langs->trans("Ref").'</span></td><td><input size="12" type="text" name="ref" value="'.$suggestedref.'">';
  392. print ' '.$form->textwithpicto('', $langs->trans("YouCanCompleteRef", $suggestedref));
  393. print '</td></tr>';
  394. // Label
  395. print '<tr><td><span class="fieldrequired">'.$langs->trans("Label").'</span></td><td><input size="80" type="text" name="title" value="'.GETPOST("title").'"></td></tr>';
  396. // Thirdparty
  397. if ($conf->societe->enabled)
  398. {
  399. print '<tr><td>'.$langs->trans("ThirdParty").'</td><td>';
  400. $filteronlist='';
  401. if (! empty($conf->global->PROJECT_FILTER_FOR_THIRDPARTY_LIST)) $filteronlist=$conf->global->PROJECT_FILTER_FOR_THIRDPARTY_LIST;
  402. $text=$form->select_thirdparty_list(GETPOST('socid','int'), 'socid', $filteronlist, 'SelectThirdParty', 1, 0, array(), '', 0, 0, 'minwidth300');
  403. if (empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS) && empty($conf->dol_use_jmobile))
  404. {
  405. $texthelp=$langs->trans("IfNeedToUseOhterObjectKeepEmpty");
  406. print $form->textwithtooltip($text.' '.img_help(),$texthelp,1);
  407. }
  408. else print $text;
  409. print ' <a href="'.DOL_URL_ROOT.'/societe/soc.php?action=create&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create').'">'.$langs->trans("AddThirdParty").'</a>';
  410. print '</td></tr>';
  411. }
  412. // Status
  413. if ($status != '')
  414. {
  415. print '<tr><td>'.$langs->trans("Status").'</td><td>';
  416. print '<input type="hidden" name="status" value="'.$status.'">';
  417. print $object->LibStatut($status, 4);
  418. print '</td></tr>';
  419. }
  420. // Public
  421. print '<tr><td>'.$langs->trans("Visibility").'</td><td>';
  422. $array=array(0 => $langs->trans("PrivateProject"),1 => $langs->trans("SharedProject"));
  423. print $form->selectarray('public',$array,$object->public);
  424. print '</td></tr>';
  425. // Date start
  426. print '<tr><td>'.$langs->trans("DateStart").'</td><td>';
  427. print $form->select_date(($date_start?$date_start:''),'projectstart',0,0,0,'',1,0,1);
  428. print '</td></tr>';
  429. // Date end
  430. print '<tr><td>'.$langs->trans("DateEnd").'</td><td>';
  431. print $form->select_date(($date_end?$date_end:-1),'projectend',0,0,0,'',1,0,1);
  432. print '</td></tr>';
  433. if (! empty($conf->global->PROJECT_USE_OPPORTUNITIES))
  434. {
  435. // Opportunity status
  436. print '<tr><td>'.$langs->trans("OpportunityStatus").'</td>';
  437. print '<td>';
  438. print $formproject->selectOpportunityStatus('opp_status',$object->opp_status);
  439. print '</tr>';
  440. // Opportunity probability
  441. print '<tr><td>'.$langs->trans("OpportunityProbability").'</td>';
  442. print '<td><input size="5" type="text" id="opp_percent" name="opp_percent" value="'.(GETPOST('opp_percent')!=''?price(GETPOST('opp_percent')):'').'"> %';
  443. print '<input type="hidden" name="opp_percent_not_set" id="opp_percent_not_set" value="'.(GETPOST('opp_percent')!=''?'0':'1').'">';
  444. print '</td>';
  445. print '</tr>';
  446. // Opportunity amount
  447. print '<tr><td>'.$langs->trans("OpportunityAmount").'</td>';
  448. print '<td><input size="5" type="text" name="opp_amount" value="'.(GETPOST('opp_amount')!=''?price(GETPOST('opp_amount')):'').'"></td>';
  449. print '</tr>';
  450. }
  451. // Budget
  452. print '<tr><td>'.$langs->trans("Budget").'</td>';
  453. print '<td><input size="5" type="text" name="budget_amount" value="'.(GETPOST('budget_amount')!=''?price(GETPOST('budget_amount')):'').'"></td>';
  454. print '</tr>';
  455. // Description
  456. print '<tr><td class="tdtop">'.$langs->trans("Description").'</td>';
  457. print '<td>';
  458. print '<textarea name="description" wrap="soft" class="centpercent" rows="'.ROWS_3.'">'.$_POST["description"].'</textarea>';
  459. print '</td></tr>';
  460. // Other options
  461. $parameters=array();
  462. $reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$object,$action); // Note that $action and $object may have been modified by hook
  463. if (empty($reshook) && ! empty($extrafields->attribute_label))
  464. {
  465. print $object->showOptionals($extrafields,'edit');
  466. }
  467. print '</table>';
  468. dol_fiche_end();
  469. print '<div class="center">';
  470. print '<input type="submit" class="button" value="'.$langs->trans("CreateDraft").'">';
  471. if (! empty($backtopage))
  472. {
  473. print ' &nbsp; &nbsp; ';
  474. print '<input type="submit" class="button" name="cancel" value="'.$langs->trans("Cancel").'">';
  475. }
  476. print '</div>';
  477. print '</form>';
  478. // Change probability from status
  479. print '<script type="text/javascript" language="javascript">
  480. jQuery(document).ready(function() {
  481. function change_percent()
  482. {
  483. var element = jQuery("#opp_status option:selected");
  484. var defaultpercent = element.attr("defaultpercent");
  485. /*if (jQuery("#opp_percent_not_set").val() == "") */
  486. jQuery("#opp_percent").val(defaultpercent);
  487. }
  488. /*init_myfunc();*/
  489. jQuery("#opp_status").change(function() {
  490. change_percent();
  491. });
  492. });
  493. </script>';
  494. }
  495. else
  496. {
  497. /*
  498. * Show or edit
  499. */
  500. $res=$object->fetch_optionals($object->id,$extralabels);
  501. // To verify role of users
  502. $userAccess = $object->restrictedProjectArea($user,'read');
  503. $userWrite = $object->restrictedProjectArea($user,'write');
  504. $userDelete = $object->restrictedProjectArea($user,'delete');
  505. //print "userAccess=".$userAccess." userWrite=".$userWrite." userDelete=".$userDelete;
  506. // Confirmation validation
  507. if ($action == 'validate')
  508. {
  509. print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ValidateProject'), $langs->trans('ConfirmValidateProject'), 'confirm_validate','',0,1);
  510. }
  511. // Confirmation close
  512. if ($action == 'close')
  513. {
  514. print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id,$langs->trans("CloseAProject"),$langs->trans("ConfirmCloseAProject"),"confirm_close",'','',1);
  515. }
  516. // Confirmation reopen
  517. if ($action == 'reopen')
  518. {
  519. print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id,$langs->trans("ReOpenAProject"),$langs->trans("ConfirmReOpenAProject"),"confirm_reopen",'','',1);
  520. }
  521. // Confirmation delete
  522. if ($action == 'delete')
  523. {
  524. $text=$langs->trans("ConfirmDeleteAProject");
  525. $task=new Task($db);
  526. $taskarray=$task->getTasksArray(0,0,$object->id,0,0);
  527. $nboftask=count($taskarray);
  528. if ($nboftask) $text.='<br>'.img_warning().' '.$langs->trans("ThisWillAlsoRemoveTasks",$nboftask);
  529. print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id,$langs->trans("DeleteAProject"),$text,"confirm_delete",'','',1);
  530. }
  531. // Clone confirmation
  532. if ($action == 'clone')
  533. {
  534. $formquestion=array(
  535. 'text' => $langs->trans("ConfirmClone"),
  536. array('type' => 'checkbox', 'name' => 'clone_contacts', 'label' => $langs->trans("CloneContacts"), 'value' => true),
  537. array('type' => 'checkbox', 'name' => 'clone_tasks', 'label' => $langs->trans("CloneTasks"), 'value' => true),
  538. array('type' => 'checkbox', 'name' => 'move_date', 'label' => $langs->trans("CloneMoveDate"), 'value' => true),
  539. array('type' => 'checkbox', 'name' => 'clone_notes', 'label' => $langs->trans("CloneNotes"), 'value' => true),
  540. array('type' => 'checkbox', 'name' => 'clone_project_files','label' => $langs->trans("CloneProjectFiles"), 'value' => false),
  541. array('type' => 'checkbox', 'name' => 'clone_task_files', 'label' => $langs->trans("CloneTaskFiles"), 'value' => false)
  542. );
  543. print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id, $langs->trans("CloneProject"), $langs->trans("ConfirmCloneProject"), "confirm_clone", $formquestion, '', 1, 240);
  544. }
  545. print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  546. print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
  547. print '<input type="hidden" name="action" value="update">';
  548. print '<input type="hidden" name="id" value="'.$object->id.'">';
  549. print '<input type="hidden" name="comefromclone" value="'.$comefromclone.'">';
  550. $head=project_prepare_head($object);
  551. dol_fiche_head($head, 'project', $langs->trans("Project"),0,($object->public?'projectpub':'project'));
  552. if ($action == 'edit' && $userWrite > 0)
  553. {
  554. print '<table class="border" width="100%">';
  555. // Ref
  556. $suggestedref=$object->ref;
  557. print '<tr><td class="titlefield fieldrequired">'.$langs->trans("Ref").'</td>';
  558. print '<td><input size="12" name="ref" value="'.$suggestedref.'">';
  559. print ' '.$form->textwithpicto('', $langs->trans("YouCanCompleteRef", $suggestedref));
  560. print '</td></tr>';
  561. // Label
  562. print '<tr><td class="fieldrequired">'.$langs->trans("Label").'</td>';
  563. print '<td><input size="80" name="title" value="'.$object->title.'"></td></tr>';
  564. // Thirdparty
  565. if ($conf->societe->enabled)
  566. {
  567. print '<tr><td>'.$langs->trans("ThirdParty").'</td><td>';
  568. $filteronlist='';
  569. if (! empty($conf->global->PROJECT_FILTER_FOR_THIRDPARTY_LIST)) $filteronlist=$conf->global->PROJECT_FILTER_FOR_THIRDPARTY_LIST;
  570. $text=$form->select_thirdparty_list($object->thirdparty->id, 'socid', $filteronlist, 'SelectThirdParty', 1, 0, array(), '', 0, 0, 'minwidth300');
  571. $texthelp=$langs->trans("IfNeedToUseOhterObjectKeepEmpty");
  572. print $form->textwithtooltip($text.' '.img_help(), $texthelp, 1, 0, '', '', 2);
  573. print '</td></tr>';
  574. }
  575. // Visibility
  576. print '<tr><td>'.$langs->trans("Visibility").'</td><td>';
  577. $array=array(0 => $langs->trans("PrivateProject"),1 => $langs->trans("SharedProject"));
  578. print $form->selectarray('public',$array,$object->public);
  579. print '</td></tr>';
  580. // Status
  581. print '<tr><td>'.$langs->trans("Status").'</td><td>'.$object->getLibStatut(4).'</td></tr>';
  582. // Date start
  583. print '<tr><td>'.$langs->trans("DateStart").'</td><td>';
  584. print $form->select_date($object->date_start?$object->date_start:-1,'projectstart',0,0,0,'',1,0,1);
  585. print ' &nbsp; &nbsp; <input type="checkbox" name="reportdate" value="yes" ';
  586. if ($comefromclone){print ' checked ';}
  587. print '/> '. $langs->trans("ProjectReportDate");
  588. print '</td></tr>';
  589. // Date end
  590. print '<tr><td>'.$langs->trans("DateEnd").'</td><td>';
  591. print $form->select_date($object->date_end?$object->date_end:-1,'projectend',0,0,0,'',1,0,1);
  592. print '</td></tr>';
  593. if (! empty($conf->global->PROJECT_USE_OPPORTUNITIES))
  594. {
  595. // Opportunity status
  596. print '<tr><td>'.$langs->trans("OpportunityStatus").'</td>';
  597. print '<td>';
  598. print $formproject->selectOpportunityStatus('opp_status', $object->opp_status, 1);
  599. print '</td>';
  600. print '</tr>';
  601. // Opportunity probability
  602. print '<tr><td>'.$langs->trans("OpportunityProbability").'</td>';
  603. print '<td><input size="5" type="text" id="opp_percent" name="opp_percent" value="'.(isset($_POST['opp_percent'])?GETPOST('opp_percent'):(strcmp($object->opp_percent,'')?price($object->opp_percent,0,$langs,1,0):'')).'"> %</td>';
  604. print '</tr>';
  605. // Opportunity amount
  606. print '<tr><td>'.$langs->trans("OpportunityAmount").'</td>';
  607. print '<td><input size="5" type="text" name="opp_amount" value="'.(isset($_POST['opp_amount'])?GETPOST('opp_amount'):(strcmp($object->opp_amount,'')?price($object->opp_amount,0,$langs,1,0):'')).'"></td>';
  608. print '</tr>';
  609. }
  610. // Budget
  611. print '<tr><td>'.$langs->trans("Budget").'</td>';
  612. print '<td><input size="5" type="text" name="budget_amount" value="'.(isset($_POST['budget_amount'])?GETPOST('budget_amount'):(strcmp($object->budget_amount,'')?price($object->budget_amount,0,$langs,1,0):'')).'"></td>';
  613. print '</tr>';
  614. // Description
  615. print '<tr><td valign="top">'.$langs->trans("Description").'</td>';
  616. print '<td>';
  617. print '<textarea name="description" wrap="soft" class="centpercent" rows="'.ROWS_3.'">'.$object->description.'</textarea>';
  618. print '</td></tr>';
  619. // Other options
  620. $parameters=array();
  621. $reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$object,$action); // Note that $action and $object may have been modified by hook
  622. if (empty($reshook) && ! empty($extrafields->attribute_label))
  623. {
  624. print $object->showOptionals($extrafields,'edit');
  625. }
  626. print '</table>';
  627. }
  628. else
  629. {
  630. print '<table class="border" width="100%">';
  631. $linkback = '<a href="'.DOL_URL_ROOT.'/projet/list.php">'.$langs->trans("BackToList").'</a>';
  632. // Ref
  633. print '<tr><td class="titlefield">'.$langs->trans("Ref").'</td><td>';
  634. // Define a complementary filter for search of next/prev ref.
  635. if (! $user->rights->projet->all->lire)
  636. {
  637. $objectsListId = $object->getProjectsAuthorizedForUser($user,0,0);
  638. $object->next_prev_filter=" rowid in (".(count($objectsListId)?join(',',array_keys($objectsListId)):'0').")";
  639. }
  640. print $form->showrefnav($object, 'ref', $linkback, 1, 'ref', 'ref');
  641. print '</td></tr>';
  642. // Label
  643. print '<tr><td>'.$langs->trans("Label").'</td><td>'.$object->title.'</td></tr>';
  644. // Third party
  645. print '<tr><td>'.$langs->trans("ThirdParty").'</td><td>';
  646. if ($object->thirdparty->id > 0) print $object->thirdparty->getNomUrl(1, 'project');
  647. else print'&nbsp;';
  648. print '</td></tr>';
  649. // Visibility
  650. print '<tr><td>'.$langs->trans("Visibility").'</td><td>';
  651. if ($object->public) print $langs->trans('SharedProject');
  652. else print $langs->trans('PrivateProject');
  653. print '</td></tr>';
  654. // Statut
  655. print '<tr><td>'.$langs->trans("Status").'</td><td>'.$object->getLibStatut(4).'</td></tr>';
  656. // Date start
  657. print '<tr><td>'.$langs->trans("DateStart").'</td><td>';
  658. print dol_print_date($object->date_start,'day');
  659. print '</td></tr>';
  660. // Date end
  661. print '<tr><td>'.$langs->trans("DateEnd").'</td><td>';
  662. print dol_print_date($object->date_end,'day');
  663. print '</td></tr>';
  664. if (! empty($conf->global->PROJECT_USE_OPPORTUNITIES))
  665. {
  666. // Opportunity status
  667. print '<tr><td>'.$langs->trans("OpportunityStatus").'</td><td>';
  668. $code = dol_getIdFromCode($db, $object->opp_status, 'c_lead_status', 'rowid', 'code');
  669. if ($code) print $langs->trans("OppStatus".$code);
  670. print '</td></tr>';
  671. // Opportunity percent
  672. print '<tr><td>'.$langs->trans("OpportunityProbability").'</td><td>';
  673. if (strcmp($object->opp_percent,'')) print price($object->opp_percent,'',$langs,1,0).' %';
  674. print '</td></tr>';
  675. // Opportunity Amount
  676. print '<tr><td>'.$langs->trans("OpportunityAmount").'</td><td>';
  677. if (strcmp($object->opp_amount,'')) print price($object->opp_amount,'',$langs,1,0,0,$conf->currency);
  678. print '</td></tr>';
  679. }
  680. // Budget
  681. print '<tr><td>'.$langs->trans("Budget").'</td><td>';
  682. if (strcmp($object->budget_amount, '')) print price($object->budget_amount,'',$langs,1,0,0,$conf->currency);
  683. print '</td></tr>';
  684. // Description
  685. print '<td class="tdtop">'.$langs->trans("Description").'</td><td>';
  686. print nl2br($object->description);
  687. print '</td></tr>';
  688. // Other options
  689. $parameters=array();
  690. $reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$object,$action); // Note that $action and $object may have been modified by hook
  691. if (empty($reshook) && ! empty($extrafields->attribute_label))
  692. {
  693. print $object->showOptionals($extrafields);
  694. }
  695. print '</table>';
  696. }
  697. dol_fiche_end();
  698. if ($action == 'edit' && $userWrite > 0)
  699. {
  700. print '<div align="center">';
  701. print '<input name="update" class="button" type="submit" value="'.$langs->trans("Modify").'">&nbsp; &nbsp; &nbsp;';
  702. print '<input type="submit" class="button" name="cancel" value="'.$langs->trans("Cancel").'">';
  703. print '</div>';
  704. }
  705. print '</form>';
  706. // Change probability from status
  707. print '<script type="text/javascript" language="javascript">
  708. jQuery(document).ready(function() {
  709. function change_percent()
  710. {
  711. var element = jQuery("#opp_status option:selected");
  712. var defaultpercent = element.attr("defaultpercent");
  713. /*if (jQuery("#opp_percent_not_set").val() == "") */
  714. jQuery("#opp_percent").val(defaultpercent);
  715. }
  716. /*init_myfunc();*/
  717. jQuery("#opp_status").change(function() {
  718. change_percent();
  719. });
  720. });
  721. </script>';
  722. /*
  723. * Boutons actions
  724. */
  725. print '<div class="tabsAction">';
  726. $parameters = array();
  727. $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been
  728. // modified by hook
  729. if (empty($reshook))
  730. {
  731. if ($action != "edit" )
  732. {
  733. // Modify
  734. if ($object->statut != 2 && $user->rights->projet->creer)
  735. {
  736. if ($userWrite > 0)
  737. {
  738. print '<div class="inline-block divButAction"><a class="butAction" href="card.php?id='.$object->id.'&amp;action=edit">'.$langs->trans("Modify").'</a></div>';
  739. }
  740. else
  741. {
  742. print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="'.$langs->trans("NotOwnerOfProject").'">'.$langs->trans('Modify').'</a></div>';
  743. }
  744. }
  745. // Validate
  746. if ($object->statut == 0 && $user->rights->projet->creer)
  747. {
  748. if ($userWrite > 0)
  749. {
  750. print '<div class="inline-block divButAction"><a class="butAction" href="card.php?id='.$object->id.'&action=validate">'.$langs->trans("Validate").'</a></div>';
  751. }
  752. else
  753. {
  754. print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="'.$langs->trans("NotOwnerOfProject").'">'.$langs->trans('Validate').'</a></div>';
  755. }
  756. }
  757. // Close
  758. if ($object->statut == 1 && $user->rights->projet->creer)
  759. {
  760. if ($userWrite > 0)
  761. {
  762. print '<div class="inline-block divButAction"><a class="butAction" href="card.php?id='.$object->id.'&amp;action=close">'.$langs->trans("Close").'</a></div>';
  763. }
  764. else
  765. {
  766. print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="'.$langs->trans("NotOwnerOfProject").'">'.$langs->trans('Close').'</a></div>';
  767. }
  768. }
  769. // Reopen
  770. if ($object->statut == 2 && $user->rights->projet->creer)
  771. {
  772. if ($userWrite > 0)
  773. {
  774. print '<div class="inline-block divButAction"><a class="butAction" href="card.php?id='.$object->id.'&amp;action=reopen">'.$langs->trans("ReOpen").'</a></div>';
  775. }
  776. else
  777. {
  778. print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="'.$langs->trans("NotOwnerOfProject").'">'.$langs->trans('ReOpen').'</a></div>';
  779. }
  780. }
  781. // Add button to create objects from project
  782. if (! empty($conf->global->PROJECT_SHOW_CREATE_OBJECT_BUTTON))
  783. {
  784. if (! empty($conf->propal->enabled) && $user->rights->propal->creer)
  785. {
  786. $langs->load("propal");
  787. print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/comm/propal/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("AddProp").'</a></div>';
  788. }
  789. if (! empty($conf->commande->enabled) && $user->rights->commande->creer)
  790. {
  791. $langs->load("orders");
  792. print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/commande/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("CreateOrder").'</a></div>';
  793. }
  794. if (! empty($conf->facture->enabled) && $user->rights->facture->creer)
  795. {
  796. $langs->load("bills");
  797. print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/compta/facture.php?action=create&projectid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("CreateBill").'</a></div>';
  798. }
  799. if (! empty($conf->supplier_proposal->enabled) && $user->rights->supplier_proposal->creer)
  800. {
  801. $langs->load("supplier_proposal");
  802. print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/supplier_proposal/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("AddSupplierProposal").'</a></div>';
  803. }
  804. if (! empty($conf->supplier_order->enabled) && $user->rights->fournisseur->commande->creer)
  805. {
  806. $langs->load("suppliers");
  807. print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/fourn/commande/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("AddSupplierOrder").'</a></div>';
  808. }
  809. if (! empty($conf->supplier_invoice->enabled) && $user->rights->fournisseur->facture->creer)
  810. {
  811. $langs->load("suppliers");
  812. print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/fourn/facture/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("AddSupplierInvoice").'</a></div>';
  813. }
  814. if (! empty($conf->ficheinter->enabled) && $user->rights->ficheinter->creer)
  815. {
  816. $langs->load("interventions");
  817. print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/fichinter/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("AddIntervention").'</a></div>';
  818. }
  819. if (! empty($conf->contrat->enabled) && $user->rights->contrat->creer)
  820. {
  821. $langs->load("contracts");
  822. print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/contrat/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("AddContract").'</a></div>';
  823. }
  824. if (! empty($conf->expensereport->enabled) && $user->rights->expensereport->creer)
  825. {
  826. $langs->load("trips");
  827. print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/expensereport/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("AddTrip").'</a></div>';
  828. }
  829. if (! empty($conf->don->enabled) && $user->rights->don->creer)
  830. {
  831. $langs->load("donations");
  832. print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/don/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("AddDonation").'</a></div>';
  833. }
  834. }
  835. // Clone
  836. if ($user->rights->projet->creer)
  837. {
  838. if ($userWrite > 0)
  839. {
  840. print '<div class="inline-block divButAction"><a class="butAction" href="card.php?id='.$object->id.'&action=clone">'.$langs->trans('ToClone').'</a></div>';
  841. }
  842. else
  843. {
  844. print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="'.$langs->trans("NotOwnerOfProject").'">'.$langs->trans('ToClone').'</a></div>';
  845. }
  846. }
  847. // Delete
  848. if ($user->rights->projet->supprimer || ($object->statut == 0 && $user->rights->projet->creer))
  849. {
  850. if ($userDelete > 0 || ($object->statut == 0 && $user->rights->projet->creer))
  851. {
  852. print '<div class="inline-block divButAction"><a class="butActionDelete" href="card.php?id='.$object->id.'&amp;action=delete">'.$langs->trans("Delete").'</a></div>';
  853. }
  854. else
  855. {
  856. print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="'.$langs->trans("NotOwnerOfProject").'">'.$langs->trans('Delete').'</a></div>';
  857. }
  858. }
  859. }
  860. }
  861. print "</div>";
  862. if ($action != 'presend')
  863. {
  864. print '<div class="fichecenter"><div class="fichehalfleft">';
  865. print '<a name="builddoc"></a>'; // ancre
  866. /*
  867. * Documents generes
  868. */
  869. $filename=dol_sanitizeFileName($object->ref);
  870. $filedir=$conf->projet->dir_output . "/" . dol_sanitizeFileName($object->ref);
  871. $urlsource=$_SERVER["PHP_SELF"]."?id=".$object->id;
  872. $genallowed=($user->rights->projet->lire && $userAccess > 0);
  873. $delallowed=($user->rights->projet->creer && $userWrite > 0);
  874. $var=true;
  875. $somethingshown=$formfile->show_documents('project',$filename,$filedir,$urlsource,$genallowed,$delallowed,$object->modelpdf);
  876. print '</div><div class="fichehalfright"><div class="ficheaddleft">';
  877. if (!empty($object->id))
  878. {
  879. // List of actions on element
  880. include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
  881. $formactions=new FormActions($db);
  882. $somethingshown=$formactions->showactions($object,'project',$socid);
  883. }
  884. print '</div></div></div>';
  885. }
  886. // Hook to add more things on page
  887. $parameters=array();
  888. $reshook=$hookmanager->executeHooks('mainCardTabAddMore',$parameters,$object,$action); // Note that $action and $object may have been modified by hook
  889. }
  890. llxFooter();
  891. $db->close();