dolibarr 25.0.0-alpha
job.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2017 Laurent Destailleur <eldy@users.sourceforge.net>
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 * Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
8 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 */
23
30// Put here all includes required by your class file
31require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
32
33
37class Job extends CommonObject
38{
42 public $module = 'hrm';
43
47 public $element = 'job';
48
52 public $table_element = 'hrm_job';
53
57 public $picto = 'technic';
58
59
60 const STATUS_DRAFT = 0;
61 const STATUS_VALIDATED = 1;
62 const STATUS_CANCELED = 9;
63
64
91 // BEGIN MODULEBUILDER PROPERTIES
95 public $fields = array(
96 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'css' => 'left', 'comment' => "Id"),
97 'label' => array('type' => 'varchar(128)', 'label' => 'Label', 'enabled' => 1, 'position' => 20, 'notnull' => 1, 'visible' => 1, 'index' => 1, 'searchall' => 1, 'showoncombobox' => 1, 'comment' => "Label of object"),
98 'description' => array('type' => 'text', 'label' => 'Description', 'enabled' => 1, 'position' => 21, 'notnull' => 0, 'visible' => 1,),
99 'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'position' => 500, 'notnull' => 1, 'visible' => -2,),
100 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'position' => 501, 'notnull' => 0, 'visible' => -2,),
101 'deplacement' => array('type' => 'select', 'required' => 1,'label' => 'NeedBusinessTravels', 'enabled' => 1, 'position' => 90, 'notnull' => 1, 'visible' => 1, 'arrayofkeyval' => array(0 => "No", 1 => "Yes"), 'default' => '0'),
102 'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'position' => 70, 'notnull' => 0, 'visible' => 0,),
103 'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'position' => 71, 'notnull' => 0, 'visible' => 0,),
104 'fk_user_creat' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserAuthor', 'enabled' => 1, 'position' => 510, 'notnull' => 1, 'visible' => -2, 'foreignkey' => 'user.rowid',),
105 'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'position' => 511, 'notnull' => -1, 'visible' => -2,),
106 );
110 public $rowid;
114 public $ref;
118 public $label;
122 public $description;
126 public $deplacement;
130 public $fk_user_creat;
134 public $fk_user_modif;
135 // END MODULEBUILDER PROPERTIES
136
137
141 public $fk_element = 'fk_job';
142
146 protected $childtables = array(
147 'hrm_evaluation' => ['name' => 'Evaluation'],
148 'hrm_job_user' => ['name' => 'Job'],
149 );
150
156 protected $childtablesoncascade = array("@SkillRank:hrm/class/skillrank.class.php:fk_object:(objecttype:=:'job')");
157
158 // /**
159 // * @var JobLine[] Array of subtable lines
160 // */
161 // public $lines = array();
162
163
164
170 public function __construct(DoliDB $db)
171 {
172 global $conf, $langs;
173
174 $this->db = $db;
175
176 $this->ismultientitymanaged = 0;
177 $this->isextrafieldmanaged = 1;
178
179 if (!getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid'])) {
180 $this->fields['rowid']['visible'] = 0;
181 }
182 if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
183 $this->fields['entity']['enabled'] = 0;
184 }
185
186 // Example to show how to set values of fields definition dynamically
187 /*if ($user->rights->hrm->job->read) {
188 $this->fields['myfield']['visible'] = 1;
189 $this->fields['myfield']['noteditable'] = 0;
190 }*/
191
192 // Unset fields that are disabled
193 foreach ($this->fields as $key => $val) {
194 if (isset($val['enabled']) && empty($val['enabled'])) {
195 unset($this->fields[$key]);
196 }
197 }
198
199 // Translate some data of arrayofkeyval
200 if (is_object($langs)) {
201 foreach ($this->fields as $key => $val) {
202 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
203 foreach ($val['arrayofkeyval'] as $key2 => $val2) {
204 $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
205 }
206 }
207 }
208 }
209 }
210
218 public function create(User $user, $notrigger = 0)
219 {
220 $resultcreate = $this->createCommon($user, $notrigger);
221
222 //$resultvalidate = $this->validate($user, $notrigger);
223
224 return $resultcreate;
225 }
226
234 public function createFromClone(User $user, $fromid)
235 {
236 global $langs, $extrafields;
237 $error = 0;
238
239 dol_syslog(__METHOD__, LOG_DEBUG);
240
241 $object = new self($this->db);
242
243 $this->db->begin();
244
245 // Load source object
246 $result = $object->fetchCommon($fromid);
247
248 // Reset some properties
249 unset($object->id);
250 unset($object->fk_user_creat);
251 unset($object->import_key);
252
253 // Clear fields
254 $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default'];
255 $object->label = $langs->trans("CopyOf")." ".$object->label;
256 $object->date_creation = dol_now();
257 $object->date_modification = null;
258
259 // Clear extrafields that are unique
260 if (is_array($object->array_options) && count($object->array_options) > 0) {
261 $extrafields->fetch_name_optionals_label($this->table_element);
262 foreach ($object->array_options as $key => $option) {
263 $shortkey = preg_replace('/options_/', '', $key);
264 if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
265 unset($object->array_options[$key]);
266 }
267 }
268 }
269
270 // Create clone
271 $object->context['createfromclone'] = 'createfromclone';
272 $result = $object->createCommon($user);
273 if ($result < 0) {
274 $error++;
276 }
277
278 if (!$error) {
279 // copy internal contacts
280 if ($this->copy_linked_contact($object, 'internal') < 0) {
281 $error++;
282 }
283 }
284
285 if (!$error) {
286 // copy external contacts if same company
287 if (property_exists($this, 'fk_soc') && $this->fk_soc == $object->socid) {
288 if ($this->copy_linked_contact($object, 'external') < 0) {
289 $error++;
290 }
291 }
292 }
293
294 unset($object->context['createfromclone']);
295
296 // End
297 if (!$error) {
298 $this->db->commit();
299 return $object;
300 } else {
301 $this->db->rollback();
302 return -1;
303 }
304 }
305
313 public function fetch($id, $ref = null)
314 {
315 $result = $this->fetchCommon($id, $ref);
316
317 return $result;
318 }
319
325 public function fetchLines()
326 {
327 $this->lines = array();
328
329 $result = $this->fetchLinesCommon();
330 return $result;
331 }
332
333
346 public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND')
347 {
348 dol_syslog(__METHOD__, LOG_DEBUG);
349
350 $records = array();
351
352 $sql = 'SELECT ';
353 $sql .= $this->getFieldList('t');
354 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
355 if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
356 $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')';
357 } else {
358 $sql .= ' WHERE 1 = 1';
359 }
360
361 // Manage filter
362 $errormessage = '';
363 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
364 if ($errormessage) {
365 $this->errors[] = $errormessage;
366 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
367 return -1;
368 }
369
370 if (!empty($sortfield)) {
371 $sql .= $this->db->order($sortfield, $sortorder);
372 }
373 if (!empty($limit)) {
374 $sql .= ' '.$this->db->plimit($limit, $offset);
375 }
376
377 $resql = $this->db->query($sql);
378 if ($resql) {
379 $num = $this->db->num_rows($resql);
380 $i = 0;
381 while ($i < ($limit ? min($limit, $num) : $num)) {
382 $obj = $this->db->fetch_object($resql);
383
384 $record = new self($this->db);
385 $record->setVarsFromFetchObj($obj);
386
387 $records[$record->id] = $record;
388
389 $i++;
390 }
391 $this->db->free($resql);
392
393 return $records;
394 } else {
395 $this->errors[] = 'Error '.$this->db->lasterror();
396 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
397
398 return -1;
399 }
400 }
401
409 public function update(User $user, $notrigger = 0)
410 {
411 return $this->updateCommon($user, $notrigger);
412 }
413
421 public function delete(User $user, $notrigger = 0)
422 {
423 return $this->deleteCommon($user, $notrigger);
424 //return $this->deleteCommon($user, $notrigger, 1);
425 }
426
435 public function deleteLine(User $user, $idline, $notrigger = 0)
436 {
437 if ($this->status < 0) {
438 $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
439 return -2;
440 }
441
442 return $this->deleteLineCommon($user, $idline, $notrigger);
443 }
444
445
453 public function validate($user, $notrigger = 0)
454 {
455 global $conf, $langs;
456
457 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
458
459 $error = 0;
460
461 // Protection
462 if ($this->status == self::STATUS_VALIDATED) {
463 dol_syslog(get_class($this)."::validate action abandoned: already validated", LOG_WARNING);
464 return 0;
465 }
466
467 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->hrm->job->write))
468 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->hrm->job->job_advance->validate))))
469 {
470 $this->error='NotEnoughPermissions';
471 dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
472 return -1;
473 }*/
474
475 $now = dol_now();
476
477 $this->db->begin();
478
479 // Define new ref
480 if (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref)) { // empty should not happened, but when it occurs, the test save life
481 $num = $this->getNextNumRef();
482 } else {
483 $num = (string) $this->ref;
484 }
485 $this->newref = $num;
486
487 if (!empty($num)) {
488 // Validate
489 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
490 $sql .= " SET ref = '".$this->db->escape($num)."',";
491 $sql .= " status = ".self::STATUS_VALIDATED;
492 if (!empty($this->fields['date_validation'])) {
493 $sql .= ", date_validation = '".$this->db->idate($now)."'";
494 }
495 if (!empty($this->fields['fk_user_valid'])) { // @phan-suppress-current-line PhanTypeMismatchProperty
496 $sql .= ", fk_user_valid = ".((int) $user->id);
497 }
498 $sql .= " WHERE rowid = ".((int) $this->id);
499
500 dol_syslog(get_class($this)."::validate()", LOG_DEBUG);
501 $resql = $this->db->query($sql);
502 if (!$resql) {
503 dol_print_error($this->db);
504 $this->error = $this->db->lasterror();
505 $error++;
506 }
507
508 if (!$error && !$notrigger) {
509 // Call trigger
510 $result = $this->call_trigger('HRM_JOB_VALIDATE', $user);
511 if ($result < 0) {
512 $error++;
513 }
514 // End call triggers
515 }
516 }
517
518 if (!$error) {
519 $this->oldref = $this->ref;
520
521 // Rename directory if dir was a temporary ref
522 if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
523 // Now we rename also files into index
524 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'job/".$this->db->escape($this->newref)."'";
525 $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'job/".$this->db->escape($this->ref)."' and entity = ".((int) $conf->entity);
526 $resql = $this->db->query($sql);
527 if (!$resql) {
528 $error++;
529 $this->error = $this->db->lasterror();
530 }
531 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'job/".$this->db->escape($this->newref)."'";
532 $sql .= " WHERE filepath = 'job/".$this->db->escape($this->ref)."' and entity = ".((int) $conf->entity);
533 $resql = $this->db->query($sql);
534 if (!$resql) {
535 $error++;
536 $this->error = $this->db->lasterror();
537 }
538
539 // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
540 $oldref = dol_sanitizeFileName($this->ref);
541 $newref = dol_sanitizeFileName($num);
542 $dirsource = $conf->hrm->dir_output.'/job/'.$oldref;
543 $dirdest = $conf->hrm->dir_output.'/job/'.$newref;
544 if (!$error && file_exists($dirsource)) {
545 dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
546
547 if (@rename($dirsource, $dirdest)) {
548 dol_syslog("Rename ok");
549 // Rename docs starting with $oldref with $newref
550 $listoffiles = dol_dir_list($conf->hrm->dir_output.'/job/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
551 foreach ($listoffiles as $fileentry) {
552 $dirsource = $fileentry['name'];
553 $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
554 $dirsource = $fileentry['path'].'/'.$dirsource;
555 $dirdest = $fileentry['path'].'/'.$dirdest;
556 @rename($dirsource, $dirdest);
557 }
558 }
559 }
560 }
561 }
562
563 // Set new ref and current status
564 if (!$error) {
565 $this->ref = $num;
566 $this->status = self::STATUS_VALIDATED;
567 }
568
569 if (!$error) {
570 $this->db->commit();
571 return 1;
572 } else {
573 $this->db->rollback();
574 return -1;
575 }
576 }
577
584 public function getLastJobForUser($fk_user)
585 {
586 $Tab = $this->getForUser($fk_user);
587
588 if (empty($Tab)) {
589 return '';
590 }
591
592 $lastpos = array_shift($Tab);
593
594 return $lastpos;
595 }
596
603 public function getForUser($userid)
604 {
605 global $db;
606
607 $TReturn = array();
608 $position = new Position($db);
609 $TPosition = $position->getForUser($userid);
610 foreach ($TPosition as $UPosition) {
611 $tmpjob = new Job($db);
612 if ($tmpjob->fetch($UPosition->fk_job) > 0) {
613 $TReturn[$tmpjob->id] = $tmpjob->label;
614 }
615 }
616 return $TReturn;
617 }
618
626 public function setDraft($user, $notrigger = 0)
627 {
628 // Protection
629 if ($this->status <= self::STATUS_DRAFT) {
630 return 0;
631 }
632
633 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->hrm->write))
634 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->hrm->hrm_advance->validate))))
635 {
636 $this->error='Permission denied';
637 return -1;
638 }*/
639
640 return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'JOB_UNVALIDATE');
641 }
642
650 public function cancel($user, $notrigger = 0)
651 {
652 // Protection
653 if ($this->status != self::STATUS_VALIDATED) {
654 return 0;
655 }
656
657 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->hrm->write))
658 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->hrm->hrm_advance->validate))))
659 {
660 $this->error='Permission denied';
661 return -1;
662 }*/
663
664 return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'JOB_CANCEL');
665 }
666
674 public function reopen($user, $notrigger = 0)
675 {
676 // Protection
677 if ($this->status != self::STATUS_CANCELED) {
678 return 0;
679 }
680
681 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->hrm->write))
682 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->hrm->hrm_advance->validate))))
683 {
684 $this->error='Permission denied';
685 return -1;
686 }*/
687
688 return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'JOB_REOPEN');
689 }
690
701 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
702 {
703 global $conf, $langs, $hookmanager;
704
705 if (!empty($conf->dol_no_mouse_hover)) {
706 $notooltip = 1; // Force disable tooltips
707 }
708
709 $result = '';
710
711 $label = img_picto('', $this->picto).' <u>'.$langs->trans("JobProfile").'</u>';
712 if (isset($this->status)) {
713 $label .= ' '.$this->getLibStatut(5);
714 }
715 $label .= '<br>';
716 $label .= '<b>'.$langs->trans('Label').':</b> '.$this->label;
717
718 $url = dol_buildpath('/hrm/job_card.php', 1).'?id='.$this->id;
719
720 if ($option != 'nolink') {
721 // Add param to save lastsearch_values or not
722 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
723 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
724 $add_save_lastsearch_values = 1;
725 }
726 if ($add_save_lastsearch_values) {
727 $url .= '&save_lastsearch_values=1';
728 }
729 }
730
731 $linkclose = '';
732 if (empty($notooltip)) {
733 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
734 $label = $langs->trans("ShowJob");
735 $linkclose .= ' alt="'.dolPrintHTMLForAttribute($label).'"';
736 }
737 $linkclose .= ' title="'.dolPrintHTMLForAttribute($label).'"';
738 $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
739 } else {
740 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
741 }
742
743 if ($option == 'nolink') {
744 $linkstart = '<span';
745 } else {
746 $linkstart = '<a href="'.$url.'"';
747 }
748 $linkstart .= $linkclose.'>';
749 if ($option == 'nolink') {
750 $linkend = '</span>';
751 } else {
752 $linkend = '</a>';
753 }
754
755 $result .= $linkstart;
756
757 if (empty($this->showphoto_on_popup)) {
758 if ($withpicto) {
759 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
760 }
761 } else {
762 if ($withpicto) {
763 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
764
765 list($class, $module) = explode('@', $this->picto);
766 $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->label);
767 $filearray = dol_dir_list($upload_dir, "files");
768 $filename = $filearray[0]['name'];
769 if (!empty($filename)) {
770 $pospoint = strpos($filearray[0]['name'], '.');
771
772 $pathtophoto = $class.'/'.$this->label.'/thumbs/'.dol_substr($filename, 0, $pospoint).'_mini'.dol_substr($filename, $pospoint);
773 if (!getDolGlobalString(strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS')) {
774 $result .= '<div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref"><img class="photo'.$module.'" alt="No photo" border="0" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart='.$module.'&entity='.$conf->entity.'&file='.urlencode($pathtophoto).'"></div></div>';
775 } else {
776 $result .= '<div class="floatleft inline-block valignmiddle divphotoref"><img class="photouserphoto userphoto" alt="No photo" border="0" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart='.$module.'&entity='.$conf->entity.'&file='.urlencode($pathtophoto).'"></div>';
777 }
778
779 $result .= '</div>';
780 } else {
781 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
782 }
783 }
784 }
785
786 if ($withpicto != 2) {
787 $result .= $this->label;
788 }
789
790 $result .= $linkend;
791 //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
792
793 global $action, $hookmanager;
794 $hookmanager->initHooks(array('jobdao'));
795 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
796 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
797 if ($reshook > 0) {
798 $result = $hookmanager->resPrint;
799 } else {
800 $result .= $hookmanager->resPrint;
801 }
802
803 return $result;
804 }
805
812 public function getLibStatut($mode = 0)
813 {
814 return $this->LibStatut($this->status, $mode);
815 }
816
817 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
825 public function LibStatut($status, $mode = 0)
826 {
827 // phpcs:enable
828
829 return ''; // There is no status on job profile for the moment
830 }
831
838 public function info($id)
839 {
840 $sql = 'SELECT rowid, date_creation as datec, tms as datem,';
841 $sql .= ' fk_user_creat, fk_user_modif';
842 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
843 $sql .= ' WHERE t.rowid = '.((int) $id);
844 $result = $this->db->query($sql);
845 if ($result) {
846 if ($this->db->num_rows($result)) {
847 $obj = $this->db->fetch_object($result);
848
849 $this->id = $obj->rowid;
850
851 $this->user_creation_id = $obj->fk_user_creat;
852 $this->user_modification_id = $obj->fk_user_modif;
853 $this->date_creation = $this->db->jdate($obj->datec);
854 $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
855 }
856
857 $this->db->free($result);
858 } else {
859 dol_print_error($this->db);
860 }
861 }
862
869 public function initAsSpecimen()
870 {
871 // Set here init that are not commonf fields
872 // $this->property1 = ...
873 // $this->property2 = ...
874
875 return $this->initAsSpecimenCommon();
876 }
877
883 public function getLinesArray()
884 {
885 $this->lines = array();
886
887 $objectline = new JobLine($this->db);
888 $result = $objectline->fetchAll('ASC', 'position', 0, 0, '(fk_job:=:'.((int) $this->id).')');
889
890 if (is_numeric($result)) {
891 $this->setErrorsFromObject($objectline);
892 return $result;
893 } else {
894 $this->lines = $result;
895 return $this->lines;
896 }
897 }
898
904 public function getNextNumRef()
905 {
906 global $langs, $conf;
907 $langs->load("hrm");
908
909 if (!getDolGlobalString('hrm_JOB_ADDON')) {
910 $conf->global->hrm_JOB_ADDON = 'mod_job_standard';
911 }
912
913 if (getDolGlobalString('hrm_JOB_ADDON')) {
914 $mybool = false;
915
916 $file = getDolGlobalString('hrm_JOB_ADDON') . ".php";
917 $classname = getDolGlobalString('hrm_JOB_ADDON');
918
919 // Include file with class
920 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
921 foreach ($dirmodels as $reldir) {
922 $dir = dol_buildpath($reldir."core/modules/hrm/");
923
924 // Load file with numbering class (if found)
925 $mybool = ((bool) @include_once $dir.$file) || $mybool;
926 }
927
928 if (!$mybool) {
929 dol_print_error(null, "Failed to include file ".$file);
930 return '';
931 }
932
933 if (class_exists($classname)) {
934 $obj = new $classname();
935 '@phan-var-force ModeleNumRefEvaluation $obj';
937 $numref = $obj->getNextValue($this);
938
939 if ($numref != '' && $numref != '-1') {
940 return $numref;
941 } else {
942 $this->error = $obj->error;
943 //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
944 return "";
945 }
946 } else {
947 print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname;
948 return "";
949 }
950 } else {
951 print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
952 return "";
953 }
954 }
955
967 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
968 {
969 global $conf, $langs;
970
971 $result = 0;
972
973 $langs->load("hrm");
974
975 if (!dol_strlen($modele)) {
976 $modele = 'standard_job';
977
978 if (!empty($this->model_pdf)) {
979 $modele = $this->model_pdf;
980 } elseif (getDolGlobalString('JOB_ADDON_PDF')) {
981 $modele = getDolGlobalString('JOB_ADDON_PDF');
982 }
983 }
984
985 $modelpath = "core/modules/hrm/doc/";
986
987 if (!empty($modele)) {
988 $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
989 }
990
991 return $result;
992 }
993
1001 public function getKanbanView($option = '', $arraydata = null)
1002 {
1003 global $selected, $langs;
1004
1005 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
1006
1007 $return = '<div class="box-flex-item box-flex-grow-zero">';
1008 $return .= '<div class="info-box info-box-sm">';
1009 $return .= '<span class="info-box-icon bg-infobox-action">';
1010 $return .= img_picto('', $this->picto);
1011 $return .= '</span>';
1012 $return .= '<div class="info-box-content">';
1013 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . $this->getNomUrl(0) . '</span>';
1014 if ($selected >= 0) {
1015 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
1016 }
1017 /*if (property_exists($this, 'deplacement')) {
1018 $return .= '<br><span class="opacitymedium">'.$langs->trans("Type").'</span>';
1019 $return .= ' : <span class="info-box-label ">'.$this->fields['deplacement']['arrayofkeyval'][$this->deplacement].'</span>';
1020 }*/
1021 if (empty($this->description)) {
1022 //$return .= '<br><span class="info-box-label opacitymedium">'.$langs->trans("Description").'</span> : ';
1023 $return .= '<br><span class="info-box-label ">' . dol_trunc($this->description, 25) . '</span>';
1024 }
1025 $return .= '</div>';
1026 $return .= '</div>';
1027 $return .= '</div>';
1028 return $return;
1029 }
1030
1036 public function getSkillRankForJob($id)
1037 {
1038 if (empty($id)) {
1039 return -1;
1040 }
1041 $skillranks = array();
1042 $sql = "SELECT rowid";
1043 $sql .= " FROM ".MAIN_DB_PREFIX."hrm_skillrank";
1044 $sql .= " WHERE fk_object = ".((int) $id);
1045
1046 $resql = $this->db->query($sql);
1047 if ($resql) {
1048 $num = $this->db->num_rows($resql);
1049 $i = 0;
1050 while ($i < $num) {
1051 $obj = $this->db->fetch_object($resql);
1052 $skillranks[] = $obj->rowid;
1053 $i++;
1054 }
1055 $this->db->free($resql);
1056 } else {
1057 dol_print_error($this->db);
1058 }
1059 return $skillranks;
1060 }
1061}
1062
1063
1064require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
1065
1070{
1071 // To complete with content of an object JobLine
1072 // We should have a field rowid, fk_job and position
1073
1079 public function __construct(DoliDB $db)
1080 {
1081 $this->db = $db;
1082
1083 $this->isextrafieldmanaged = 0;
1084 }
1085}
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
$object ref
Definition info.php:90
deleteLineCommon(User $user, $idline, $notrigger=0)
Delete a line of object in database.
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
setErrorsFromObject($object)
setErrorsFromObject
createCommon(User $user, $notrigger=0)
Create object in the database.
getFieldList($alias='', $excludefields=array())
Function to concat keys of fields.
updateCommon(User $user, $notrigger=0)
Update object into database.
setStatusCommon($user, $status, $notrigger=0, $triggercode='')
Set to a status.
initAsSpecimenCommon()
Initialise object with example values Id must be 0 if object instance is a specimen.
copy_linked_contact($objFrom, $source='internal')
Copy contact from one element to current.
fetchLinesCommon($morewhere='', $noextrafields=0)
Load object in memory from the database.
fetchCommon($id, $ref=null, $morewhere='', $noextrafields=0)
Load object in memory from the database.
deleteCommon(User $user, $notrigger=0, $forcechilddeletion=0)
Delete object in database.
Parent class for class inheritance lines of business objects This class is useless for the moment so ...
Class to manage Dolibarr database access.
Class for Job.
Definition job.class.php:38
getLastJobForUser($fk_user)
Get the last job occupied by a user.
fetchLines()
Load object lines in memory from the database.
cancel($user, $notrigger=0)
Set cancel status.
__construct(DoliDB $db)
Constructor.
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
Create a document onto disk according to template module.
setDraft($user, $notrigger=0)
Set draft status.
update(User $user, $notrigger=0)
Update object into database.
validate($user, $notrigger=0)
Validate object.
getLibStatut($mode=0)
Return the label of the status.
getLinesArray()
Create an array of lines.
fetch($id, $ref=null)
Load object in memory from the database.
initAsSpecimen()
Initialise object with example values Id must be 0 if object instance is a specimen.
LibStatut($status, $mode=0)
Return the status.
deleteLine(User $user, $idline, $notrigger=0)
Delete a line of object in database.
getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='', $save_lastsearch_value=-1)
Return a link to the object card (with optionally the picto)
createFromClone(User $user, $fromid)
Clone an object into another one.
reopen($user, $notrigger=0)
Set back to validated status.
getSkillRankForJob($id)
function for get required skills associate to job object
create(User $user, $notrigger=0)
Create object into database.
fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, $filter='', $filtermode='AND')
Load list of objects in memory from the database.
getForUser($userid)
Get array of jobs occupied by a user.
getKanbanView($option='', $arraydata=null)
Return clickable link of object (with eventually picto)
info($id)
Load the info information in the object.
Class JobLine.
__construct(DoliDB $db)
Constructor.
Class for Position.
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
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
dol_dir_list($utf8_path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition files.lib.php:65
dol_now($mode='gmt')
Return date for now.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0, $forbiddenfields=array())
forgeSQLFromUniversalSearchCriteria
dol_substr($string, $start, $length=null, $stringencoding='', $trunconbytes=0)
Make a substring.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '...' if string larger than length.
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.