2
0
forked from Wavyzz/dolibarr

New create public page for recruitment candidature (#31220)

* New creation of public recruitement candidature

* Fix some problems

* fix lang file

* Fix CI

* Fix CI

---------

Co-authored-by: Hystepik <lmarcouiller@nltechno.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
This commit is contained in:
Lucas Marcouiller
2024-10-04 09:00:17 +02:00
committed by GitHub
parent 8e62fe4241
commit b595b30a5b
7 changed files with 151 additions and 48 deletions

View File

@@ -52,7 +52,11 @@ function checkNbPostsForASpeceificIp($object, $nb_post_max)
$sql = "SELECT COUNT(".(!empty($object->table_rowid) ? $object->table_rowid : 'rowid').") as nb_posts";
$sql .= " FROM ".MAIN_DB_PREFIX.$object->table_element;
$sql .= " WHERE ip = '".$db->escape($object->ip)."'";
if (array_key_exists('date_creation', $object->fields)) {
$sql .= " AND date_creation > '".$db->idate($minmonthpost)."'";
} else {
$sql .= " AND datec > '".$db->idate($minmonthpost)."'";
}
$resql = $db->query($sql);
if ($resql) {
$num = $db->num_rows($resql);

View File

@@ -132,4 +132,7 @@ ALTER TABLE llx_societe ADD COLUMN ip varchar(250);
ALTER TABLE llx_recruitment_recruitmentcandidature ADD COLUMN ip varchar(250);
ALTER TABLE llx_socpeople ADD COLUMN ip varchar(250);
ALTER TABLE llx_recruitment_recruitmentcandidature MODIFY fk_user_creat integer NULL;
ALTER TABLE llx_ecm_files ADD COLUMN agenda_id integer;

View File

@@ -25,7 +25,7 @@ CREATE TABLE llx_recruitment_recruitmentcandidature(
note_private text,
date_creation datetime NOT NULL,
tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
fk_user_creat integer NOT NULL,
fk_user_creat integer,
fk_user_modif integer,
fk_user integer, -- Id of user created from the job application
import_key varchar(14),

View File

@@ -64,4 +64,7 @@ NoPositionOpen=No positions open at the moment
ConfirmClose=Confirm cancellation
ConfirmCloseAsk=Are you sure you want to cancel this recruitment candidature
Recruitment=Recruitment
ApplyJobCandidature=Apply for this job
ErrorRecruitmmentCandidatureAlreadyExists= Recruitment candidature already exists with email %s
RecruitmentCandidatureSaved=Recruitement candidature successfully saved
NoOpenJobOffer=No open job offers at the moment

View File

@@ -174,6 +174,7 @@ if (getDolGlobalString('RECRUITMENT_IMAGE_PUBLIC_INTERFACE')) {
$results = $object->fetchAll($sortorder, $sortfield, 0, 0, '(status:=:1)');
$now = dol_now();
$params = array();
if (is_array($results)) {
if (empty($results)) {
@@ -187,6 +188,7 @@ if (is_array($results)) {
foreach ($results as $job) {
$object = $job;
$arrayofpostulatebutton = array();
print '<table id="dolpaymenttable" summary="Job position offer" class="center">'."\n";
@@ -274,6 +276,17 @@ if (is_array($results)) {
print $text;
print '<input type="hidden" name="ref" value="'.$object->ref.'">';
$arrayofpostulatebutton[] = array(
'url' => '/public/recruitment/view.php?ref='.$object->ref,
'label' => $langs->trans('ApplyJobCandidature'),
'lang' => 'recruitment',
'perm' => true,
'enabled' => true,
);
print '<div class="center">';
print dolGetButtonAction('', $langs->trans("ApplyJobCandidature"), 'default', $arrayofpostulatebutton, 'applicate_'.$object->ref, true, $params);
print '</div>';
print '</div>'."\n";
print "\n";

View File

@@ -38,10 +38,12 @@ if (!defined('NOBROWSERNOTIF')) {
// Load Dolibarr environment
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/recruitment/class/recruitmentjobposition.class.php';
require_once DOL_DOCUMENT_ROOT.'/recruitment/class/recruitmentcandidature.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
require_once DOL_DOCUMENT_ROOT . '/core/lib/public.lib.php';
// Load translation files required by the page
$langs->loadLangs(array("companies", "other", "recruitment"));
@@ -50,7 +52,12 @@ $langs->loadLangs(array("companies", "other", "recruitment"));
$action = GETPOST('action', 'aZ09');
$cancel = GETPOST('cancel', 'alpha');
$email = GETPOST('email', 'alpha');
$backtopage = '';
$firstname = GETPOST('firstname', 'alpha');
$lastname = GETPOST('lastname', 'alpha');
$birthday = GETPOST('birthday', 'alpha');
$phone = GETPOST('phone', 'alpha');
$message = GETPOST('message', 'alpha');
$requestedremuneration = GETPOST('requestedremuneration', 'alpha');
$ref = GETPOST('ref', 'alpha');
@@ -63,25 +70,26 @@ if (isset($_SESSION['email_customer'])) {
$object = new RecruitmentJobPosition($db);
if (!$action) {
if (!$ref) {
if (!$ref) {
print $langs->trans('ErrorBadParameters')." - ref missing";
exit;
} else {
$object->fetch('', $ref);
}
}
// Define $urlwithroot
//$urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root));
//$urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
$urlwithroot = DOL_MAIN_URL_ROOT; // This is to use same domain name than current. For Paypal payment, we can use internal URL like localhost.
$backtopage = $urlwithroot.'/public/recruitment/index.php';
// Security check
if (empty($conf->recruitment->enabled)) {
if (!isModEnabled("recruitment")) {
httponly_accessforbidden('Module Recruitment not enabled');
}
$object->fetch('', $ref);
$user->loadDefaultValues();
$errmsg = "";
/*
* Actions
@@ -92,56 +100,95 @@ if ($cancel) {
header("Location: ".$backtopage);
exit;
}
$action = 'view';
}
if ($action == "view" || $action == "presend" || $action == "dosubmit") { // Test on permission not required here (anonymous action protected by mitigation of /public/... urls)
if ($action == "dosubmit") { // Test on permission not required here (anonymous action protected by mitigation of /public/... urls)
$error = 0;
$display_ticket = false;
$db->begin();
if (!strlen($ref)) {
$error++;
array_push($object->errors, $langs->trans("ErrorFieldRequired", $langs->transnoentities("Ref")));
$action = '';
$action = 'view';
}
if (!strlen($email)) {
$error++;
array_push($object->errors, $langs->trans("ErrorFieldRequired", $langs->transnoentities("Email")));
$action = '';
$action = 'view';
} else {
if (!isValidEmail($email)) {
$error++;
array_push($object->errors, $langs->trans("ErrorEmailInvalid"));
$action = '';
$action = 'view';
}
}
if (!strlen($lastname)) {
$error++;
array_push($object->errors, $langs->trans("ErrorFieldRequired", $langs->transnoentities("Lastname")));
$action = 'view';
}
if (!$error) {
$sql = "SELECT rrc.rowid FROM ".MAIN_DB_PREFIX."recruitment_recruitmentcandidature as rrc";
$sql .= " WHERE rrc.email = '". $db->escape($email)."'";
$sql .= " AND rrc.entity = ". getEntity($object->element, 0);
$resql = $db->query($sql);
if ($resql) {
$num = $db->num_rows($resql);
if ($num > 0) {
$error++;
setEventMessages($langs->trans("ErrorRecruitmmentCandidatureAlreadyExists", $email), null, 'errors');
}
} else {
dol_print_error($db);
$error++;
}
}
if (!$error) { // Test on permission not required here (anonymous action protected by mitigation of /public/... urls)
$candidature = new RecruitmentCandidature($db);
$candidature->firstname = GETPOST('firstname', 'alpha');
$candidature->lastname = GETPOST('lastname', 'alpha');
$candidature->email = GETPOST('email', 'alpha');
$candidature->phone = GETPOST('phone', 'alpha');
$candidature->date_birth = GETPOST('birthday', 'alpha');
$candidature->requestedremuneration = GETPOST('requestedremuneration', 'alpha');
$candidature->description = GETPOST('message', 'alpha');
$candidature->fk_recruitmentjobposition = $object->id;
$candidature->ip = getUserRemoteIP();
// Test MAIN_SECURITY_MAX_POST_ON_PUBLIC_PAGES_BY_IP_ADDRESS
$nb_post_max = getDolGlobalInt("MAIN_SECURITY_MAX_POST_ON_PUBLIC_PAGES_BY_IP_ADDRESS", 200);
if (checkNbPostsForASpeceificIp($candidature, $nb_post_max) <= 0) {
$error++;
$errmsg .= implode('<br>', $candidature->errors);
}
if (!$error) {
$result = $candidature->create($user);
if ($result <= 0) {
$error++;
$errmsg .= implode('<br>', $candidature->errors);
}
}
if (!$error) {
$candidature->validate($user);
if ($result <= 0) {
$error++;
$errmsg .= implode('<br>', $candidature->errors);
}
}
}
if (!$error) {
$ret = $object->fetch('', $ref);
}
/*
if (!$error && $action == "dosubmit") // Test on permission not required here (anonymous action protected by mitigation of /public/... urls)
{
// Test MAIN_SECURITY_MAX_POST_ON_PUBLIC_PAGES_BY_IP_ADDRESS
// TODO Create job application
if (!$error)
{
$action = 'view';
}
}
*/
if ($error || $errors) {
setEventMessages($object->error, $object->errors, 'errors');
if ($action == "dosubmit") { // Test on permission not required here
$action = 'presend';
$db->commit();
setEventMessages($langs->trans("RecruitmentCandidatureSaved"), null);
header("Location: " . $backtopage);
exit;
} else {
$action = '';
}
$db->rollback();
$action = "view";
}
}
@@ -158,6 +205,7 @@ include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
* View
*/
$form = new Form($db);
$now = dol_now();
$head = '';
@@ -180,7 +228,7 @@ $arrayofcss = array();
$replacemainarea = (empty($conf->dol_hide_leftmenu) ? '<div>' : '').'<div>';
llxHeader($head, $langs->trans("PositionToBeFilled"), '', '', 0, 0, '', '', '', 'onlinepaymentbody', $replacemainarea, 1, 1);
dol_htmloutput_errors($errmsg);
print '<span id="dolpaymentspan"></span>'."\n";
print '<div class="center">'."\n";
@@ -254,16 +302,16 @@ if (getDolGlobalString('RECRUITMENT_NEWFORM_TEXT')) {
$text = '<tr><td align="center"><br>'.$text.'<br></td></tr>'."\n";
}
if (empty($text)) {
$text .= '<tr><td class="textpublicpayment"><br>'.$langs->trans("JobOfferToBeFilled", $mysoc->name);
$text .= '<tr><td class="textpublicpayment" colspan=2><br>'.$langs->trans("JobOfferToBeFilled", $mysoc->name);
$text .= ' &nbsp; - &nbsp; <strong>'.$mysoc->name.'</strong>';
$text .= ' &nbsp; - &nbsp; <span class="nowraponall"><span class="fa fa-calendar secondary"></span> '.dol_print_date($object->date_creation).'</span>';
$text .= '</td></tr>'."\n";
$text .= '<tr><td class="textpublicpayment"><h1 class="paddingleft paddingright">'.$object->label.'</h1><br></td></tr>'."\n";
$text .= '<tr><td class="textpublicpayment" colspan=2><h1 class="paddingleft paddingright">'.$object->label.'</h1><br></td></tr>'."\n";
}
print $text;
// Output payment summary form
print '<tr><td class="left">';
print '<tr><td class="left" colspan=2>';
print '<div with="100%" id="tablepublicpayment">';
print '<div class="opacitymedium">'.$langs->trans("ThisIsInformationOnJobPosition").' :</div>'."\n";
@@ -333,6 +381,38 @@ print "\n";
if ($action != 'dosubmit') {
if ($found && !$error) {
// We are in a management option and no error
print '</td></tr>'."\n";
print '<tr><td class="titlefieldcreate fieldrequired left">'.$langs->trans("Lastname").'</td><td class="left">';
print '<input type="text" class="flat minwidth400 --success" name="lastname" maxlength="128" value="'.$lastname.'">';
print '</td></tr>'."\n";
print '<tr><td class="titlefieldcreate left">'.$langs->trans("Firstname").'</td><td class="left">';
print '<input type="text" class="flat minwidth400 --success" name="firstname" maxlength="128" value="'.$firstname.'">';
print '</td></tr>'."\n";
print '<tr><td class="titlefieldcreate fieldrequired left">'.$langs->trans("Email").'</td><td class="left">';
print img_picto("", "email").'<input type="text" class="flat minwidth100 --success" name="email" value="'.$email.'">';
print '</td></tr>'."\n";
print '<tr><td class="titlefieldcreate left">'.$langs->trans("Phone").'</td><td class="left">';
print img_picto("", "phone").'<input type="text" class="flat minwidth100 --success" name="phone" value="'.$phone.'">';
print '</td></tr>'."\n";
print '<tr><td class="titlefieldcreate left minwidth300">'.$langs->trans("DateOfBirth").'</td><td class="left">';
print $form->selectDate($birthday, 'birthday', 0, 0, 1, "", 1, 0);
print '</td></tr>'."\n";
print '<tr><td class="titlefieldcreate left">'.$langs->trans("RequestedRemuneration").'</td><td class="left">';
print '<input type="text" class="flat minwidth100 --success" name="requestedremuneration" value="'.$requestedremuneration.'">';
print '</td></tr>'."\n";
print '<tr><td class="titlefieldcreate left">'.$langs->trans("Message").'</td><td class="left">';
print '<textarea class="flat quatrevingtpercent" rows="'.ROWS_5.'" name="message">'.$message.'</textarea>';
print '</td></tr>'."\n";
print '<tr><td colspan=2>';
print $form->buttonsSaveCancel('Submit', 'Cancel');
print '</td></tr>'."\n";
} else {
dol_print_error_email('ERRORSUBMITAPPLICATION');
}

View File

@@ -105,7 +105,7 @@ class RecruitmentCandidature extends CommonObject
'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'),
'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'position' => 61, 'notnull' => 0, 'visible' => 0,),
'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'position' => 62, 'notnull' => 0, 'visible' => 0,),
'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'),
'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'),
'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'position' => 511, 'notnull' => -1, 'visible' => -2, 'csslist' => 'tdoverflowmax100'),
'lastname' => array('type' => 'varchar(128)', 'label' => 'Lastname', 'enabled' => 1, 'position' => 20, 'notnull' => 0, 'visible' => 1, 'csslist' => 'tdoverflowmax150'),
'firstname' => array('type' => 'varchar(128)', 'label' => 'Firstname', 'enabled' => 1, 'position' => 21, 'notnull' => 0, 'visible' => 1, 'csslist' => 'tdoverflowmax150'),