dolibarr 21.0.0-alpha
recruitmentcandidature.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2020 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
4 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
26// Put here all includes required by your class file
27require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
28//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
29//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
30
35{
39 public $module = 'recruitment';
40
44 public $element = 'recruitmentcandidature';
45
49 public $table_element = 'recruitment_recruitmentcandidature';
50
54 public $picto = 'recruitmentcandidature';
55
59 public $email_fields_no_propagate_in_actioncomm;
60
61
62 const STATUS_DRAFT = 0;
63 const STATUS_VALIDATED = 1;
64 //const STATUS_INTERVIEW_SCHEDULED = 2;
65 const STATUS_CONTRACT_PROPOSED = 3;
66 const STATUS_CONTRACT_SIGNED = 5;
67 const STATUS_CONTRACT_REFUSED = 6;
68 const STATUS_REFUSED = 8;
69 const STATUS_CANCELED = 9;
70
71
97 // BEGIN MODULEBUILDER PROPERTIES
101 public $fields = array(
102 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'comment' => "Id"),
103 'entity' => array('type' => 'integer', 'label' => 'Entity', 'enabled' => 1, 'visible' => 0, 'position' => 5, 'notnull' => 1, 'default' => '1', 'index' => 1),
104 '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 candidature", 'csslist' => 'nowraponall'),
105 'fk_recruitmentjobposition' => array('type' => 'integer:RecruitmentJobPosition:recruitment/class/recruitmentjobposition.class.php:0:(t.status:=:1)', 'label' => 'Job', 'enabled' => 1, 'position' => 15, 'notnull' => 0, 'visible' => 1, 'index' => 1, 'picto' => 'recruitmentjobposition', 'css' => 'minwidth300 maxwidth500 widthcentpercentminusx', 'csslist' => 'minwidth100 nowraponall'),
106 'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'position' => 61, 'notnull' => 0, 'visible' => 0,),
107 'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'position' => 62, 'notnull' => 0, 'visible' => 0,),
108 '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', 'csslist' => 'tdoverflowmax100'),
109 'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'position' => 511, 'notnull' => -1, 'visible' => -2, 'csslist' => 'tdoverflowmax100'),
110 'lastname' => array('type' => 'varchar(128)', 'label' => 'Lastname', 'enabled' => 1, 'position' => 20, 'notnull' => 0, 'visible' => 1, 'csslist' => 'tdoverflowmax150'),
111 'firstname' => array('type' => 'varchar(128)', 'label' => 'Firstname', 'enabled' => 1, 'position' => 21, 'notnull' => 0, 'visible' => 1, 'csslist' => 'tdoverflowmax150'),
112 'email' => array('type' => 'email', 'label' => 'EMail', 'enabled' => 1, 'position' => 30, 'notnull' => 1, 'visible' => 1, 'picto' => 'email', 'csslist' => 'tdoverflowmax150'),
113 'phone' => array('type' => 'phone', 'label' => 'Phone', 'enabled' => 1, 'position' => 31, 'notnull' => 0, 'visible' => 1, 'picto' => 'phone', 'csslist' => 'tdoverflowmax150'),
114 'date_birth' => array('type' => 'date', 'label' => 'DateOfBirth', 'enabled' => 1, 'position' => 70, 'visible' => -1,),
115 'email_msgid' => array('type' => 'varchar(255)', 'label' => 'EmailMsgID', 'visible' => -2, 'enabled' => 1, 'position' => 540, 'notnull' => -1, 'help' => 'EmailMsgIDDesc'),
116 'email_date' => array('type' => 'datetime', 'label' => 'EmailDate', 'visible' => -2, 'enabled' => 1, 'position' => 541),
117 //'fk_recruitment_origin' => array('type'=>'integer:CRecruitmentOrigin:recruitment/class/crecruitmentorigin.class.php', 'label'=>'Origin', 'enabled'=>'1', 'position'=>45, 'visible'=>1, 'index'=>1),
118 'remuneration_requested' => array('type' => 'integer', 'label' => 'RequestedRemuneration', 'enabled' => 1, 'position' => 80, 'notnull' => 0, 'visible' => -1,),
119 'remuneration_proposed' => array('type' => 'integer', 'label' => 'ProposedRemuneration', 'enabled' => 1, 'position' => 81, 'notnull' => 0, 'visible' => -1,),
120 'description' => array('type' => 'html', 'label' => 'Description', 'enabled' => 1, 'position' => 300, 'notnull' => 0, 'visible' => 3, 'cssview' => 'wordbreak'),
121 'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'position' => 500, 'notnull' => 1, 'visible' => -4, 'csslist' => 'nowraponall'),
122 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'position' => 501, 'notnull' => 0, 'visible' => -2, 'csslist' => 'nowraponall'),
123 'fk_user' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'LinkedToDolibarrUser', 'enabled' => 1, 'position' => 600, 'notnull' => 0, 'visible' => -1, 'csslist' => 'tdoverflowmax100'),
124 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'position' => 1000, 'notnull' => -1, 'visible' => -2,),
125 'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'position' => 1010, 'notnull' => -1, 'visible' => 0,),
126 'status' => array('type' => 'smallint', 'label' => 'Status', 'enabled' => 1, 'position' => 1000, 'notnull' => 1, 'visible' => 2, 'index' => 1, 'default' => '0', 'arrayofkeyval' => array('0' => 'Draft', '1' => 'Received', '3' => 'ContractProposed', '5' => 'ContractSigned', '8' => 'Refused', '9' => 'Canceled')),
127 "ip" => array("type" => "varchar(250)", "label" => "Ip", "enabled" => "1", 'position' => 700, 'notnull' => 0, "visible" => "0", "comment" => "ip used to create record (for public submission page)"),
128 );
132 public $rowid;
136 public $entity;
140 public $ref;
144 public $fk_recruitmentjobposition;
148 public $description;
152 public $fk_user_creat;
156 public $fk_user_modif;
160 public $fk_user;
164 public $lastname;
168 public $firstname;
172 public $email;
176 public $phone;
180 public $date_birth;
184 public $email_msgid;
188 public $email_date;
192 public $remuneration_requested;
196 public $remuneration_proposed;
200 public $fk_recruitment_origin;
204 public $import_key;
208 public $model_pdf;
212 public $status;
216 public $ip;
217 // END MODULEBUILDER PROPERTIES
218
224 public function __construct(DoliDB $db)
225 {
226 global $conf, $langs;
227
228 $this->db = $db;
229
230 $this->ismultientitymanaged = 1;
231 $this->isextrafieldmanaged = 1;
232
233 if (!getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid'])) {
234 $this->fields['rowid']['visible'] = 0;
235 }
236 if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
237 $this->fields['entity']['enabled'] = 0;
238 }
239
240 // Example to show how to set values of fields definition dynamically
241 /*if ($user->rights->recruitment->recruitmentcandidature->read) {
242 $this->fields['myfield']['visible'] = 1;
243 $this->fields['myfield']['noteditable'] = 0;
244 }*/
245
246 // Unset fields that are disabled
247 foreach ($this->fields as $key => $val) {
248 if (isset($val['enabled']) && empty($val['enabled'])) {
249 unset($this->fields[$key]);
250 }
251 }
252
253 // Translate some data of arrayofkeyval
254 if (is_object($langs)) {
255 foreach ($this->fields as $key => $val) {
256 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
257 foreach ($val['arrayofkeyval'] as $key2 => $val2) {
258 $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
259 }
260 }
261 }
262 }
263 }
264
272 public function create(User $user, $notrigger = 0)
273 {
274 return $this->createCommon($user, $notrigger);
275 }
276
284 public function createFromClone(User $user, $fromid)
285 {
286 global $langs, $extrafields;
287 $error = 0;
288
289 dol_syslog(__METHOD__, LOG_DEBUG);
290
291 $object = new self($this->db);
292
293 $this->db->begin();
294
295 // Load source object
296 $result = $object->fetchCommon($fromid);
297 if ($result > 0 && !empty($object->table_element_line)) {
298 $object->fetchLines();
299 }
300
301 // get lines so they will be clone
302 //foreach($this->lines as $line)
303 // $line->fetch_optionals();
304
305 // Reset some properties
306 unset($object->id);
307 unset($object->fk_user_creat);
308 unset($object->import_key);
309
310 // Clear fields
311 if (property_exists($object, 'ref')) {
312 // @phan-suppress-next-line PhanTypeMismatchProperty
313 $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default'];
314 }
315 if (property_exists($object, 'label')) {
316 $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default'];
317 }
318 if (property_exists($object, 'status')) {
319 $object->status = self::STATUS_DRAFT;
320 }
321 if (property_exists($object, 'date_creation')) {
322 $object->date_creation = dol_now();
323 }
324 if (property_exists($object, 'date_modification')) {
325 $object->date_modification = null;
326 }
327
328 // ...
329 // Clear extrafields that are unique
330 if (is_array($object->array_options) && count($object->array_options) > 0) {
331 $extrafields->fetch_name_optionals_label($this->table_element);
332 foreach ($object->array_options as $key => $option) {
333 $shortkey = preg_replace('/options_/', '', $key);
334 if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
335 //var_dump($key);
336 //var_dump($clonedObj->array_options[$key]); exit;
337 unset($object->array_options[$key]);
338 }
339 }
340 }
341
342 // Create clone
343 $object->context['createfromclone'] = 'createfromclone';
344 $result = $object->createCommon($user);
345 if ($result < 0) {
346 $error++;
347 $this->error = $object->error;
348 $this->errors = $object->errors;
349 }
350
351 if (!$error) {
352 // copy internal contacts
353 if ($this->copy_linked_contact($object, 'internal') < 0) {
354 $error++;
355 }
356 }
357
358 if (!$error) {
359 // copy external contacts if same company
360 if (property_exists($this, 'socid') && $this->socid == $object->socid) {
361 if ($this->copy_linked_contact($object, 'external') < 0) {
362 $error++;
363 }
364 }
365 }
366
367 unset($object->context['createfromclone']);
368
369 // End
370 if (!$error) {
371 $this->db->commit();
372 return $object;
373 } else {
374 $this->db->rollback();
375 return -1;
376 }
377 }
378
387 public function fetch($id, $ref = null, $email_msgid = '')
388 {
389 $morewhere = '';
390 if ($email_msgid) {
391 $morewhere = " AND email_msgid = '".$this->db->escape($email_msgid)."'";
392 }
393 $result = $this->fetchCommon($id, $ref, $morewhere);
394 if ($result > 0 && !empty($this->table_element_line)) {
395 $this->fetchLines();
396 }
397 return $result;
398 }
399
405 public function fetchLines()
406 {
407 $this->lines = array();
408
409 $result = $this->fetchLinesCommon();
410 return $result;
411 }
412
413
426 public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND')
427 {
428 dol_syslog(__METHOD__, LOG_DEBUG);
429
430 $records = array();
431
432 $sql = 'SELECT ';
433 $sql .= $this->getFieldList();
434 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
435 if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
436 $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')';
437 } else {
438 $sql .= ' WHERE 1 = 1';
439 }
440
441 // Manage filter
442 $errormessage = '';
443 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
444 if ($errormessage) {
445 $this->errors[] = $errormessage;
446 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
447 return -1;
448 }
449
450 if (!empty($sortfield)) {
451 $sql .= $this->db->order($sortfield, $sortorder);
452 }
453 if (!empty($limit)) {
454 $sql .= $this->db->plimit($limit, $offset);
455 }
456
457 $resql = $this->db->query($sql);
458 if ($resql) {
459 $num = $this->db->num_rows($resql);
460 $i = 0;
461 while ($i < ($limit ? min($limit, $num) : $num)) {
462 $obj = $this->db->fetch_object($resql);
463
464 $record = new self($this->db);
465 $record->setVarsFromFetchObj($obj);
466
467 $records[$record->id] = $record;
468
469 $i++;
470 }
471 $this->db->free($resql);
472
473 return $records;
474 } else {
475 $this->errors[] = 'Error '.$this->db->lasterror();
476 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
477
478 return -1;
479 }
480 }
481
489 public function update(User $user, $notrigger = 0)
490 {
491 return $this->updateCommon($user, $notrigger);
492 }
493
501 public function delete(User $user, $notrigger = 0)
502 {
503 return $this->deleteCommon($user, $notrigger);
504 //return $this->deleteCommon($user, $notrigger, 1);
505 }
506
515 public function deleteLine(User $user, $idline, $notrigger = 0)
516 {
517 if ($this->status < 0) {
518 $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
519 return -2;
520 }
521
522 return $this->deleteLineCommon($user, $idline, $notrigger);
523 }
524
525
533 public function validate($user, $notrigger = 0)
534 {
535 global $conf, $langs;
536
537 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
538
539 $error = 0;
540
541 // Protection
542 if ($this->status == self::STATUS_VALIDATED) {
543 dol_syslog(get_class($this)."::validate action abandoned: already validated", LOG_WARNING);
544 return 0;
545 }
546
547 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->recruitmentcandidature->write))
548 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->recruitmentcandidature->recruitmentcandidature_advance->validate))))
549 {
550 $this->error='NotEnoughPermissions';
551 dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
552 return -1;
553 }*/
554
555 $now = dol_now();
556
557 $this->db->begin();
558
559 // Define new ref
560 if (!$error && (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
561 $num = $this->getNextNumRef();
562 } else {
563 $num = $this->ref;
564 }
565 $this->newref = $num;
566
567 if (!empty($num)) {
568 // Validate
569 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
570 $sql .= " SET ref = '".$this->db->escape($num)."',";
571 $sql .= " status = ".self::STATUS_VALIDATED;
572 if (!empty($this->fields['date_validation'])) {
573 $sql .= ", date_validation = '".$this->db->idate($now)."',";
574 }
575 if (!empty($this->fields['fk_user_valid'])) { // @phan-suppress-current-line PhanTypeMismatchProperty
576 $sql .= ", fk_user_valid = ".((int) $user->id);
577 }
578 $sql .= " WHERE rowid = ".((int) $this->id);
579
580 dol_syslog(get_class($this)."::validate()", LOG_DEBUG);
581 $resql = $this->db->query($sql);
582 if (!$resql) {
583 dol_print_error($this->db);
584 $this->error = $this->db->lasterror();
585 $error++;
586 }
587
588 if (!$error && !$notrigger) {
589 // Call trigger
590 $result = $this->call_trigger('RECRUITMENTCANDIDATURE_VALIDATE', $user);
591 if ($result < 0) {
592 $error++;
593 }
594 // End call triggers
595 }
596 }
597
598 if (!$error) {
599 $this->oldref = $this->ref;
600
601 // Rename directory if dir was a temporary ref
602 if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
603 // Now we rename also files into index
604 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'recruitmentcandidature/".$this->db->escape($this->newref)."'";
605 $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'recruitmentcandidature/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
606 $resql = $this->db->query($sql);
607 if (!$resql) {
608 $error++;
609 $this->error = $this->db->lasterror();
610 }
611 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'recruitmentcandidature/".$this->db->escape($this->newref)."'";
612 $sql .= " WHERE filepath = 'recruitmentcandidature/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
613 $resql = $this->db->query($sql);
614 if (!$resql) {
615 $error++;
616 $this->error = $this->db->lasterror();
617 }
618
619 // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
620 $oldref = dol_sanitizeFileName($this->ref);
621 $newref = dol_sanitizeFileName($num);
622 $dirsource = $conf->recruitment->dir_output.'/recruitmentcandidature/'.$oldref;
623 $dirdest = $conf->recruitment->dir_output.'/recruitmentcandidature/'.$newref;
624 if (!$error && file_exists($dirsource)) {
625 dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
626
627 if (@rename($dirsource, $dirdest)) {
628 dol_syslog("Rename ok");
629 // Rename docs starting with $oldref with $newref
630 $listoffiles = dol_dir_list($conf->recruitment->dir_output.'/recruitmentcandidature/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
631 foreach ($listoffiles as $fileentry) {
632 $dirsource = $fileentry['name'];
633 $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
634 $dirsource = $fileentry['path'].'/'.$dirsource;
635 $dirdest = $fileentry['path'].'/'.$dirdest;
636 @rename($dirsource, $dirdest);
637 }
638 }
639 }
640 }
641 }
642
643 // Set new ref and current status
644 if (!$error) {
645 $this->ref = $num;
646 $this->status = self::STATUS_VALIDATED;
647 }
648
649 if (!$error) {
650 $this->db->commit();
651 return 1;
652 } else {
653 $this->db->rollback();
654 return -1;
655 }
656 }
657
658
666 public function setDraft($user, $notrigger = 0)
667 {
668 // Protection
669 if ($this->status <= self::STATUS_DRAFT) {
670 return 0;
671 }
672
673 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->write))
674 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->recruitment_advance->validate))))
675 {
676 $this->error='Permission denied';
677 return -1;
678 }*/
679
680 return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'RECRUITMENTCANDIDATURE_UNVALIDATE');
681 }
682
690 public function cancel($user, $notrigger = 0)
691 {
692 // Protection
693 if ($this->status != self::STATUS_VALIDATED) {
694 return 0;
695 }
696
697 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->write))
698 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->recruitment_advance->validate))))
699 {
700 $this->error='Permission denied';
701 return -1;
702 }*/
703
704 return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'RECRUITMENTCANDIDATURE_CLOSE');
705 }
706
714 public function reopen($user, $notrigger = 0)
715 {
716 // Protection
717 if ($this->status != self::STATUS_REFUSED && $this->status != self::STATUS_CANCELED && $this->status != self::STATUS_CONTRACT_REFUSED) {
718 return 0;
719 }
720
721 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->write))
722 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->recruitment_advance->validate))))
723 {
724 $this->error='Permission denied';
725 return -1;
726 }*/
727
728 return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'RECRUITMENTCANDIDATURE_REOPEN');
729 }
730
740 public function getFullName($langs, $option = 0, $nameorder = -1, $maxlen = 0)
741 {
742 $lastname = $this->lastname;
743 $firstname = $this->firstname;
744 if (empty($lastname)) {
745 $lastname = (isset($this->lastname) ? $this->lastname : (isset($this->name) ? $this->name : (isset($this->nom) ? $this->nom : (isset($this->societe) ? $this->societe : (isset($this->company) ? $this->company : '')))));
746 }
747
748 $ret = '';
749
750 $ret .= dolGetFirstLastname($firstname, $lastname, $nameorder);
751
752 return dol_trunc($ret, $maxlen);
753 }
754
765 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
766 {
767 global $conf, $langs, $hookmanager;
768
769 if (!empty($conf->dol_no_mouse_hover)) {
770 $notooltip = 1; // Force disable tooltips
771 }
772
773 $result = '';
774
775 $label = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("RecruitmentCandidature").'</u>';
776 if (isset($this->status)) {
777 $label .= ' '.$this->getLibStatut(5);
778 }
779 $label .= '<br>';
780 $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref;
781 $label .= '<br><b>'.$langs->trans('Email').':</b> '.$this->email;
782 $label .= '<br><b>'.$langs->trans('Name').':</b> '.$this->getFullName($langs);
783
784 $url = dol_buildpath('/recruitment/recruitmentcandidature_card.php', 1).'?id='.$this->id;
785
786 if ($option != 'nolink') {
787 // Add param to save lastsearch_values or not
788 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
789 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
790 $add_save_lastsearch_values = 1;
791 }
792 if ($add_save_lastsearch_values) {
793 $url .= '&save_lastsearch_values=1';
794 }
795 }
796
797 $linkclose = '';
798 if (empty($notooltip)) {
799 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
800 $label = $langs->trans("ShowRecruitmentCandidature");
801 $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
802 }
803 $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
804 $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
805 } else {
806 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
807 }
808
809 $linkstart = '<a href="'.$url.'"';
810 $linkstart .= $linkclose.'>';
811 $linkend = '</a>';
812
813 $result .= $linkstart;
814
815 if (empty($this->showphoto_on_popup)) {
816 if ($withpicto) {
817 $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);
818 }
819 } else {
820 if ($withpicto) {
821 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
822
823 list($class, $module) = explode('@', $this->picto);
824 $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref);
825 $filearray = dol_dir_list($upload_dir, "files");
826 $filename = $filearray[0]['name'];
827 if (!empty($filename)) {
828 $pospoint = strpos($filearray[0]['name'], '.');
829
830 $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint);
831 if (!getDolGlobalString(strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS')) {
832 $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>';
833 } else {
834 $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>';
835 }
836
837 $result .= '</div>';
838 } else {
839 $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);
840 }
841 }
842 }
843
844 if ($withpicto != 2) {
845 $result .= $this->ref;
846 }
847
848 $result .= $linkend;
849 //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
850
851 global $action, $hookmanager;
852 $hookmanager->initHooks(array('recruitmentcandidaturedao'));
853 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
854 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
855 if ($reshook > 0) {
856 $result = $hookmanager->resPrint;
857 } else {
858 $result .= $hookmanager->resPrint;
859 }
860
861 return $result;
862 }
863
870 public function getLibStatut($mode = 0)
871 {
872 return $this->LibStatut($this->status, $mode);
873 }
874
875 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
883 public function LibStatut($status, $mode = 0)
884 {
885 // phpcs:enable
886 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
887 global $langs;
888 //$langs->load("recruitment@recruitment");
889 $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
890 $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Received').' ('.$langs->transnoentitiesnoconv("InterviewToDo").')';
891 $this->labelStatus[self::STATUS_CONTRACT_PROPOSED] = $langs->transnoentitiesnoconv('ContractProposed');
892 $this->labelStatus[self::STATUS_CONTRACT_SIGNED] = $langs->transnoentitiesnoconv('ContractSigned');
893 $this->labelStatus[self::STATUS_CONTRACT_REFUSED] = $langs->transnoentitiesnoconv('ContractRefused');
894 $this->labelStatus[self::STATUS_REFUSED] = $langs->transnoentitiesnoconv('Refused');
895 $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Canceled');
896 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
897 $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Received');
898 $this->labelStatusShort[self::STATUS_CONTRACT_PROPOSED] = $langs->transnoentitiesnoconv('ContractProposed');
899 $this->labelStatusShort[self::STATUS_CONTRACT_SIGNED] = $langs->transnoentitiesnoconv('ContractSigned');
900 $this->labelStatusShort[self::STATUS_CONTRACT_REFUSED] = $langs->transnoentitiesnoconv('ContractRefused');
901 $this->labelStatusShort[self::STATUS_REFUSED] = $langs->transnoentitiesnoconv('Refused');
902 $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Canceled');
903 }
904
905 $statusType = 'status'.$status;
906 //if ($status == self::STATUS_VALIDATED) $statusType = 'status1';
907 if ($status == self::STATUS_CANCELED) {
908 $statusType = 'status9';
909 }
910 if ($status == self::STATUS_CONTRACT_PROPOSED) {
911 $statusType = 'status4';
912 }
913 if ($status == self::STATUS_CONTRACT_SIGNED) {
914 $statusType = 'status6';
915 }
916 if ($status == self::STATUS_REFUSED) {
917 $statusType = 'status10';
918 }
919
920 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
921 }
922
929 public function info($id)
930 {
931 $sql = 'SELECT rowid, date_creation as datec, tms as datem,';
932 $sql .= ' fk_user_creat, fk_user_modif';
933 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
934 $sql .= ' WHERE t.rowid = '.((int) $id);
935 $result = $this->db->query($sql);
936 if ($result) {
937 if ($this->db->num_rows($result)) {
938 $obj = $this->db->fetch_object($result);
939
940 $this->id = $obj->rowid;
941
942 $this->user_creation_id = $obj->fk_user_creat;
943 $this->user_modification_id = $obj->fk_user_modif;
944 $this->date_creation = $this->db->jdate($obj->datec);
945 $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
946 }
947
948 $this->db->free($result);
949 } else {
950 dol_print_error($this->db);
951 }
952 }
953
960 public function initAsSpecimen()
961 {
962 return $this->initAsSpecimenCommon();
963 }
964
970 public function getLinesArray()
971 {
972 $this->lines = array();
973
974 $objectline = new RecruitmentCandidatureLine($this->db);
975 $result = $objectline->fetchAll('ASC', 'position', 0, 0, '(fk_recruitmentcandidature:=:'.((int) $this->id).')');
976
977 if (is_numeric($result)) {
978 $this->error = $objectline->error;
979 $this->errors = $objectline->errors;
980 return $result;
981 } else {
982 $this->lines = $result;
983 // @phpstan-ignore-next-line
984 return $result; // @phan-suppress-current-line PhanTypeMismatchReturn
985 }
986 }
987
993 public function getNextNumRef()
994 {
995 global $langs, $conf;
996 $langs->load("recruitment@recruitment");
997
998 if (!getDolGlobalString('RECRUITMENT_RECRUITMENTCANDIDATURE_ADDON')) {
999 $conf->global->RECRUITMENT_RECRUITMENTCANDIDATURE_ADDON = 'mod_recruitmentcandidature_standard';
1000 }
1001
1002 if (getDolGlobalString('RECRUITMENT_RECRUITMENTCANDIDATURE_ADDON')) {
1003 $mybool = false;
1004
1005 $file = getDolGlobalString('RECRUITMENT_RECRUITMENTCANDIDATURE_ADDON') . ".php";
1006 $classname = getDolGlobalString('RECRUITMENT_RECRUITMENTCANDIDATURE_ADDON');
1007
1008 // Include file with class
1009 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1010 foreach ($dirmodels as $reldir) {
1011 $dir = dol_buildpath($reldir."core/modules/recruitment/");
1012
1013 // Load file with numbering class (if found)
1014 $mybool = ((bool) @include_once $dir.$file) || $mybool;
1015 }
1016
1017 if (!$mybool) {
1018 dol_print_error(null, "Failed to include file ".$file);
1019 return '';
1020 }
1021
1022 if (class_exists($classname)) {
1023 $obj = new $classname();
1024 '@phan-var-force ModeleNumRefRecruitmentCandidature $module';
1025 $numref = $obj->getNextValue($this);
1026
1027 if ($numref != '' && $numref != '-1') {
1028 return $numref;
1029 } else {
1030 $this->error = $obj->error;
1031 //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1032 return "";
1033 }
1034 } else {
1035 print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname;
1036 return "";
1037 }
1038 } else {
1039 print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1040 return "";
1041 }
1042 }
1043
1055 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1056 {
1057 global $conf, $langs;
1058
1059 $result = 0;
1060 $includedocgeneration = 0;
1061
1062 $langs->load("recruitment@recruitment");
1063
1064 if (!dol_strlen($modele)) {
1065 if (getDolGlobalString('RECRUITMENTCANDIDATURE_ADDON_PDF')) {
1066 $modele = getDolGlobalString('RECRUITMENTCANDIDATURE_ADDON_PDF');
1067 } else {
1068 $modele = ''; // No default value. For job application, we allow to disable all PDF generation
1069 }
1070 }
1071
1072 $modelpath = "core/modules/recruitment/doc/";
1073
1074 if ($includedocgeneration && !empty($modele)) {
1075 $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1076 }
1077
1078 return $result;
1079 }
1080
1088 public function doScheduledJob()
1089 {
1090 global $conf, $langs;
1091
1092 //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log';
1093
1094 $error = 0;
1095 $this->output = '';
1096 $this->error = '';
1097
1098 dol_syslog(__METHOD__, LOG_DEBUG);
1099
1100 $now = dol_now();
1101
1102 $this->db->begin();
1103
1104 // ...
1105
1106 $this->db->commit();
1107
1108 return $error;
1109 }
1110
1118 public function getKanbanView($option = '', $arraydata = null)
1119 {
1120 global $mysoc;
1121
1122 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
1123
1124 $return = '<div class="box-flex-item box-flex-grow-zero">';
1125 $return .= '<div class="info-box info-box-sm">';
1126 $return .= '<span class="info-box-icon bg-infobox-action">';
1127 $return .= img_picto('', $this->picto);
1128 $return .= '</span>';
1129 $return .= '<div class="info-box-content">';
1130 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).'</span>';
1131 if ($selected >= 0) {
1132 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
1133 }
1134 if (property_exists($this, 'fk_recruitmentjobposition')) {
1135 $return .= '<br>';
1136 //$return .= '<span class="opacitymedium">';
1137 //$return .= $langs->trans('Job').'</span> : ';
1138 $return .= '<div class="info-box-label tdoverflowmax150">';
1139 $tmpjob = new RecruitmentJobPosition($this->db);
1140 $tmpjob->fetch($this->fk_recruitmentjobposition);
1141 //$return .= $this->fk_recruitmentjobposition;
1142 $return .= dolPrintHTML($tmpjob->label);
1143 $return .= '</div>';
1144 }
1145 if (property_exists($this, 'phone') && $this->phone) {
1146 $return .= '<div class="info-box-label small">'.dol_print_phone($this->phone, $mysoc->country_code, 0, 0, 'AC_TEL', '&nbsp;', 'phone').'</div>';
1147 }
1148 if (property_exists($this, 'email') && $this->email) {
1149 $return .= '<div class="info-box-label small">'.dol_print_email($this->email, 0, 0, 1, 64, 1, 1).'</div>';
1150 }
1151 if (method_exists($this, 'getLibStatut')) {
1152 $return .= '<div class="info-box-status">'.$this->getLibStatut(3).'</div>';
1153 }
1154 $return .= '</div>';
1155 $return .= '</div>';
1156 $return .= '</div>';
1157 return $return;
1158 }
1159}
1160
1161
1162require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
1163
1168{
1169 // To complete with content of an object RecruitmentCandidatureLine
1170 // We should have a field rowid, fk_recruitmentcandidature and position
1171
1177 public function __construct(DoliDB $db)
1178 {
1179 $this->db = $db;
1180 }
1181}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:58
$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.
Parent class for class inheritance lines of business objects This class is useless for the moment so ...
Class to manage Dolibarr database access.
Class for RecruitmentCandidature.
getLinesArray()
Create an array of lines.
createFromClone(User $user, $fromid)
Clone an object into another one.
cancel($user, $notrigger=0)
Set cancel status.
doScheduledJob()
Action executed by scheduler CAN BE A CRON TASK.
getKanbanView($option='', $arraydata=null)
Return clickable link of object (with eventually picto)
getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='', $save_lastsearch_value=-1)
Return a link to the object card (with optionally the picto)
getNextNumRef()
Returns the reference to the following non used object depending on the active numbering module.
reopen($user, $notrigger=0)
Set back to validated status.
initAsSpecimen()
Initialise object with example values Id must be 0 if object instance is a specimen.
getLibStatut($mode=0)
Return label of the status.
fetch($id, $ref=null, $email_msgid='')
Load object in memory from the database.
fetchLines()
Load object lines in memory from the database.
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
Create a document onto disk according to template module.
update(User $user, $notrigger=0)
Update object into database.
validate($user, $notrigger=0)
Validate object.
deleteLine(User $user, $idline, $notrigger=0)
Delete a line of object in database.
LibStatut($status, $mode=0)
Return the status.
fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, $filter='', $filtermode='AND')
Load list of objects in memory from the database.
getFullName($langs, $option=0, $nameorder=-1, $maxlen=0)
Return full name ('name+' '+lastname)
setDraft($user, $notrigger=0)
Set draft status.
create(User $user, $notrigger=0)
Create object into database.
info($id)
Load the info information in the object.
Class RecruitmentCandidatureLine.
Class for RecruitmentJobPosition.
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:162
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as p label as s rowid as s nom as s email
Sender: Who sends the email ("Sender" has sent emails on behalf of "From").
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)
dolPrintHTML($s, $allowiframe=0)
Return a string (that can be on several lines) ready to be output on a HTML page.
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.
dolGetFirstLastname($firstname, $lastname, $nameorder=-1)
Return firstname and lastname in correct order.
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...
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:140