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