dolibarr 21.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
28require_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
66
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 );
136 public $rowid;
137
141 public $ref;
145 public $entity;
146
150 public $label;
151
155 public $qty;
156
160 public $fk_soc;
161
165 public $fk_project;
169 public $fk_user_recruiter;
170
174 public $email_recruiter;
175
179 public $remuneration_suggested;
180
184 public $fk_user_supervisor;
188 public $fk_establishment;
192 public $date_planned;
196 public $description;
200 public $note_public;
204 public $note_private;
208 public $fk_user_creat;
212 public $fk_user_modif;
216 public $last_main_doc;
220 public $import_key;
224 public $model_pdf;
228 public $status;
229 // END MODULEBUILDER PROPERTIES
230
231
237 public function __construct(DoliDB $db)
238 {
239 global $conf, $langs;
240
241 $this->db = $db;
242
243 $this->ismultientitymanaged = 1;
244 $this->isextrafieldmanaged = 1;
245
246 if (!getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid'])) {
247 $this->fields['rowid']['visible'] = 0;
248 }
249 if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
250 $this->fields['entity']['enabled'] = 0;
251 }
252
253 // Example to show how to set values of fields definition dynamically
254 /*if ($user->hasRight('recruitment', 'recruitmentjobposition', 'read')) {
255 $this->fields['myfield']['visible'] = 1;
256 $this->fields['myfield']['noteditable'] = 0;
257 }*/
258
259 // Unset fields that are disabled
260 foreach ($this->fields as $key => $val) {
261 if (isset($val['enabled']) && empty($val['enabled'])) {
262 unset($this->fields[$key]);
263 }
264 }
265
266 // Translate some data of arrayofkeyval
267 if (is_object($langs)) {
268 foreach ($this->fields as $key => $val) {
269 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
270 foreach ($val['arrayofkeyval'] as $key2 => $val2) {
271 $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
272 }
273 }
274 }
275 }
276 }
277
285 public function create(User $user, $notrigger = 0)
286 {
287 return $this->createCommon($user, $notrigger);
288 }
289
297 public function createFromClone(User $user, $fromid)
298 {
299 global $langs, $extrafields;
300 $error = 0;
301
302 dol_syslog(__METHOD__, LOG_DEBUG);
303
304 $object = new self($this->db);
305
306 $this->db->begin();
307
308 // Load source object
309 $result = $object->fetchCommon($fromid);
310 if ($result > 0 && !empty($object->table_element_line)) {
311 $object->fetchLines();
312 }
313
314 // get lines so they will be clone
315 //foreach($this->lines as $line)
316 // $line->fetch_optionals();
317
318 // Reset some properties
319 unset($object->id);
320 unset($object->fk_user_creat);
321 unset($object->import_key);
322
323 // Clear fields
324 if (property_exists($object, 'ref')) {
325 // @phan-suppress-next-line PhanTypeMismatchProperty
326 $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default'];
327 }
328 if (property_exists($object, 'label')) {
329 // @phan-suppress-next-line PhanTypeInvalidDimOffset
330 $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default'];
331 }
332 if (property_exists($object, 'status')) {
333 $object->status = self::STATUS_DRAFT;
334 }
335 if (property_exists($object, 'date_creation')) {
336 $object->date_creation = dol_now();
337 }
338 if (property_exists($object, 'date_modification')) {
339 $object->date_modification = null;
340 }
341 // ...
342 // Clear extrafields that are unique
343 if (is_array($object->array_options) && count($object->array_options) > 0) {
344 $extrafields->fetch_name_optionals_label($this->table_element);
345 foreach ($object->array_options as $key => $option) {
346 $shortkey = preg_replace('/options_/', '', $key);
347 if (!empty($extrafields->attributes[$this->element]['unique'][$shortkey])) {
348 //var_dump($key);
349 //var_dump($clonedObj->array_options[$key]); exit;
350 unset($object->array_options[$key]);
351 }
352 }
353 }
354
355 // Create clone
356 $object->context['createfromclone'] = 'createfromclone';
357 $result = $object->createCommon($user);
358 if ($result < 0) {
359 $error++;
360 $this->error = $object->error;
361 $this->errors = $object->errors;
362 }
363
364 if (!$error) {
365 // copy internal contacts
366 if ($this->copy_linked_contact($object, 'internal') < 0) {
367 $error++;
368 }
369 }
370
371 if (!$error) {
372 // copy external contacts if same company
373 if (property_exists($this, 'socid') && $this->socid == $object->socid) {
374 if ($this->copy_linked_contact($object, 'external') < 0) {
375 $error++;
376 }
377 }
378 }
379
380 unset($object->context['createfromclone']);
381
382 // End
383 if (!$error) {
384 $this->db->commit();
385 return $object;
386 } else {
387 $this->db->rollback();
388 return -1;
389 }
390 }
391
399 public function fetch($id, $ref = null)
400 {
401 $result = $this->fetchCommon($id, $ref);
402 if ($result > 0 && !empty($this->table_element_line)) {
403 $this->fetchLines();
404 }
405 return $result;
406 }
407
413 public function fetchLines()
414 {
415 $this->lines = array();
416
417 $result = $this->fetchLinesCommon();
418 return $result;
419 }
420
421
434 public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND')
435 {
436 dol_syslog(__METHOD__, LOG_DEBUG);
437
438 $records = array();
439
440 $sql = 'SELECT ';
441 $sql .= $this->getFieldList();
442 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
443 if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
444 $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')';
445 } else {
446 $sql .= ' WHERE 1 = 1';
447 }
448
449 // Manage filter
450 $errormessage = '';
451 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
452 if ($errormessage) {
453 $this->errors[] = $errormessage;
454 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
455 return -1;
456 }
457
458 if (!empty($sortfield)) {
459 $sql .= $this->db->order($sortfield, $sortorder);
460 }
461 if (!empty($limit)) {
462 $sql .= $this->db->plimit($limit, $offset);
463 }
464
465 $resql = $this->db->query($sql);
466 if ($resql) {
467 $num = $this->db->num_rows($resql);
468 $i = 0;
469 while ($i < ($limit ? min($limit, $num) : $num)) {
470 $obj = $this->db->fetch_object($resql);
471
472 $record = new self($this->db);
473 $record->setVarsFromFetchObj($obj);
474
475 $records[$record->id] = $record;
476
477 $i++;
478 }
479 $this->db->free($resql);
480
481 return $records;
482 } else {
483 $this->errors[] = 'Error '.$this->db->lasterror();
484 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
485
486 return -1;
487 }
488 }
489
497 public function update(User $user, $notrigger = 0)
498 {
499 return $this->updateCommon($user, $notrigger);
500 }
501
509 public function delete(User $user, $notrigger = 0)
510 {
511 return $this->deleteCommon($user, $notrigger);
512 //return $this->deleteCommon($user, $notrigger, 1);
513 }
514
523 public function deleteLine(User $user, $idline, $notrigger = 0)
524 {
525 if ($this->status < 0) {
526 $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
527 return -2;
528 }
529
530 return $this->deleteLineCommon($user, $idline, $notrigger);
531 }
532
533
541 public function validate($user, $notrigger = 0)
542 {
543 global $conf;
544
545 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
546
547 $error = 0;
548
549 // Protection
550 if ($this->status == self::STATUS_VALIDATED) {
551 dol_syslog(get_class($this)."::validate action abandoned: already validated", LOG_WARNING);
552 return 0;
553 }
554
555 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitmentjobposition->create))
556 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitmentjobposition->recruitmentjobposition_advance->validate))))
557 {
558 $this->error='NotEnoughPermissions';
559 dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
560 return -1;
561 }*/
562
563 $now = dol_now();
564
565 $this->db->begin();
566
567 // Define new ref
568 if (!$error && (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
569 $num = $this->getNextNumRef();
570 } else {
571 $num = $this->ref;
572 }
573 $this->newref = $num;
574
575 if (!empty($num)) {
576 // Validate
577 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
578 $sql .= " SET ref = '".$this->db->escape($num)."',";
579 $sql .= " status = ".self::STATUS_VALIDATED;
580 if (!empty($this->fields['date_validation'])) {
581 $sql .= ", date_validation = '".$this->db->idate($now)."',";
582 }
583 if (!empty($this->fields['fk_user_valid'])) { // @phan-suppress-current-line PhanTypeMismatchProperty
584 $sql .= ", fk_user_valid = ".((int) $user->id);
585 }
586 $sql .= " WHERE rowid = ".((int) $this->id);
587
588 dol_syslog(get_class($this)."::validate()", LOG_DEBUG);
589 $resql = $this->db->query($sql);
590 if (!$resql) {
591 dol_print_error($this->db);
592 $this->error = $this->db->lasterror();
593 $error++;
594 }
595
596 if (!$error && !$notrigger) {
597 // Call trigger
598 $result = $this->call_trigger('RECRUITMENTJOBPOSITION_VALIDATE', $user);
599 if ($result < 0) {
600 $error++;
601 }
602 // End call triggers
603 }
604 }
605
606 if (!$error) {
607 $this->oldref = $this->ref;
608
609 // Rename directory if dir was a temporary ref
610 if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
611 // Now we rename also files into index
612 $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)."'";
613 $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'recruitmentjobposition/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
614 $resql = $this->db->query($sql);
615 if (!$resql) {
616 $error++;
617 $this->error = $this->db->lasterror();
618 }
619 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'recruitmentjobposition/".$this->db->escape($this->newref)."'";
620 $sql .= " WHERE filepath = 'recruitmentjobposition/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
621 $resql = $this->db->query($sql);
622 if (!$resql) {
623 $error++;
624 $this->error = $this->db->lasterror();
625 }
626
627 // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
628 $oldref = dol_sanitizeFileName($this->ref);
629 $newref = dol_sanitizeFileName($num);
630 $dirsource = $conf->recruitment->dir_output.'/recruitmentjobposition/'.$oldref;
631 $dirdest = $conf->recruitment->dir_output.'/recruitmentjobposition/'.$newref;
632 if (!$error && file_exists($dirsource)) {
633 dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
634
635 if (@rename($dirsource, $dirdest)) {
636 dol_syslog("Rename ok");
637 // Rename docs starting with $oldref with $newref
638 $listoffiles = dol_dir_list($conf->recruitment->dir_output.'/recruitmentjobposition/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
639 foreach ($listoffiles as $fileentry) {
640 $dirsource = $fileentry['name'];
641 $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
642 $dirsource = $fileentry['path'].'/'.$dirsource;
643 $dirdest = $fileentry['path'].'/'.$dirdest;
644 @rename($dirsource, $dirdest);
645 }
646 }
647 }
648 }
649 }
650
651 // Set new ref and current status
652 if (!$error) {
653 $this->ref = $num;
655 }
656
657 if (!$error) {
658 $this->db->commit();
659 return 1;
660 } else {
661 $this->db->rollback();
662 return -1;
663 }
664 }
665
666
674 public function setDraft($user, $notrigger = 0)
675 {
676 // Protection
677 if ($this->status <= self::STATUS_DRAFT) {
678 return 0;
679 }
680
681 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->write))
682 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->recruitment_advance->validate))))
683 {
684 $this->error='Permission denied';
685 return -1;
686 }*/
687
688 return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'RECRUITMENTJOBPOSITION_UNVALIDATE');
689 }
690
698 public function cancel($user, $notrigger = 0)
699 {
700 // Protection
701 if ($this->status != self::STATUS_VALIDATED) {
702 return 0;
703 }
704
705 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->write))
706 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->recruitment_advance->validate))))
707 {
708 $this->error='Permission denied';
709 return -1;
710 }*/
711
712 return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'RECRUITMENTJOBPOSITION_CLOSE');
713 }
714
724 public function cloture($user, $status, $note = "", $notrigger = 0)
725 {
726 global $langs, $conf;
727
728 $error = 0;
729 $now = dol_now();
730
731 $this->db->begin();
732
733 $newprivatenote = dol_concatdesc($this->note_private, $note);
734
735 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
736 $sql .= " SET status = ".((int) $status).", note_private = '".$this->db->escape($newprivatenote)."'";
737 //$sql .= ", date_cloture='".$this->db->idate($now)."', fk_user_cloture=".$user->id;
738 $sql .= " WHERE rowid = ".((int) $this->id);
739
740 $resql = $this->db->query($sql);
741 if ($resql) {
742 $modelpdf = $this->model_pdf;
743 $triggerName = 'RECRUITMENTJOB_CLOSE_REFUSED';
744
745 if ($status == self::STATUS_RECRUITED) {
746 $triggerName = 'RECRUITMENTJOB_CLOSE_RECRUITED';
747 $modelpdf = $this->model_pdf;
748 }
749
750 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
751 // Define output language
752 $outputlangs = $langs;
753 if (getDolGlobalInt('MAIN_MULTILANGS')) {
754 $outputlangs = new Translate("", $conf);
755 $newlang = (GETPOST('lang_id', 'aZ09') ? GETPOST('lang_id', 'aZ09') : $this->thirdparty->default_lang);
756 $outputlangs->setDefaultLang($newlang);
757 }
758
759 // PDF
760 $hidedetails = (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS') ? 1 : 0);
761 $hidedesc = (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DESC') ? 1 : 0);
762 $hideref = (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_REF') ? 1 : 0);
763
764 //$ret=$object->fetch($id); // Reload to get new records
765 $this->generateDocument($modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
766 }
767
768 if (!$error) {
769 $this->oldcopy = clone $this;
770 $this->status = $status;
771 $this->date_cloture = $now;
772 $this->note_private = $newprivatenote;
773 }
774
775 if (!$notrigger && empty($error)) {
776 // Call trigger
777 $result = $this->call_trigger($triggerName, $user);
778 if ($result < 0) {
779 $error++;
780 }
781 // End call triggers
782 }
783
784 if (!$error) {
785 $this->db->commit();
786 return 1;
787 } else {
788 $this->status = $this->oldcopy->status;
789 $this->date_cloture = $this->oldcopy->date_cloture;
790 $this->note_private = $this->oldcopy->note_private;
791
792 $this->db->rollback();
793 return -1;
794 }
795 } else {
796 $this->error = $this->db->lasterror();
797 $this->db->rollback();
798 return -1;
799 }
800 }
801
809 public function reopen($user, $notrigger = 0)
810 {
811 // Protection
812 if ($this->status != self::STATUS_CANCELED) {
813 return 0;
814 }
815
816 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->write))
817 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->recruitment_advance->validate))))
818 {
819 $this->error='Permission denied';
820 return -1;
821 }*/
822
823 return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'RECRUITMENTJOBPOSITION_REOPEN');
824 }
825
836 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
837 {
838 global $conf, $langs, $hookmanager;
839
840 if (!empty($conf->dol_no_mouse_hover)) {
841 $notooltip = 1; // Force disable tooltips
842 }
843
844 $result = '';
845
846 $label = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("PositionToBeFilled").'</u>';
847 if (isset($this->status)) {
848 $label .= ' '.$this->getLibStatut(5);
849 }
850 $label .= '<br>';
851 $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref;
852 $label .= '<br><b>'.$langs->trans('Label').':</b> '.$this->label;
853
854 $url = dol_buildpath('/recruitment/recruitmentjobposition_card.php', 1).'?id='.$this->id;
855
856 if ($option != 'nolink') {
857 // Add param to save lastsearch_values or not
858 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
859 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
860 $add_save_lastsearch_values = 1;
861 }
862 if ($add_save_lastsearch_values) {
863 $url .= '&save_lastsearch_values=1';
864 }
865 }
866
867 $linkclose = '';
868 if (empty($notooltip)) {
869 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
870 $label = $langs->trans("ShowRecruitmentJobPosition");
871 $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
872 }
873 $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
874 $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
875 } else {
876 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
877 }
878
879 $linkstart = '<a href="'.$url.'"';
880 $linkstart .= $linkclose.'>';
881 $linkend = '</a>';
882
883 $result .= $linkstart;
884
885 if (empty($this->showphoto_on_popup)) {
886 if ($withpicto) {
887 $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);
888 }
889 } else {
890 if ($withpicto) {
891 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
892
893 list($class, $module) = explode('@', $this->picto);
894 $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref);
895 $filearray = dol_dir_list($upload_dir, "files");
896 $filename = $filearray[0]['name'];
897 if (!empty($filename)) {
898 $pospoint = strpos($filearray[0]['name'], '.');
899
900 $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint);
901 if (!getDolGlobalString(strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS')) {
902 $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>';
903 } else {
904 $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>';
905 }
906
907 $result .= '</div>';
908 } else {
909 $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);
910 }
911 }
912 }
913
914 if ($withpicto != 2) {
915 $result .= $this->ref;
916 }
917
918 $result .= $linkend;
919 //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
920
921 global $action, $hookmanager;
922 $hookmanager->initHooks(array('recruitmentjobpositiondao'));
923 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
924 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
925 if ($reshook > 0) {
926 $result = $hookmanager->resPrint;
927 } else {
928 $result .= $hookmanager->resPrint;
929 }
930
931 return $result;
932 }
933
940 public function getLibStatut($mode = 0)
941 {
942 return $this->LibStatut($this->status, $mode);
943 }
944
945 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
953 public function LibStatut($status, $mode = 0)
954 {
955 // phpcs:enable
956 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
957 global $langs;
958 //$langs->load("recruitment");
959 $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
960 $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated');
961 $this->labelStatus[self::STATUS_RECRUITED] = $langs->transnoentitiesnoconv('Recruited');
962 $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Canceled');
963 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
964 $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated');
965 $this->labelStatusShort[self::STATUS_RECRUITED] = $langs->transnoentitiesnoconv('Recruited');
966 $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Canceled');
967 }
968
969 $statusType = 'status'.$status;
970 if ($status == self::STATUS_VALIDATED) {
971 $statusType = 'status4';
972 }
973 if ($status == self::STATUS_RECRUITED) {
974 $statusType = 'status6';
975 }
976 if ($status == self::STATUS_CANCELED) {
977 $statusType = 'status9';
978 }
979
980 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
981 }
982
989 public function info($id)
990 {
991 $sql = 'SELECT rowid, date_creation as datec, tms as datem,';
992 $sql .= ' fk_user_creat, fk_user_modif';
993 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
994 $sql .= ' WHERE t.rowid = '.((int) $id);
995 $result = $this->db->query($sql);
996 if ($result) {
997 if ($this->db->num_rows($result)) {
998 $obj = $this->db->fetch_object($result);
999
1000 $this->id = $obj->rowid;
1001
1002 $this->user_creation_id = $obj->fk_user_creat;
1003 $this->user_modification_id = $obj->fk_user_modif;
1004 $this->date_creation = $this->db->jdate($obj->datec);
1005 $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
1006 }
1007
1008 $this->db->free($result);
1009 } else {
1010 dol_print_error($this->db);
1011 }
1012 }
1013
1020 public function initAsSpecimen()
1021 {
1022 return $this->initAsSpecimenCommon();
1023 }
1024
1030 public function getLinesArray()
1031 {
1032 $this->lines = array();
1033
1034 return $this->lines;
1035 }
1036
1042 public function getNextNumRef()
1043 {
1044 global $langs, $conf;
1045 $langs->load("recruitment");
1046
1047 if (!getDolGlobalString('RECRUITMENT_RECRUITMENTJOBPOSITION_ADDON')) {
1048 $conf->global->RECRUITMENT_RECRUITMENTJOBPOSITION_ADDON = 'mod_recruitmentjobposition_standard';
1049 }
1050
1051 if (getDolGlobalString('RECRUITMENT_RECRUITMENTJOBPOSITION_ADDON')) {
1052 $mybool = false;
1053
1054 $file = getDolGlobalString('RECRUITMENT_RECRUITMENTJOBPOSITION_ADDON') . ".php";
1055 $classname = getDolGlobalString('RECRUITMENT_RECRUITMENTJOBPOSITION_ADDON');
1056
1057 // Include file with class
1058 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1059 foreach ($dirmodels as $reldir) {
1060 $dir = dol_buildpath($reldir."core/modules/recruitment/");
1061
1062 // Load file with numbering class (if found)
1063 $mybool = ((bool) @include_once $dir.$file) || $mybool;
1064 }
1065
1066 if (!$mybool) {
1067 dol_print_error(null, "Failed to include file ".$file);
1068 return '';
1069 }
1070
1071 if (class_exists($classname)) {
1072 $obj = new $classname();
1073 '@phan-var-force ModeleNumRefRecruitmentJobPosition $obj';
1074 $numref = $obj->getNextValue($this);
1075
1076 if ($numref != '' && $numref != '-1') {
1077 return $numref;
1078 } else {
1079 $this->error = $obj->error;
1080 //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1081 return "";
1082 }
1083 } else {
1084 print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname;
1085 return "";
1086 }
1087 } else {
1088 print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1089 return "";
1090 }
1091 }
1092
1104 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1105 {
1106 global $conf, $langs;
1107
1108 $result = 0;
1109 $includedocgeneration = 1;
1110
1111 $langs->load("recruitment");
1112
1113 if (!dol_strlen($modele)) {
1114 if (getDolGlobalString('RECRUITMENTJOBPOSITION_ADDON_PDF')) {
1115 $modele = getDolGlobalString('RECRUITMENTJOBPOSITION_ADDON_PDF');
1116 } else {
1117 $modele = ''; // No default value. For job position, we allow to disable all PDF generation
1118 }
1119 }
1120
1121 $modelpath = "core/modules/recruitment/doc/";
1122
1123 if ($includedocgeneration && !empty($modele)) {
1124 $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1125 }
1126
1127 return $result;
1128 }
1129
1137 public function doScheduledJob()
1138 {
1139 //global $conf, $langs;
1140
1141 //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log';
1142
1143 $error = 0;
1144 $this->output = '';
1145 $this->error = '';
1146
1147 dol_syslog(__METHOD__, LOG_DEBUG);
1148
1149 $now = dol_now();
1150
1151 $this->db->begin();
1152
1153 // ...
1154
1155 $this->db->commit();
1156
1157 return $error;
1158 }
1159
1160
1168 public function getKanbanView($option = '', $arraydata = null)
1169 {
1170 global $langs;
1171
1172 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
1173
1174 $return = '<div class="box-flex-item box-flex-grow-zero">';
1175 $return .= '<div class="info-box info-box-sm">';
1176 $return .= '<span class="info-box-icon bg-infobox-action">';
1177 $return .= img_picto('', $this->picto);
1178 $return .= '</span>';
1179 $return .= '<div class="info-box-content">';
1180 $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>';
1181 if ($selected >= 0) {
1182 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
1183 }
1184 /*
1185 if (property_exists($this, 'date_planned')) {
1186 $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>';
1187 }*/
1188 if (property_exists($this, 'remuneration_suggested')) {
1189 $return .= '<br><span class="opacitymedium">'.$langs->trans("Remuneration").'</span> : <span class="info-box-label">'.$this->remuneration_suggested.'</span>';
1190 }
1191 if (method_exists($this, 'getLibStatut')) {
1192 $return .= '<br><div class="info-box-status">'.$this->getLibStatut(3).' &nbsp; <span class="opacitymedium" title="'.$langs->trans("RecruitmentCandidatures").'">'.$langs->trans("RecruitmentCandidatures", '', '', '', '', 5).'</span> : <span>';
1193 $return .= $arraydata['nbapplications'];
1194 $return .= '</span></div>';
1195 }
1196 $return .= '</div>';
1197 $return .= '</div>';
1198 $return .= '</div>';
1199 return $return;
1200 }
1201}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:66
$object ref
Definition info.php:89
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.
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 clickable 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.
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:171
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 a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79