dolibarr  20.0.0-beta
recruitmentjobposition.class.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2020 Laurent Destailleur <eldy@users.sourceforge.net>
3 /* Copyright (C) 2022 Alexandre Spangaro <aspangaro@open-dsi.fr>
4  * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
5  * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <https://www.gnu.org/licenses/>.
19  */
20 
27 // Put here all includes required by your class file
28 require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
29 //require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
30 //require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
31 
36 {
40  public $module = 'recruitment';
41 
45  public $element = 'recruitmentjobposition';
46 
50  public $table_element = 'recruitment_recruitmentjobposition';
51 
55  public $picto = 'recruitmentjobposition';
56 
60  const STATUS_DRAFT = 0;
61 
65  const STATUS_VALIDATED = 1;
66 
70  const STATUS_RECRUITED = 3;
71 
75  const STATUS_CANCELED = 9;
76 
77 
103  // BEGIN MODULEBUILDER PROPERTIES
107  public $fields = array(
108  'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'comment' => "Id"),
109  'entity' => array('type' => 'integer', 'label' => 'Entity', 'enabled' => 1, 'visible' => 0, 'position' => 5, 'notnull' => 1, 'default' => '1', 'index' => 1),
110  'ref' => array('type' => 'varchar(128)', 'label' => 'Ref', 'enabled' => 1, 'position' => 10, 'notnull' => 1, 'visible' => 4, 'noteditable' => 1, 'default' => '(PROV)', 'index' => 1, 'searchall' => 1, 'showoncombobox' => 1, 'comment' => "Reference of object", 'css' => 'nowraponall'),
111  'label' => array('type' => 'varchar(255)', 'label' => 'JobLabel', 'enabled' => 1, 'position' => 30, 'notnull' => 1, 'visible' => 1, 'searchall' => 1, 'css' => 'minwidth500', 'csslist' => 'tdoverflowmax300', 'showoncombobox' => '2', 'autofocusoncreate' => 1),
112  'qty' => array('type' => 'integer', 'label' => 'NbOfEmployeesExpected', 'enabled' => 1, 'position' => 45, 'notnull' => 1, 'visible' => 1, 'default' => '1', 'isameasure' => 1, 'css' => 'maxwidth75imp'),
113  'fk_project' => array('type' => 'integer:Project:projet/class/project.class.php:1', 'label' => 'Project', 'enabled' => '$conf->project->enabled', 'position' => 52, 'notnull' => -1, 'visible' => -1, 'index' => 1, 'css' => 'maxwidth500', 'picto' => 'project'),
114  'fk_user_recruiter' => array('type' => 'integer:User:user/class/user.class.php:1:(statut:=:1)', 'label' => 'ResponsibleOfRecruitement', 'enabled' => 1, 'position' => 54, 'notnull' => 1, 'visible' => 1, 'foreignkey' => 'user.rowid', 'css' => 'maxwidth500', 'csslist' => 'tdoverflowmax150', 'picto' => 'user'),
115  'email_recruiter' => array('type' => 'varchar(255)', 'label' => 'EmailRecruiter', 'enabled' => 1, 'position' => 54, 'notnull' => 0, 'visible' => -1, 'help' => 'ToUseAGenericEmail', 'picto' => 'email'),
116  'fk_user_supervisor' => array('type' => 'integer:User:user/class/user.class.php:1:(statut:=:1)', 'label' => 'FutureManager', 'enabled' => 1, 'position' => 55, 'notnull' => 0, 'visible' => -1, 'foreignkey' => 'user.rowid', 'css' => 'maxwidth500', 'csslist' => 'tdoverflowmax150', 'picto' => 'user'),
117  'fk_establishment' => array('type' => 'integer:Establishment:hrm/class/establishment.class.php', 'label' => 'Establishment', 'enabled' => '$conf->hrm->enabled', 'position' => 56, 'notnull' => 0, 'visible' => -1, 'foreignkey' => 'establishment.rowid',),
118  'fk_soc' => array('type' => 'integer:Societe:societe/class/societe.class.php:1:((status:=:1) AND (entity:IN:__SHARED_ENTITIES__))', 'label' => 'WorkPlace', 'enabled' => 'isModEnabled("societe")', 'position' => 57, 'notnull' => -1, 'visible' => -1, 'css' => 'maxwidth500', 'index' => 1, 'help' => "IfJobIsLocatedAtAPartner", 'picto' => 'company'),
119  'date_planned' => array('type' => 'date', 'label' => 'DateExpected', 'enabled' => 1, 'position' => 60, 'notnull' => 0, 'visible' => 1,),
120  'remuneration_suggested' => array('type' => 'varchar(255)', 'label' => 'Remuneration', 'enabled' => 1, 'position' => 62, 'notnull' => 0, 'visible' => 1,),
121  'description' => array('type' => 'html', 'label' => 'Description', 'enabled' => 1, 'position' => 65, 'notnull' => 0, 'visible' => 3,),
122  'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'position' => 101, 'notnull' => 0, 'visible' => 0,),
123  'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'position' => 102, 'notnull' => 0, 'visible' => 0,),
124  'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'position' => 500, 'notnull' => 1, 'visible' => -4,),
125  'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'position' => 501, 'notnull' => 0, 'visible' => -2,),
126  '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',),
127  'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'position' => 511, 'notnull' => -1, 'visible' => -2,),
128  'last_main_doc' => array('type' => 'varchar(255)', 'label' => 'LastMainDoc', 'enabled' => 1, 'position' => 900, 'notnull' => 0, 'visible' => 0,),
129  'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'position' => 1000, 'notnull' => -1, 'visible' => -2,),
130  'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'position' => 1010, 'notnull' => -1, 'visible' => 0,),
131  'status' => array('type' => 'smallint', 'label' => 'Status', 'enabled' => 1, 'position' => 1000, 'notnull' => 1, 'visible' => 5, 'default' => '0', 'index' => 1, 'arrayofkeyval' => array('0' => 'Draft', '1' => 'Validated', '3' => 'Recruited', '9' => 'Canceled'),),
132  );
133  public $rowid;
134 
138  public $ref;
139  public $entity;
140 
144  public $label;
145  public $qty;
146  public $fk_soc;
147  public $fk_project;
148  public $fk_user_recruiter;
149 
153  public $email_recruiter;
154 
158  public $remuneration_suggested;
159 
160  public $fk_user_supervisor;
161  public $fk_establishment;
162  public $date_planned;
163  public $description;
164  public $note_public;
165  public $note_private;
166  public $date_creation;
167  public $fk_user_creat;
168  public $fk_user_modif;
169  public $last_main_doc;
170  public $import_key;
171  public $model_pdf;
172  public $status;
173  // END MODULEBUILDER PROPERTIES
174 
175 
181  public function __construct(DoliDB $db)
182  {
183  global $conf, $langs;
184 
185  $this->db = $db;
186 
187  $this->ismultientitymanaged = 1;
188  $this->isextrafieldmanaged = 1;
189 
190  if (!getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid'])) {
191  $this->fields['rowid']['visible'] = 0;
192  }
193  if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
194  $this->fields['entity']['enabled'] = 0;
195  }
196 
197  // Example to show how to set values of fields definition dynamically
198  /*if ($user->hasRight('recruitment', 'recruitmentjobposition', 'read')) {
199  $this->fields['myfield']['visible'] = 1;
200  $this->fields['myfield']['noteditable'] = 0;
201  }*/
202 
203  // Unset fields that are disabled
204  foreach ($this->fields as $key => $val) {
205  if (isset($val['enabled']) && empty($val['enabled'])) {
206  unset($this->fields[$key]);
207  }
208  }
209 
210  // Translate some data of arrayofkeyval
211  if (is_object($langs)) {
212  foreach ($this->fields as $key => $val) {
213  if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
214  foreach ($val['arrayofkeyval'] as $key2 => $val2) {
215  $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
216  }
217  }
218  }
219  }
220  }
221 
229  public function create(User $user, $notrigger = 0)
230  {
231  return $this->createCommon($user, $notrigger);
232  }
233 
241  public function createFromClone(User $user, $fromid)
242  {
243  global $langs, $extrafields;
244  $error = 0;
245 
246  dol_syslog(__METHOD__, LOG_DEBUG);
247 
248  $object = new self($this->db);
249 
250  $this->db->begin();
251 
252  // Load source object
253  $result = $object->fetchCommon($fromid);
254  if ($result > 0 && !empty($object->table_element_line)) {
255  $object->fetchLines();
256  }
257 
258  // get lines so they will be clone
259  //foreach($this->lines as $line)
260  // $line->fetch_optionals();
261 
262  // Reset some properties
263  unset($object->id);
264  unset($object->fk_user_creat);
265  unset($object->import_key);
266 
267  // Clear fields
268  if (property_exists($object, 'ref')) {
269  $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default'];
270  }
271  if (property_exists($object, 'label')) {
272  $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default'];
273  }
274  if (property_exists($object, 'status')) {
275  $object->status = self::STATUS_DRAFT;
276  }
277  if (property_exists($object, 'date_creation')) {
278  $object->date_creation = dol_now();
279  }
280  if (property_exists($object, 'date_modification')) {
281  $object->date_modification = null;
282  }
283  // ...
284  // Clear extrafields that are unique
285  if (is_array($object->array_options) && count($object->array_options) > 0) {
286  $extrafields->fetch_name_optionals_label($this->table_element);
287  foreach ($object->array_options as $key => $option) {
288  $shortkey = preg_replace('/options_/', '', $key);
289  if (!empty($extrafields->attributes[$this->element]['unique'][$shortkey])) {
290  //var_dump($key);
291  //var_dump($clonedObj->array_options[$key]); exit;
292  unset($object->array_options[$key]);
293  }
294  }
295  }
296 
297  // Create clone
298  $object->context['createfromclone'] = 'createfromclone';
299  $result = $object->createCommon($user);
300  if ($result < 0) {
301  $error++;
302  $this->error = $object->error;
303  $this->errors = $object->errors;
304  }
305 
306  if (!$error) {
307  // copy internal contacts
308  if ($this->copy_linked_contact($object, 'internal') < 0) {
309  $error++;
310  }
311  }
312 
313  if (!$error) {
314  // copy external contacts if same company
315  if (property_exists($this, 'socid') && $this->socid == $object->socid) {
316  if ($this->copy_linked_contact($object, 'external') < 0) {
317  $error++;
318  }
319  }
320  }
321 
322  unset($object->context['createfromclone']);
323 
324  // End
325  if (!$error) {
326  $this->db->commit();
327  return $object;
328  } else {
329  $this->db->rollback();
330  return -1;
331  }
332  }
333 
341  public function fetch($id, $ref = null)
342  {
343  $result = $this->fetchCommon($id, $ref);
344  if ($result > 0 && !empty($this->table_element_line)) {
345  $this->fetchLines();
346  }
347  return $result;
348  }
349 
355  public function fetchLines()
356  {
357  $this->lines = array();
358 
359  $result = $this->fetchLinesCommon();
360  return $result;
361  }
362 
363 
376  public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND')
377  {
378  dol_syslog(__METHOD__, LOG_DEBUG);
379 
380  $records = array();
381 
382  $sql = 'SELECT ';
383  $sql .= $this->getFieldList();
384  $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
385  if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
386  $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')';
387  } else {
388  $sql .= ' WHERE 1 = 1';
389  }
390 
391  // Manage filter
392  $errormessage = '';
393  $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
394  if ($errormessage) {
395  $this->errors[] = $errormessage;
396  dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
397  return -1;
398  }
399 
400  if (!empty($sortfield)) {
401  $sql .= $this->db->order($sortfield, $sortorder);
402  }
403  if (!empty($limit)) {
404  $sql .= $this->db->plimit($limit, $offset);
405  }
406 
407  $resql = $this->db->query($sql);
408  if ($resql) {
409  $num = $this->db->num_rows($resql);
410  $i = 0;
411  while ($i < ($limit ? min($limit, $num) : $num)) {
412  $obj = $this->db->fetch_object($resql);
413 
414  $record = new self($this->db);
415  $record->setVarsFromFetchObj($obj);
416 
417  $records[$record->id] = $record;
418 
419  $i++;
420  }
421  $this->db->free($resql);
422 
423  return $records;
424  } else {
425  $this->errors[] = 'Error '.$this->db->lasterror();
426  dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
427 
428  return -1;
429  }
430  }
431 
439  public function update(User $user, $notrigger = 0)
440  {
441  return $this->updateCommon($user, $notrigger);
442  }
443 
451  public function delete(User $user, $notrigger = 0)
452  {
453  return $this->deleteCommon($user, $notrigger);
454  //return $this->deleteCommon($user, $notrigger, 1);
455  }
456 
465  public function deleteLine(User $user, $idline, $notrigger = 0)
466  {
467  if ($this->status < 0) {
468  $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
469  return -2;
470  }
471 
472  return $this->deleteLineCommon($user, $idline, $notrigger);
473  }
474 
475 
483  public function validate($user, $notrigger = 0)
484  {
485  global $conf;
486 
487  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
488 
489  $error = 0;
490 
491  // Protection
492  if ($this->status == self::STATUS_VALIDATED) {
493  dol_syslog(get_class($this)."::validate action abandoned: already validated", LOG_WARNING);
494  return 0;
495  }
496 
497  /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitmentjobposition->create))
498  || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitmentjobposition->recruitmentjobposition_advance->validate))))
499  {
500  $this->error='NotEnoughPermissions';
501  dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
502  return -1;
503  }*/
504 
505  $now = dol_now();
506 
507  $this->db->begin();
508 
509  // Define new ref
510  if (!$error && (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
511  $num = $this->getNextNumRef();
512  } else {
513  $num = $this->ref;
514  }
515  $this->newref = $num;
516 
517  if (!empty($num)) {
518  // Validate
519  $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
520  $sql .= " SET ref = '".$this->db->escape($num)."',";
521  $sql .= " status = ".self::STATUS_VALIDATED;
522  if (!empty($this->fields['date_validation'])) {
523  $sql .= ", date_validation = '".$this->db->idate($now)."',";
524  }
525  if (!empty($this->fields['fk_user_valid'])) {
526  $sql .= ", fk_user_valid = ".$user->id;
527  }
528  $sql .= " WHERE rowid = ".((int) $this->id);
529 
530  dol_syslog(get_class($this)."::validate()", LOG_DEBUG);
531  $resql = $this->db->query($sql);
532  if (!$resql) {
533  dol_print_error($this->db);
534  $this->error = $this->db->lasterror();
535  $error++;
536  }
537 
538  if (!$error && !$notrigger) {
539  // Call trigger
540  $result = $this->call_trigger('RECRUITMENTJOBPOSITION_VALIDATE', $user);
541  if ($result < 0) {
542  $error++;
543  }
544  // End call triggers
545  }
546  }
547 
548  if (!$error) {
549  $this->oldref = $this->ref;
550 
551  // Rename directory if dir was a temporary ref
552  if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
553  // Now we rename also files into index
554  $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'recruitmentjobposition/".$this->db->escape($this->newref)."'";
555  $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'recruitmentjobposition/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
556  $resql = $this->db->query($sql);
557  if (!$resql) {
558  $error++;
559  $this->error = $this->db->lasterror();
560  }
561  $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'recruitmentjobposition/".$this->db->escape($this->newref)."'";
562  $sql .= " WHERE filepath = 'recruitmentjobposition/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
563  $resql = $this->db->query($sql);
564  if (!$resql) {
565  $error++;
566  $this->error = $this->db->lasterror();
567  }
568 
569  // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
570  $oldref = dol_sanitizeFileName($this->ref);
571  $newref = dol_sanitizeFileName($num);
572  $dirsource = $conf->recruitment->dir_output.'/recruitmentjobposition/'.$oldref;
573  $dirdest = $conf->recruitment->dir_output.'/recruitmentjobposition/'.$newref;
574  if (!$error && file_exists($dirsource)) {
575  dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
576 
577  if (@rename($dirsource, $dirdest)) {
578  dol_syslog("Rename ok");
579  // Rename docs starting with $oldref with $newref
580  $listoffiles = dol_dir_list($conf->recruitment->dir_output.'/recruitmentjobposition/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
581  foreach ($listoffiles as $fileentry) {
582  $dirsource = $fileentry['name'];
583  $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
584  $dirsource = $fileentry['path'].'/'.$dirsource;
585  $dirdest = $fileentry['path'].'/'.$dirdest;
586  @rename($dirsource, $dirdest);
587  }
588  }
589  }
590  }
591  }
592 
593  // Set new ref and current status
594  if (!$error) {
595  $this->ref = $num;
597  }
598 
599  if (!$error) {
600  $this->db->commit();
601  return 1;
602  } else {
603  $this->db->rollback();
604  return -1;
605  }
606  }
607 
608 
616  public function setDraft($user, $notrigger = 0)
617  {
618  // Protection
619  if ($this->status <= self::STATUS_DRAFT) {
620  return 0;
621  }
622 
623  /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->write))
624  || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->recruitment_advance->validate))))
625  {
626  $this->error='Permission denied';
627  return -1;
628  }*/
629 
630  return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'RECRUITMENTJOBPOSITION_UNVALIDATE');
631  }
632 
640  public function cancel($user, $notrigger = 0)
641  {
642  // Protection
643  if ($this->status != self::STATUS_VALIDATED) {
644  return 0;
645  }
646 
647  /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->write))
648  || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->recruitment_advance->validate))))
649  {
650  $this->error='Permission denied';
651  return -1;
652  }*/
653 
654  return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'RECRUITMENTJOBPOSITION_CLOSE');
655  }
656 
666  public function cloture($user, $status, $note = "", $notrigger = 0)
667  {
668  global $langs, $conf;
669 
670  $error = 0;
671  $now = dol_now();
672 
673  $this->db->begin();
674 
675  $newprivatenote = dol_concatdesc($this->note_private, $note);
676 
677  $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
678  $sql .= " SET status = ".((int) $status).", note_private = '".$this->db->escape($newprivatenote)."'";
679  //$sql .= ", date_cloture='".$this->db->idate($now)."', fk_user_cloture=".$user->id;
680  $sql .= " WHERE rowid = ".((int) $this->id);
681 
682  $resql = $this->db->query($sql);
683  if ($resql) {
684  $modelpdf = $this->model_pdf;
685  $triggerName = 'RECRUITMENTJOB_CLOSE_REFUSED';
686 
687  if ($status == self::STATUS_RECRUITED) {
688  $triggerName = 'RECRUITMENTJOB_CLOSE_RECRUITED';
689  $modelpdf = $this->model_pdf;
690  }
691 
692  if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
693  // Define output language
694  $outputlangs = $langs;
695  if (getDolGlobalInt('MAIN_MULTILANGS')) {
696  $outputlangs = new Translate("", $conf);
697  $newlang = (GETPOST('lang_id', 'aZ09') ? GETPOST('lang_id', 'aZ09') : $this->thirdparty->default_lang);
698  $outputlangs->setDefaultLang($newlang);
699  }
700 
701  // PDF
702  $hidedetails = (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS') ? 1 : 0);
703  $hidedesc = (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DESC') ? 1 : 0);
704  $hideref = (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_REF') ? 1 : 0);
705 
706  //$ret=$object->fetch($id); // Reload to get new records
707  $this->generateDocument($modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
708  }
709 
710  if (!$error) {
711  $this->oldcopy = clone $this;
712  $this->status = $status;
713  $this->date_cloture = $now;
714  $this->note_private = $newprivatenote;
715  }
716 
717  if (!$notrigger && empty($error)) {
718  // Call trigger
719  $result = $this->call_trigger($triggerName, $user);
720  if ($result < 0) {
721  $error++;
722  }
723  // End call triggers
724  }
725 
726  if (!$error) {
727  $this->db->commit();
728  return 1;
729  } else {
730  $this->status = $this->oldcopy->status;
731  $this->date_cloture = $this->oldcopy->date_cloture;
732  $this->note_private = $this->oldcopy->note_private;
733 
734  $this->db->rollback();
735  return -1;
736  }
737  } else {
738  $this->error = $this->db->lasterror();
739  $this->db->rollback();
740  return -1;
741  }
742  }
743 
751  public function reopen($user, $notrigger = 0)
752  {
753  // Protection
754  if ($this->status != self::STATUS_CANCELED) {
755  return 0;
756  }
757 
758  /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->write))
759  || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->recruitment_advance->validate))))
760  {
761  $this->error='Permission denied';
762  return -1;
763  }*/
764 
765  return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'RECRUITMENTJOBPOSITION_REOPEN');
766  }
767 
778  public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
779  {
780  global $conf, $langs, $hookmanager;
781 
782  if (!empty($conf->dol_no_mouse_hover)) {
783  $notooltip = 1; // Force disable tooltips
784  }
785 
786  $result = '';
787 
788  $label = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("PositionToBeFilled").'</u>';
789  if (isset($this->status)) {
790  $label .= ' '.$this->getLibStatut(5);
791  }
792  $label .= '<br>';
793  $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref;
794  $label .= '<br><b>'.$langs->trans('Label').':</b> '.$this->label;
795 
796  $url = dol_buildpath('/recruitment/recruitmentjobposition_card.php', 1).'?id='.$this->id;
797 
798  if ($option != 'nolink') {
799  // Add param to save lastsearch_values or not
800  $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
801  if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
802  $add_save_lastsearch_values = 1;
803  }
804  if ($add_save_lastsearch_values) {
805  $url .= '&save_lastsearch_values=1';
806  }
807  }
808 
809  $linkclose = '';
810  if (empty($notooltip)) {
811  if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
812  $label = $langs->trans("ShowRecruitmentJobPosition");
813  $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
814  }
815  $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
816  $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
817  } else {
818  $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
819  }
820 
821  $linkstart = '<a href="'.$url.'"';
822  $linkstart .= $linkclose.'>';
823  $linkend = '</a>';
824 
825  $result .= $linkstart;
826 
827  if (empty($this->showphoto_on_popup)) {
828  if ($withpicto) {
829  $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);
830  }
831  } else {
832  if ($withpicto) {
833  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
834 
835  list($class, $module) = explode('@', $this->picto);
836  $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref);
837  $filearray = dol_dir_list($upload_dir, "files");
838  $filename = $filearray[0]['name'];
839  if (!empty($filename)) {
840  $pospoint = strpos($filearray[0]['name'], '.');
841 
842  $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint);
843  if (!getDolGlobalString(strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS')) {
844  $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>';
845  } else {
846  $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>';
847  }
848 
849  $result .= '</div>';
850  } else {
851  $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);
852  }
853  }
854  }
855 
856  if ($withpicto != 2) {
857  $result .= $this->ref;
858  }
859 
860  $result .= $linkend;
861  //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
862 
863  global $action, $hookmanager;
864  $hookmanager->initHooks(array('recruitmentjobpositiondao'));
865  $parameters = array('id' => $this->id, 'getnomurl' => &$result);
866  $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
867  if ($reshook > 0) {
868  $result = $hookmanager->resPrint;
869  } else {
870  $result .= $hookmanager->resPrint;
871  }
872 
873  return $result;
874  }
875 
882  public function getLibStatut($mode = 0)
883  {
884  return $this->LibStatut($this->status, $mode);
885  }
886 
887  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
895  public function LibStatut($status, $mode = 0)
896  {
897  // phpcs:enable
898  if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
899  global $langs;
900  //$langs->load("recruitment");
901  $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
902  $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated');
903  $this->labelStatus[self::STATUS_RECRUITED] = $langs->transnoentitiesnoconv('Recruited');
904  $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Canceled');
905  $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
906  $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated');
907  $this->labelStatusShort[self::STATUS_RECRUITED] = $langs->transnoentitiesnoconv('Recruited');
908  $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Canceled');
909  }
910 
911  $statusType = 'status'.$status;
912  if ($status == self::STATUS_VALIDATED) {
913  $statusType = 'status4';
914  }
915  if ($status == self::STATUS_RECRUITED) {
916  $statusType = 'status6';
917  }
918  if ($status == self::STATUS_CANCELED) {
919  $statusType = 'status9';
920  }
921 
922  return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
923  }
924 
931  public function info($id)
932  {
933  $sql = 'SELECT rowid, date_creation as datec, tms as datem,';
934  $sql .= ' fk_user_creat, fk_user_modif';
935  $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
936  $sql .= ' WHERE t.rowid = '.((int) $id);
937  $result = $this->db->query($sql);
938  if ($result) {
939  if ($this->db->num_rows($result)) {
940  $obj = $this->db->fetch_object($result);
941 
942  $this->id = $obj->rowid;
943 
944  $this->user_creation_id = $obj->fk_user_creat;
945  $this->user_modification_id = $obj->fk_user_modif;
946  $this->date_creation = $this->db->jdate($obj->datec);
947  $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
948  }
949 
950  $this->db->free($result);
951  } else {
952  dol_print_error($this->db);
953  }
954  }
955 
962  public function initAsSpecimen()
963  {
964  return $this->initAsSpecimenCommon();
965  }
966 
972  public function getLinesArray()
973  {
974  $this->lines = array();
975 
976  return $this->lines;
977  }
978 
984  public function getNextNumRef()
985  {
986  global $langs, $conf;
987  $langs->load("recruitment");
988 
989  if (!getDolGlobalString('RECRUITMENT_RECRUITMENTJOBPOSITION_ADDON')) {
990  $conf->global->RECRUITMENT_RECRUITMENTJOBPOSITION_ADDON = 'mod_recruitmentjobposition_standard';
991  }
992 
993  if (getDolGlobalString('RECRUITMENT_RECRUITMENTJOBPOSITION_ADDON')) {
994  $mybool = false;
995 
996  $file = getDolGlobalString('RECRUITMENT_RECRUITMENTJOBPOSITION_ADDON') . ".php";
997  $classname = getDolGlobalString('RECRUITMENT_RECRUITMENTJOBPOSITION_ADDON');
998 
999  // Include file with class
1000  $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1001  foreach ($dirmodels as $reldir) {
1002  $dir = dol_buildpath($reldir."core/modules/recruitment/");
1003 
1004  // Load file with numbering class (if found)
1005  $mybool = ((bool) @include_once $dir.$file) || $mybool;
1006  }
1007 
1008  if ($mybool === false) {
1009  dol_print_error(null, "Failed to include file ".$file);
1010  return '';
1011  }
1012 
1013  if (class_exists($classname)) {
1014  $obj = new $classname();
1015  $numref = $obj->getNextValue($this);
1016 
1017  if ($numref != '' && $numref != '-1') {
1018  return $numref;
1019  } else {
1020  $this->error = $obj->error;
1021  //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1022  return "";
1023  }
1024  } else {
1025  print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname;
1026  return "";
1027  }
1028  } else {
1029  print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1030  return "";
1031  }
1032  }
1033 
1045  public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1046  {
1047  global $conf, $langs;
1048 
1049  $result = 0;
1050  $includedocgeneration = 1;
1051 
1052  $langs->load("recruitment");
1053 
1054  if (!dol_strlen($modele)) {
1055  if (getDolGlobalString('RECRUITMENTJOBPOSITION_ADDON_PDF')) {
1056  $modele = getDolGlobalString('RECRUITMENTJOBPOSITION_ADDON_PDF');
1057  } else {
1058  $modele = ''; // No default value. For job position, we allow to disable all PDF generation
1059  }
1060  }
1061 
1062  $modelpath = "core/modules/recruitment/doc/";
1063 
1064  if ($includedocgeneration && !empty($modele)) {
1065  $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1066  }
1067 
1068  return $result;
1069  }
1070 
1078  public function doScheduledJob()
1079  {
1080  //global $conf, $langs;
1081 
1082  //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log';
1083 
1084  $error = 0;
1085  $this->output = '';
1086  $this->error = '';
1087 
1088  dol_syslog(__METHOD__, LOG_DEBUG);
1089 
1090  $now = dol_now();
1091 
1092  $this->db->begin();
1093 
1094  // ...
1095 
1096  $this->db->commit();
1097 
1098  return $error;
1099  }
1100 
1101 
1109  public function getKanbanView($option = '', $arraydata = null)
1110  {
1111  global $langs;
1112 
1113  $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
1114 
1115  $return = '<div class="box-flex-item box-flex-grow-zero">';
1116  $return .= '<div class="info-box info-box-sm">';
1117  $return .= '<span class="info-box-icon bg-infobox-action">';
1118  $return .= img_picto('', $this->picto);
1119  $return .= '</span>';
1120  $return .= '<div class="info-box-content">';
1121  $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).($this->qty > 1 ? ' <span title="'.$langs->trans("NbOfEmployeesExpected").'">('.$this->qty.')</span>' : '').'</span>';
1122  if ($selected >= 0) {
1123  $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
1124  }
1125  /*
1126  if (property_exists($this, 'date_planned')) {
1127  $return .= '<br><span class="opacitymedium">'.$langs->trans("Date").'</span> : <span class="info-box-label">'.dol_print_date($this->db->jdate($this->date_planned), 'day').'</span>';
1128  }*/
1129  if (property_exists($this, 'remuneration_suggested')) {
1130  $return .= '<br><span class="opacitymedium">'.$langs->trans("Remuneration").'</span> : <span class="info-box-label">'.$this->remuneration_suggested.'</span>';
1131  }
1132  if (method_exists($this, 'getLibStatut')) {
1133  $return .= '<br><div class="info-box-status">'.$this->getLibStatut(3).' &nbsp; <span class="opacitymedium" title="'.$langs->trans("RecruitmentCandidatures").'">'.$langs->trans("RecruitmentCandidatures", '', '', '', '', 5).'</span> : <span>';
1134  $return .= $arraydata['nbapplications'];
1135  $return .= '</span></div>';
1136  }
1137  $return .= '</div>';
1138  $return .= '</div>';
1139  $return .= '</div>';
1140  return $return;
1141  }
1142 }
if($user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition: card.php:58
print $langs trans("AuditedSecurityEvents").'</strong >< span class="opacitymedium"></span >< br > status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition: security.php:607
$object ref
Definition: info.php:79
Parent class of all other business classes (invoices, contracts, proposals, orders,...
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.
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.
call_trigger($triggerName, $user)
Call trigger based on this instance.
Class to manage Dolibarr database access.
Class for RecruitmentJobPosition.
validate($user, $notrigger=0)
Validate object.
deleteLine(User $user, $idline, $notrigger=0)
Delete a line of object in database.
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
Create a document onto disk according to template module.
info($id)
Load the info information in the object.
__construct(DoliDB $db)
Constructor.
cloture($user, $status, $note="", $notrigger=0)
Close the recruitment.
getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='', $save_lastsearch_value=-1)
Return a link to the object card (with optionally the picto)
doScheduledJob()
Action executed by scheduler CAN BE A CRON TASK.
setDraft($user, $notrigger=0)
Set draft status.
getLibStatut($mode=0)
Return label of the status.
create(User $user, $notrigger=0)
Create object into database.
LibStatut($status, $mode=0)
Return the status.
getLinesArray()
Create an array of lines.
reopen($user, $notrigger=0)
Set back to validated status.
getKanbanView($option='', $arraydata=null)
Return clicable link of object (with eventually picto)
fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, $filter='', $filtermode='AND')
Load list of objects in memory from the database.
update(User $user, $notrigger=0)
Update object into database.
fetch($id, $ref=null)
Load object in memory from the database.
cancel($user, $notrigger=0)
Set cancel status.
createFromClone(User $user, $fromid)
Clone an object into another one.
initAsSpecimen()
Initialise object with example values Id must be 0 if object instance is a specimen.
getNextNumRef()
Returns the reference to the following non used object depending on the active numbering module.
fetchLines()
Load object lines in memory from the database.
Class to manage translations.
Class to manage Dolibarr users.
Definition: user.class.php:50
if(isModEnabled('invoice') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&!getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD') && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') && $user->hasRight('tax', 'charges', 'lire')) if(isModEnabled('invoice') &&isModEnabled('order') && $user->hasRight("commande", "lire") &&!getDolGlobalString('WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER')) $sql
Social contributions to pay.
Definition: index.php:745
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:63
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0)
forgeSQLFromUniversalSearchCriteria
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getDolGlobalString($key, $default='')
Return 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.