dolibarr 20.0.0
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 );
133 public $rowid;
134
138 public $ref;
139 public $entity;
140
144 public $label;
145
149 public $qty;
150
154 public $fk_soc;
155
159 public $fk_project;
160 public $fk_user_recruiter;
161
165 public $email_recruiter;
166
170 public $remuneration_suggested;
171
172 public $fk_user_supervisor;
173 public $fk_establishment;
174 public $date_planned;
175 public $description;
176 public $note_public;
177 public $note_private;
178 public $date_creation;
179 public $fk_user_creat;
180 public $fk_user_modif;
181 public $last_main_doc;
182 public $import_key;
183 public $model_pdf;
184 public $status;
185 // END MODULEBUILDER PROPERTIES
186
187
193 public function __construct(DoliDB $db)
194 {
195 global $conf, $langs;
196
197 $this->db = $db;
198
199 $this->ismultientitymanaged = 1;
200 $this->isextrafieldmanaged = 1;
201
202 if (!getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid'])) {
203 $this->fields['rowid']['visible'] = 0;
204 }
205 if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
206 $this->fields['entity']['enabled'] = 0;
207 }
208
209 // Example to show how to set values of fields definition dynamically
210 /*if ($user->hasRight('recruitment', 'recruitmentjobposition', 'read')) {
211 $this->fields['myfield']['visible'] = 1;
212 $this->fields['myfield']['noteditable'] = 0;
213 }*/
214
215 // Unset fields that are disabled
216 foreach ($this->fields as $key => $val) {
217 if (isset($val['enabled']) && empty($val['enabled'])) {
218 unset($this->fields[$key]);
219 }
220 }
221
222 // Translate some data of arrayofkeyval
223 if (is_object($langs)) {
224 foreach ($this->fields as $key => $val) {
225 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
226 foreach ($val['arrayofkeyval'] as $key2 => $val2) {
227 $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
228 }
229 }
230 }
231 }
232 }
233
241 public function create(User $user, $notrigger = 0)
242 {
243 return $this->createCommon($user, $notrigger);
244 }
245
253 public function createFromClone(User $user, $fromid)
254 {
255 global $langs, $extrafields;
256 $error = 0;
257
258 dol_syslog(__METHOD__, LOG_DEBUG);
259
260 $object = new self($this->db);
261
262 $this->db->begin();
263
264 // Load source object
265 $result = $object->fetchCommon($fromid);
266 if ($result > 0 && !empty($object->table_element_line)) {
267 $object->fetchLines();
268 }
269
270 // get lines so they will be clone
271 //foreach($this->lines as $line)
272 // $line->fetch_optionals();
273
274 // Reset some properties
275 unset($object->id);
276 unset($object->fk_user_creat);
277 unset($object->import_key);
278
279 // Clear fields
280 if (property_exists($object, 'ref')) {
281 $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default'];
282 }
283 if (property_exists($object, 'label')) {
284 $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default'];
285 }
286 if (property_exists($object, 'status')) {
287 $object->status = self::STATUS_DRAFT;
288 }
289 if (property_exists($object, 'date_creation')) {
290 $object->date_creation = dol_now();
291 }
292 if (property_exists($object, 'date_modification')) {
293 $object->date_modification = null;
294 }
295 // ...
296 // Clear extrafields that are unique
297 if (is_array($object->array_options) && count($object->array_options) > 0) {
298 $extrafields->fetch_name_optionals_label($this->table_element);
299 foreach ($object->array_options as $key => $option) {
300 $shortkey = preg_replace('/options_/', '', $key);
301 if (!empty($extrafields->attributes[$this->element]['unique'][$shortkey])) {
302 //var_dump($key);
303 //var_dump($clonedObj->array_options[$key]); exit;
304 unset($object->array_options[$key]);
305 }
306 }
307 }
308
309 // Create clone
310 $object->context['createfromclone'] = 'createfromclone';
311 $result = $object->createCommon($user);
312 if ($result < 0) {
313 $error++;
314 $this->error = $object->error;
315 $this->errors = $object->errors;
316 }
317
318 if (!$error) {
319 // copy internal contacts
320 if ($this->copy_linked_contact($object, 'internal') < 0) {
321 $error++;
322 }
323 }
324
325 if (!$error) {
326 // copy external contacts if same company
327 if (property_exists($this, 'socid') && $this->socid == $object->socid) {
328 if ($this->copy_linked_contact($object, 'external') < 0) {
329 $error++;
330 }
331 }
332 }
333
334 unset($object->context['createfromclone']);
335
336 // End
337 if (!$error) {
338 $this->db->commit();
339 return $object;
340 } else {
341 $this->db->rollback();
342 return -1;
343 }
344 }
345
353 public function fetch($id, $ref = null)
354 {
355 $result = $this->fetchCommon($id, $ref);
356 if ($result > 0 && !empty($this->table_element_line)) {
357 $this->fetchLines();
358 }
359 return $result;
360 }
361
367 public function fetchLines()
368 {
369 $this->lines = array();
370
371 $result = $this->fetchLinesCommon();
372 return $result;
373 }
374
375
388 public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND')
389 {
390 dol_syslog(__METHOD__, LOG_DEBUG);
391
392 $records = array();
393
394 $sql = 'SELECT ';
395 $sql .= $this->getFieldList();
396 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
397 if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
398 $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')';
399 } else {
400 $sql .= ' WHERE 1 = 1';
401 }
402
403 // Manage filter
404 $errormessage = '';
405 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
406 if ($errormessage) {
407 $this->errors[] = $errormessage;
408 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
409 return -1;
410 }
411
412 if (!empty($sortfield)) {
413 $sql .= $this->db->order($sortfield, $sortorder);
414 }
415 if (!empty($limit)) {
416 $sql .= $this->db->plimit($limit, $offset);
417 }
418
419 $resql = $this->db->query($sql);
420 if ($resql) {
421 $num = $this->db->num_rows($resql);
422 $i = 0;
423 while ($i < ($limit ? min($limit, $num) : $num)) {
424 $obj = $this->db->fetch_object($resql);
425
426 $record = new self($this->db);
427 $record->setVarsFromFetchObj($obj);
428
429 $records[$record->id] = $record;
430
431 $i++;
432 }
433 $this->db->free($resql);
434
435 return $records;
436 } else {
437 $this->errors[] = 'Error '.$this->db->lasterror();
438 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
439
440 return -1;
441 }
442 }
443
451 public function update(User $user, $notrigger = 0)
452 {
453 return $this->updateCommon($user, $notrigger);
454 }
455
463 public function delete(User $user, $notrigger = 0)
464 {
465 return $this->deleteCommon($user, $notrigger);
466 //return $this->deleteCommon($user, $notrigger, 1);
467 }
468
477 public function deleteLine(User $user, $idline, $notrigger = 0)
478 {
479 if ($this->status < 0) {
480 $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
481 return -2;
482 }
483
484 return $this->deleteLineCommon($user, $idline, $notrigger);
485 }
486
487
495 public function validate($user, $notrigger = 0)
496 {
497 global $conf;
498
499 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
500
501 $error = 0;
502
503 // Protection
504 if ($this->status == self::STATUS_VALIDATED) {
505 dol_syslog(get_class($this)."::validate action abandoned: already validated", LOG_WARNING);
506 return 0;
507 }
508
509 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitmentjobposition->create))
510 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitmentjobposition->recruitmentjobposition_advance->validate))))
511 {
512 $this->error='NotEnoughPermissions';
513 dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
514 return -1;
515 }*/
516
517 $now = dol_now();
518
519 $this->db->begin();
520
521 // Define new ref
522 if (!$error && (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
523 $num = $this->getNextNumRef();
524 } else {
525 $num = $this->ref;
526 }
527 $this->newref = $num;
528
529 if (!empty($num)) {
530 // Validate
531 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
532 $sql .= " SET ref = '".$this->db->escape($num)."',";
533 $sql .= " status = ".self::STATUS_VALIDATED;
534 if (!empty($this->fields['date_validation'])) {
535 $sql .= ", date_validation = '".$this->db->idate($now)."',";
536 }
537 if (!empty($this->fields['fk_user_valid'])) {
538 $sql .= ", fk_user_valid = ".$user->id;
539 }
540 $sql .= " WHERE rowid = ".((int) $this->id);
541
542 dol_syslog(get_class($this)."::validate()", LOG_DEBUG);
543 $resql = $this->db->query($sql);
544 if (!$resql) {
545 dol_print_error($this->db);
546 $this->error = $this->db->lasterror();
547 $error++;
548 }
549
550 if (!$error && !$notrigger) {
551 // Call trigger
552 $result = $this->call_trigger('RECRUITMENTJOBPOSITION_VALIDATE', $user);
553 if ($result < 0) {
554 $error++;
555 }
556 // End call triggers
557 }
558 }
559
560 if (!$error) {
561 $this->oldref = $this->ref;
562
563 // Rename directory if dir was a temporary ref
564 if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
565 // Now we rename also files into index
566 $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)."'";
567 $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'recruitmentjobposition/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
568 $resql = $this->db->query($sql);
569 if (!$resql) {
570 $error++;
571 $this->error = $this->db->lasterror();
572 }
573 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'recruitmentjobposition/".$this->db->escape($this->newref)."'";
574 $sql .= " WHERE filepath = 'recruitmentjobposition/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
575 $resql = $this->db->query($sql);
576 if (!$resql) {
577 $error++;
578 $this->error = $this->db->lasterror();
579 }
580
581 // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
582 $oldref = dol_sanitizeFileName($this->ref);
583 $newref = dol_sanitizeFileName($num);
584 $dirsource = $conf->recruitment->dir_output.'/recruitmentjobposition/'.$oldref;
585 $dirdest = $conf->recruitment->dir_output.'/recruitmentjobposition/'.$newref;
586 if (!$error && file_exists($dirsource)) {
587 dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
588
589 if (@rename($dirsource, $dirdest)) {
590 dol_syslog("Rename ok");
591 // Rename docs starting with $oldref with $newref
592 $listoffiles = dol_dir_list($conf->recruitment->dir_output.'/recruitmentjobposition/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
593 foreach ($listoffiles as $fileentry) {
594 $dirsource = $fileentry['name'];
595 $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
596 $dirsource = $fileentry['path'].'/'.$dirsource;
597 $dirdest = $fileentry['path'].'/'.$dirdest;
598 @rename($dirsource, $dirdest);
599 }
600 }
601 }
602 }
603 }
604
605 // Set new ref and current status
606 if (!$error) {
607 $this->ref = $num;
609 }
610
611 if (!$error) {
612 $this->db->commit();
613 return 1;
614 } else {
615 $this->db->rollback();
616 return -1;
617 }
618 }
619
620
628 public function setDraft($user, $notrigger = 0)
629 {
630 // Protection
631 if ($this->status <= self::STATUS_DRAFT) {
632 return 0;
633 }
634
635 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->write))
636 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->recruitment_advance->validate))))
637 {
638 $this->error='Permission denied';
639 return -1;
640 }*/
641
642 return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'RECRUITMENTJOBPOSITION_UNVALIDATE');
643 }
644
652 public function cancel($user, $notrigger = 0)
653 {
654 // Protection
655 if ($this->status != self::STATUS_VALIDATED) {
656 return 0;
657 }
658
659 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->write))
660 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->recruitment_advance->validate))))
661 {
662 $this->error='Permission denied';
663 return -1;
664 }*/
665
666 return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'RECRUITMENTJOBPOSITION_CLOSE');
667 }
668
678 public function cloture($user, $status, $note = "", $notrigger = 0)
679 {
680 global $langs, $conf;
681
682 $error = 0;
683 $now = dol_now();
684
685 $this->db->begin();
686
687 $newprivatenote = dol_concatdesc($this->note_private, $note);
688
689 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
690 $sql .= " SET status = ".((int) $status).", note_private = '".$this->db->escape($newprivatenote)."'";
691 //$sql .= ", date_cloture='".$this->db->idate($now)."', fk_user_cloture=".$user->id;
692 $sql .= " WHERE rowid = ".((int) $this->id);
693
694 $resql = $this->db->query($sql);
695 if ($resql) {
696 $modelpdf = $this->model_pdf;
697 $triggerName = 'RECRUITMENTJOB_CLOSE_REFUSED';
698
699 if ($status == self::STATUS_RECRUITED) {
700 $triggerName = 'RECRUITMENTJOB_CLOSE_RECRUITED';
701 $modelpdf = $this->model_pdf;
702 }
703
704 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
705 // Define output language
706 $outputlangs = $langs;
707 if (getDolGlobalInt('MAIN_MULTILANGS')) {
708 $outputlangs = new Translate("", $conf);
709 $newlang = (GETPOST('lang_id', 'aZ09') ? GETPOST('lang_id', 'aZ09') : $this->thirdparty->default_lang);
710 $outputlangs->setDefaultLang($newlang);
711 }
712
713 // PDF
714 $hidedetails = (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS') ? 1 : 0);
715 $hidedesc = (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DESC') ? 1 : 0);
716 $hideref = (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_REF') ? 1 : 0);
717
718 //$ret=$object->fetch($id); // Reload to get new records
719 $this->generateDocument($modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
720 }
721
722 if (!$error) {
723 $this->oldcopy = clone $this;
724 $this->status = $status;
725 $this->date_cloture = $now;
726 $this->note_private = $newprivatenote;
727 }
728
729 if (!$notrigger && empty($error)) {
730 // Call trigger
731 $result = $this->call_trigger($triggerName, $user);
732 if ($result < 0) {
733 $error++;
734 }
735 // End call triggers
736 }
737
738 if (!$error) {
739 $this->db->commit();
740 return 1;
741 } else {
742 $this->status = $this->oldcopy->status;
743 $this->date_cloture = $this->oldcopy->date_cloture;
744 $this->note_private = $this->oldcopy->note_private;
745
746 $this->db->rollback();
747 return -1;
748 }
749 } else {
750 $this->error = $this->db->lasterror();
751 $this->db->rollback();
752 return -1;
753 }
754 }
755
763 public function reopen($user, $notrigger = 0)
764 {
765 // Protection
766 if ($this->status != self::STATUS_CANCELED) {
767 return 0;
768 }
769
770 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->write))
771 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->recruitment_advance->validate))))
772 {
773 $this->error='Permission denied';
774 return -1;
775 }*/
776
777 return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'RECRUITMENTJOBPOSITION_REOPEN');
778 }
779
790 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
791 {
792 global $conf, $langs, $hookmanager;
793
794 if (!empty($conf->dol_no_mouse_hover)) {
795 $notooltip = 1; // Force disable tooltips
796 }
797
798 $result = '';
799
800 $label = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("PositionToBeFilled").'</u>';
801 if (isset($this->status)) {
802 $label .= ' '.$this->getLibStatut(5);
803 }
804 $label .= '<br>';
805 $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref;
806 $label .= '<br><b>'.$langs->trans('Label').':</b> '.$this->label;
807
808 $url = dol_buildpath('/recruitment/recruitmentjobposition_card.php', 1).'?id='.$this->id;
809
810 if ($option != 'nolink') {
811 // Add param to save lastsearch_values or not
812 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
813 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
814 $add_save_lastsearch_values = 1;
815 }
816 if ($add_save_lastsearch_values) {
817 $url .= '&save_lastsearch_values=1';
818 }
819 }
820
821 $linkclose = '';
822 if (empty($notooltip)) {
823 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
824 $label = $langs->trans("ShowRecruitmentJobPosition");
825 $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
826 }
827 $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
828 $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
829 } else {
830 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
831 }
832
833 $linkstart = '<a href="'.$url.'"';
834 $linkstart .= $linkclose.'>';
835 $linkend = '</a>';
836
837 $result .= $linkstart;
838
839 if (empty($this->showphoto_on_popup)) {
840 if ($withpicto) {
841 $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);
842 }
843 } else {
844 if ($withpicto) {
845 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
846
847 list($class, $module) = explode('@', $this->picto);
848 $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref);
849 $filearray = dol_dir_list($upload_dir, "files");
850 $filename = $filearray[0]['name'];
851 if (!empty($filename)) {
852 $pospoint = strpos($filearray[0]['name'], '.');
853
854 $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint);
855 if (!getDolGlobalString(strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS')) {
856 $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>';
857 } else {
858 $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>';
859 }
860
861 $result .= '</div>';
862 } else {
863 $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);
864 }
865 }
866 }
867
868 if ($withpicto != 2) {
869 $result .= $this->ref;
870 }
871
872 $result .= $linkend;
873 //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
874
875 global $action, $hookmanager;
876 $hookmanager->initHooks(array('recruitmentjobpositiondao'));
877 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
878 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
879 if ($reshook > 0) {
880 $result = $hookmanager->resPrint;
881 } else {
882 $result .= $hookmanager->resPrint;
883 }
884
885 return $result;
886 }
887
894 public function getLibStatut($mode = 0)
895 {
896 return $this->LibStatut($this->status, $mode);
897 }
898
899 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
907 public function LibStatut($status, $mode = 0)
908 {
909 // phpcs:enable
910 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
911 global $langs;
912 //$langs->load("recruitment");
913 $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
914 $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated');
915 $this->labelStatus[self::STATUS_RECRUITED] = $langs->transnoentitiesnoconv('Recruited');
916 $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Canceled');
917 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
918 $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated');
919 $this->labelStatusShort[self::STATUS_RECRUITED] = $langs->transnoentitiesnoconv('Recruited');
920 $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Canceled');
921 }
922
923 $statusType = 'status'.$status;
924 if ($status == self::STATUS_VALIDATED) {
925 $statusType = 'status4';
926 }
927 if ($status == self::STATUS_RECRUITED) {
928 $statusType = 'status6';
929 }
930 if ($status == self::STATUS_CANCELED) {
931 $statusType = 'status9';
932 }
933
934 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
935 }
936
943 public function info($id)
944 {
945 $sql = 'SELECT rowid, date_creation as datec, tms as datem,';
946 $sql .= ' fk_user_creat, fk_user_modif';
947 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
948 $sql .= ' WHERE t.rowid = '.((int) $id);
949 $result = $this->db->query($sql);
950 if ($result) {
951 if ($this->db->num_rows($result)) {
952 $obj = $this->db->fetch_object($result);
953
954 $this->id = $obj->rowid;
955
956 $this->user_creation_id = $obj->fk_user_creat;
957 $this->user_modification_id = $obj->fk_user_modif;
958 $this->date_creation = $this->db->jdate($obj->datec);
959 $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
960 }
961
962 $this->db->free($result);
963 } else {
964 dol_print_error($this->db);
965 }
966 }
967
974 public function initAsSpecimen()
975 {
976 return $this->initAsSpecimenCommon();
977 }
978
984 public function getLinesArray()
985 {
986 $this->lines = array();
987
988 return $this->lines;
989 }
990
996 public function getNextNumRef()
997 {
998 global $langs, $conf;
999 $langs->load("recruitment");
1000
1001 if (!getDolGlobalString('RECRUITMENT_RECRUITMENTJOBPOSITION_ADDON')) {
1002 $conf->global->RECRUITMENT_RECRUITMENTJOBPOSITION_ADDON = 'mod_recruitmentjobposition_standard';
1003 }
1004
1005 if (getDolGlobalString('RECRUITMENT_RECRUITMENTJOBPOSITION_ADDON')) {
1006 $mybool = false;
1007
1008 $file = getDolGlobalString('RECRUITMENT_RECRUITMENTJOBPOSITION_ADDON') . ".php";
1009 $classname = getDolGlobalString('RECRUITMENT_RECRUITMENTJOBPOSITION_ADDON');
1010
1011 // Include file with class
1012 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1013 foreach ($dirmodels as $reldir) {
1014 $dir = dol_buildpath($reldir."core/modules/recruitment/");
1015
1016 // Load file with numbering class (if found)
1017 $mybool = ((bool) @include_once $dir.$file) || $mybool;
1018 }
1019
1020 if ($mybool === false) {
1021 dol_print_error(null, "Failed to include file ".$file);
1022 return '';
1023 }
1024
1025 if (class_exists($classname)) {
1026 $obj = new $classname();
1027 $numref = $obj->getNextValue($this);
1028
1029 if ($numref != '' && $numref != '-1') {
1030 return $numref;
1031 } else {
1032 $this->error = $obj->error;
1033 //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1034 return "";
1035 }
1036 } else {
1037 print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname;
1038 return "";
1039 }
1040 } else {
1041 print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1042 return "";
1043 }
1044 }
1045
1057 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1058 {
1059 global $conf, $langs;
1060
1061 $result = 0;
1062 $includedocgeneration = 1;
1063
1064 $langs->load("recruitment");
1065
1066 if (!dol_strlen($modele)) {
1067 if (getDolGlobalString('RECRUITMENTJOBPOSITION_ADDON_PDF')) {
1068 $modele = getDolGlobalString('RECRUITMENTJOBPOSITION_ADDON_PDF');
1069 } else {
1070 $modele = ''; // No default value. For job position, we allow to disable all PDF generation
1071 }
1072 }
1073
1074 $modelpath = "core/modules/recruitment/doc/";
1075
1076 if ($includedocgeneration && !empty($modele)) {
1077 $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1078 }
1079
1080 return $result;
1081 }
1082
1090 public function doScheduledJob()
1091 {
1092 //global $conf, $langs;
1093
1094 //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log';
1095
1096 $error = 0;
1097 $this->output = '';
1098 $this->error = '';
1099
1100 dol_syslog(__METHOD__, LOG_DEBUG);
1101
1102 $now = dol_now();
1103
1104 $this->db->begin();
1105
1106 // ...
1107
1108 $this->db->commit();
1109
1110 return $error;
1111 }
1112
1113
1121 public function getKanbanView($option = '', $arraydata = null)
1122 {
1123 global $langs;
1124
1125 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
1126
1127 $return = '<div class="box-flex-item box-flex-grow-zero">';
1128 $return .= '<div class="info-box info-box-sm">';
1129 $return .= '<span class="info-box-icon bg-infobox-action">';
1130 $return .= img_picto('', $this->picto);
1131 $return .= '</span>';
1132 $return .= '<div class="info-box-content">';
1133 $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>';
1134 if ($selected >= 0) {
1135 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
1136 }
1137 /*
1138 if (property_exists($this, 'date_planned')) {
1139 $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>';
1140 }*/
1141 if (property_exists($this, 'remuneration_suggested')) {
1142 $return .= '<br><span class="opacitymedium">'.$langs->trans("Remuneration").'</span> : <span class="info-box-label">'.$this->remuneration_suggested.'</span>';
1143 }
1144 if (method_exists($this, 'getLibStatut')) {
1145 $return .= '<br><div class="info-box-status">'.$this->getLibStatut(3).' &nbsp; <span class="opacitymedium" title="'.$langs->trans("RecruitmentCandidatures").'">'.$langs->trans("RecruitmentCandidatures", '', '', '', '', 5).'</span> : <span>';
1146 $return .= $arraydata['nbapplications'];
1147 $return .= '</span></div>';
1148 }
1149 $return .= '</div>';
1150 $return .= '</div>';
1151 $return .= '</div>';
1152 return $return;
1153 }
1154}
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:636
$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.
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.
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...
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.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.