skill_tab.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. <?php
  2. /* Copyright (C) 2021 grégory Blémand <contact@atm-consulting.fr>
  3. * Copyright (C) 2021 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
  4. * Copyright (C) 2021 Greg Rastklan <greg.rastklan@atm-consulting.fr>
  5. * Copyright (C) 2021 Jean-Pascal BOUDET <jean-pascal.boudet@atm-consulting.fr>
  6. * Copyright (C) 2021 Grégory BLEMAND <gregory.blemand@atm-consulting.fr>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. */
  21. /**
  22. * \file htdocs/hrm/skill_tab.php
  23. * \ingroup hrm
  24. * \brief Page to add/delete/view skill to jobs/users
  25. */
  26. // Load Dolibarr environment
  27. require '../main.inc.php';
  28. require_once DOL_DOCUMENT_ROOT . '/core/class/html.formcompany.class.php';
  29. require_once DOL_DOCUMENT_ROOT . '/core/class/html.formfile.class.php';
  30. require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
  31. require_once DOL_DOCUMENT_ROOT . '/user/class/user.class.php';
  32. require_once DOL_DOCUMENT_ROOT . '/hrm/class/job.class.php';
  33. require_once DOL_DOCUMENT_ROOT . '/hrm/class/skill.class.php';
  34. require_once DOL_DOCUMENT_ROOT . '/hrm/class/skillrank.class.php';
  35. require_once DOL_DOCUMENT_ROOT . '/hrm/lib/hrm_skill.lib.php';
  36. // Load translation files required by the page
  37. $langs->loadLangs(array('hrm', 'other'));
  38. // Get Parameters
  39. $id = GETPOST('id', 'int');
  40. $TSkillsToAdd = GETPOST('fk_skill', 'array');
  41. $objecttype = GETPOST('objecttype', 'alpha');
  42. $TNote = GETPOST('TNote', 'array');
  43. $lineid = GETPOST('lineid', 'int');
  44. $action = GETPOST('action', 'aZ09');
  45. $confirm = GETPOST('confirm', 'alpha');
  46. $cancel = GETPOST('cancel', 'aZ09');
  47. $contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'skillcard'; // To manage different context of search
  48. $backtopage = GETPOST('backtopage', 'alpha');
  49. $backtopageforcancel = GETPOST('backtopageforcancel', 'alpha');
  50. $TAuthorizedObjects = array('job', 'user');
  51. $skill = new SkillRank($db);
  52. // Initialize technical objects
  53. if (in_array($objecttype, $TAuthorizedObjects)) {
  54. if ($objecttype == 'job') {
  55. $object = new Job($db);
  56. } elseif ($objecttype == "user") {
  57. $object = new User($db);
  58. }
  59. } else {
  60. accessforbidden('ErrorBadObjectType');
  61. }
  62. $hookmanager->initHooks(array('skilltab', 'globalcard')); // Note that conf->hooks_modules contains array
  63. // Load object
  64. include DOL_DOCUMENT_ROOT . '/core/actions_fetchobject.inc.php'; // Must be include, not include_once.
  65. // Permissions
  66. $permissiontoread = $user->hasRight('hrm', 'all', 'read');
  67. $permissiontoadd = $user->hasRight('hrm', 'all', 'write'); // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php
  68. // Security check (enable the most restrictive one)
  69. if ($user->socid > 0) accessforbidden();
  70. if (empty($conf->hrm->enabled)) accessforbidden();
  71. if (!$permissiontoread) accessforbidden();
  72. /*
  73. * Actions
  74. */
  75. $parameters = array();
  76. $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
  77. if ($reshook < 0) {
  78. setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
  79. }
  80. if (empty($reshook)) {
  81. $error = 0;
  82. $backurlforlist = DOL_URL_ROOT.'/hrm/skill_list.php';
  83. if (empty($backtopage) || ($cancel && empty($id))) {
  84. if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) {
  85. if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) {
  86. $backtopage = $backurlforlist;
  87. } else {
  88. $backtopage = DOL_URL_ROOT.'/hrm/skill_list.php?id=' . ($id > 0 ? $id : '__ID__');
  89. }
  90. }
  91. }
  92. if ($action == 'addSkill') {
  93. $error = 0;
  94. if (empty($TSkillsToAdd)) {
  95. setEventMessage('ErrNoSkillSelected', 'errors');
  96. $error++;
  97. }
  98. if (!$error) {
  99. foreach ($TSkillsToAdd as $k=>$v) {
  100. $skillAdded = new SkillRank($db);
  101. $skillAdded->fk_skill = $v;
  102. $skillAdded->fk_object = $id;
  103. $skillAdded->objecttype = $objecttype;
  104. $ret = $skillAdded->create($user);
  105. if ($ret < 0) setEventMessages($skillAdded->error, null, 'errors');
  106. //else unset($TSkillsToAdd);
  107. }
  108. if ($ret > 0) setEventMessages($langs->trans("SaveAddSkill"), null);
  109. }
  110. } elseif ($action == 'saveSkill') {
  111. if (!empty($TNote)) {
  112. foreach ($TNote as $skillId => $rank) {
  113. $TSkills = $skill->fetchAll('ASC', 't.rowid', 0, 0, array('customsql' => 'fk_object=' . ((int) $id) . " AND objecttype='" . $db->escape($objecttype) . "' AND fk_skill = " . ((int) $skillId)));
  114. if (is_array($TSkills) && !empty($TSkills)) {
  115. foreach ($TSkills as $tmpObj) {
  116. $tmpObj->rankorder = $rank;
  117. $tmpObj->update($user);
  118. }
  119. }
  120. }
  121. setEventMessages($langs->trans("SaveLevelSkill"), null);
  122. header("Location: " . DOL_URL_ROOT.'/hrm/skill_tab.php?id=' . $id. '&objecttype=job');
  123. exit;
  124. }
  125. } elseif ($action == 'confirm_deleteskill' && $confirm == 'yes') {
  126. $skillToDelete = new SkillRank($db);
  127. $ret = $skillToDelete->fetch($lineid);
  128. setEventMessages($langs->trans("DeleteSkill"), null);
  129. if ($ret > 0) {
  130. $skillToDelete->delete($user);
  131. }
  132. }
  133. }
  134. /*
  135. * View
  136. */
  137. $form = new Form($db);
  138. $formfile = new FormFile($db);
  139. $formproject = new FormProjets($db);
  140. $title = $langs->trans("RequiredSkills");
  141. $help_url = '';
  142. llxHeader('', $title, $help_url);
  143. // Part to show record
  144. if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) {
  145. $res = $object->fetch_optionals();
  146. // view configuration
  147. if ($objecttype == 'job') {
  148. require_once DOL_DOCUMENT_ROOT . '/hrm/lib/hrm_job.lib.php';
  149. $head = jobPrepareHead($object);
  150. $listLink = dol_buildpath('/hrm/job_list.php', 1);
  151. } elseif ($objecttype == "user") {
  152. require_once DOL_DOCUMENT_ROOT . "/core/lib/usergroups.lib.php";
  153. $object->getRights();
  154. $head = user_prepare_head($object);
  155. $listLink = dol_buildpath('/user/list.php', 1);
  156. }
  157. print dol_get_fiche_head($head, 'skill_tab', $langs->trans("Workstation"), -1, $object->picto);
  158. $formconfirm = '';
  159. // Confirmation to delete
  160. /*if ($action == 'delete') {
  161. $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteSkill'), $langs->trans('ConfirmDeleteObject'), 'confirm_delete', '', 0, 1);
  162. }*/
  163. // Confirmation to delete line
  164. if ($action == 'ask_deleteskill') {
  165. $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id . '&objecttype=' . $objecttype . '&lineid=' . $lineid, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_deleteskill', '', 0, 1);
  166. }
  167. // Clone confirmation
  168. /*if ($action == 'clone') {
  169. // Create an array for form
  170. $formquestion = array();
  171. $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneAsk', $object->ref), 'confirm_clone', $formquestion, 'yes', 1);
  172. }*/
  173. // Call Hook formConfirm
  174. $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid);
  175. $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
  176. if (empty($reshook)) {
  177. $formconfirm .= $hookmanager->resPrint;
  178. } elseif ($reshook > 0) {
  179. $formconfirm = $hookmanager->resPrint;
  180. }
  181. // Print form confirm
  182. print $formconfirm;
  183. // Object card
  184. // ------------------------------------------------------------
  185. if ($objecttype == 'job') {
  186. $linkback = '<a href="' . dol_buildpath('/hrm/job_list.php', 1) . '?restore_lastsearch_values=1' . (!empty($socid) ? '&socid=' . $socid : '') . '">' . $langs->trans("BackToList") . '</a>';
  187. $morehtmlref = '<div class="refid">';
  188. $morehtmlref.= $object->label;
  189. $morehtmlref .= '</div>';
  190. dol_banner_tab($object, 'id', $linkback, 1, 'rowid', 'rowid', $morehtmlref);
  191. } else {
  192. $linkback = '<a href="' . $listLink . '?restore_lastsearch_values=1' . (!empty($socid) ? '&socid=' . $socid : '') . '">' . $langs->trans("BackToList") . '</a>';
  193. $morehtmlref = '<a href="'.DOL_URL_ROOT.'/user/vcard.php?id='.$object->id.'&output=file&file='.urlencode(dol_sanitizeFileName($object->getFullName($langs).'.vcf')).'" class="refid" rel="noopener">';
  194. $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"');
  195. $morehtmlref .= '</a>';
  196. $urltovirtualcard = '/user/virtualcard.php?id='.((int) $object->id);
  197. $morehtmlref .= dolButtonToOpenUrlInDialogPopup('publicvirtualcard', $langs->trans("PublicVirtualCardUrl").' - '.$object->getFullName($langs), img_picto($langs->trans("PublicVirtualCardUrl"), 'card', 'class="valignmiddle marginleftonly paddingrightonly"'), $urltovirtualcard, '', 'nohover');
  198. dol_banner_tab($object, 'id', $linkback, 1, 'rowid', 'rowid', $morehtmlref, '&objecttype='.$objecttype);
  199. }
  200. // Get all available skills
  201. $static_skill = new Skill($db);
  202. $TAllSkills = $static_skill->fetchAll();
  203. // Array format for multiselectarray function
  204. $TAllSkillsFormatted=array();
  205. if (!empty($TAllSkills)) {
  206. foreach ($TAllSkills as $k=>$v) {
  207. $TAllSkillsFormatted[$k] = $v->label;
  208. }
  209. }
  210. // table of skillRank linked to current object
  211. $TSkillsJob = $skill->fetchAll('ASC', 't.rowid', 0, 0, array('customsql' => 'fk_object=' . ((int) $id) . " AND objecttype='" . $db->escape($objecttype) . "'"));
  212. $TAlreadyUsedSkill = array();
  213. if (is_array($TSkillsJob) && !empty($TSkillsJob)) {
  214. foreach ($TSkillsJob as $skillElement) {
  215. $TAlreadyUsedSkill[$skillElement->fk_skill] = $skillElement->fk_skill;
  216. }
  217. }
  218. print '<div class="fichecenter">';
  219. print '<div class="fichehalfleft">';
  220. print '<div class="underbanner clearboth"></div>';
  221. print '<table class="border centpercent tableforfield">'."\n";
  222. if ($objecttype == 'job') {
  223. // Common attributes
  224. //$keyforbreak='fieldkeytoswitchonsecondcolumn'; // We change column just before this field
  225. //unset($object->fields['fk_project']); // Hide field already shown in banner
  226. //unset($object->fields['fk_soc']); // Hide field already shown in banner
  227. $object->fields['label']['visible']=0; // Already in banner
  228. include DOL_DOCUMENT_ROOT . '/core/tpl/commonfields_view.tpl.php';
  229. // Other attributes. Fields from hook formObjectOptions and Extrafields.
  230. include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php';
  231. } else {
  232. // Login
  233. print '<tr><td class="titlefield">'.$langs->trans("Login").'</td>';
  234. if (!empty($object->ldap_sid) && $object->statut == 0) {
  235. print '<td class="error">';
  236. print $langs->trans("LoginAccountDisableInDolibarr");
  237. print '</td>';
  238. } else {
  239. print '<td>';
  240. $addadmin = '';
  241. if (property_exists($object, 'admin')) {
  242. if (isModEnabled('multicompany') && !empty($object->admin) && empty($object->entity)) {
  243. $addadmin .= img_picto($langs->trans("SuperAdministratorDesc"), "redstar", 'class="paddingleft"');
  244. } elseif (!empty($object->admin)) {
  245. $addadmin .= img_picto($langs->trans("AdministratorDesc"), "star", 'class="paddingleft"');
  246. }
  247. }
  248. print showValueWithClipboardCPButton(!empty($object->login) ? $object->login : '').$addadmin;
  249. print '</td>';
  250. }
  251. print '</tr>'."\n";
  252. $object->fields['label']['visible']=0; // Already in banner
  253. $object->fields['firstname']['visible']=0; // Already in banner
  254. $object->fields['lastname']['visible']=0; // Already in banner
  255. //include DOL_DOCUMENT_ROOT . '/core/tpl/commonfields_view.tpl.php';
  256. // Ref employee
  257. print '<tr><td class="titlefield">'.$langs->trans("RefEmployee").'</td>';
  258. print '<td class="error">';
  259. print showValueWithClipboardCPButton(!empty($object->ref_employee) ? $object->ref_employee : '');
  260. print '</td>';
  261. print '</tr>'."\n";
  262. // National Registration Number
  263. print '<tr><td class="titlefield">'.$langs->trans("NationalRegistrationNumber").'</td>';
  264. print '<td class="error">';
  265. print showValueWithClipboardCPButton(!empty($object->national_registration_number) ? $object->national_registration_number : '');
  266. print '</td>';
  267. print '</tr>'."\n";
  268. }
  269. print '</table>';
  270. print '</div>';
  271. print '</div>';
  272. print '<div class="clearboth"></div><br>';
  273. if ($objecttype != 'user' && $permissiontoadd) {
  274. // form pour ajouter des compétences
  275. print '<form name="addSkill" method="post" action="' . $_SERVER['PHP_SELF'] . '">';
  276. print '<input type="hidden" name="objecttype" value="' . $objecttype . '">';
  277. print '<input type="hidden" name="id" value="' . $id . '">';
  278. print '<input type="hidden" name="action" value="addSkill">';
  279. print '<input type="hidden" name="token" value="'.newToken().'">';
  280. print '<div class="div-table-responsive-no-min">';
  281. print '<table id="tablelines" class="noborder noshadow" width="100%">';
  282. print '<tr><td style="width:90%">' . $langs->trans('AddSkill') . '</td><td style="width:10%"></td></tr>';
  283. print '<tr>';
  284. print '<td>';
  285. print img_picto('', 'shapes', 'class="pictofixedwidth"');
  286. print $form->multiselectarray('fk_skill', array_diff_key($TAllSkillsFormatted, $TAlreadyUsedSkill), array(), 0, 0, 'widthcentpercentminusx') . '</td>';
  287. print '<td><input class="button reposition" type="submit" value="' . $langs->trans('Add') . '"></td>';
  288. print '</tr>';
  289. print '</table>';
  290. print '</div>';
  291. print '</form>';
  292. }
  293. print '<br>';
  294. print '<div class="clearboth"></div>';
  295. if ($objecttype != 'user' && $permissiontoadd) {
  296. print '<form name="saveSkill" method="post" action="' . $_SERVER['PHP_SELF'] . '">';
  297. print '<input type="hidden" name="objecttype" value="' . $objecttype . '">';
  298. print '<input type="hidden" name="id" value="' . $id . '">';
  299. print '<input type="hidden" name="token" value="'.newToken().'">';
  300. print '<input type="hidden" name="action" value="saveSkill">';
  301. }
  302. print '<div class="div-table-responsive-no-min">';
  303. print '<table id="tablelines" class="noborder centpercent" width="100%">';
  304. print '<tr class="liste_titre">';
  305. print '<th>'.$langs->trans('SkillType').'</th>';
  306. print '<th>'.$langs->trans('Label').'</th>';
  307. print '<th>'.$langs->trans('Description').'</th>';
  308. print '<th>'.$langs->trans($objecttype === 'job' ? 'RequiredRank' : 'EmployeeRank').'</th>';
  309. if ($objecttype === 'job') {
  310. print '<th class="linecoledit"></th>';
  311. print '<th class="linecoldelete"></th>';
  312. }
  313. print '</tr>';
  314. if (!is_array($TSkillsJob) || empty($TSkillsJob)) {
  315. print '<tr><td><span class="opacitymedium">' . $langs->trans("NoRecordFound") . '</span></td></tr>';
  316. } else {
  317. $sk = new Skill($db);
  318. foreach ($TSkillsJob as $skillElement) {
  319. $sk->fetch($skillElement->fk_skill);
  320. print '<tr>';
  321. print '<td>';
  322. print Skill::typeCodeToLabel($sk->skill_type);
  323. print '</td><td class="linecolfk_skill">';
  324. print $sk->getNomUrl(1);
  325. print '</td>';
  326. print '<td>';
  327. print $sk->description;
  328. print '</td><td class="linecolrank">';
  329. print displayRankInfos($skillElement->rankorder, $skillElement->fk_skill, 'TNote', $objecttype == 'job' && $permissiontoadd ? 'edit' : 'view');
  330. print '</td>';
  331. if ($objecttype != 'user' && $permissiontoadd) {
  332. print '<td class="linecoledit"></td>';
  333. print '<td class="linecoldelete">';
  334. print '<a class="reposition" href="' . $_SERVER["PHP_SELF"] . '?id=' . $skillElement->fk_object . '&amp;objecttype=' . $objecttype . '&amp;action=ask_deleteskill&amp;lineid=' . $skillElement->id . '">';
  335. print img_delete();
  336. print '</a>';
  337. }
  338. print '</td>';
  339. print '</tr>';
  340. }
  341. }
  342. print '</table>';
  343. if ($objecttype != 'user' && $permissiontoadd) print '<td><input class="button pull-right" type="submit" value="' . $langs->trans('SaveRank') . '"></td>';
  344. print '</div>';
  345. if ($objecttype != 'user' && $permissiontoadd) print '</form>';
  346. // liste des compétences liées
  347. print dol_get_fiche_end();
  348. llxFooter();
  349. }