Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,9 @@
NEW: Accountancy - Allow grouping taxes with primary line price (#26732)
NEW: Activate PHPUnit with tests on permission on $action ==...
NEW: Add advice for max size on list for better performance
NEW: Holiday module - Option "Les demandes de congés requièrent une double validation" in module settings
NEW: Approbation de niveau 2 des demandes de congés
NEW: Holiday module - Add "Responsable de seconde approbation" responsible field on holiday card

Check failure on line 457 in ChangeLog

View workflow job for this annotation

GitHub Actions / pre-commit / pre-commit

Responsable ==> Responsible

Check failure on line 457 in ChangeLog

View workflow job for this annotation

GitHub Actions / pre-commit / pre-commit

Responsable ==> Responsible
NEW: Add an advanced permission to validate knowledge (#30855)
NEW: Add a test mode into the setup of AI module to test the AI prompts.
NEW: Add a tool to decrypt data encrypted in database.
Expand Down
19 changes: 19 additions & 0 deletions htdocs/admin/holiday.php
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,8 @@
print "</td>";
print "</tr>";

// EN: Display toggle to consume holiday balance at end of month.
// FR: Affiche le bascule pour consommer le solde de congés en fin de mois.
// Set holiday decrease at the end of month
print '<tr class="oddeven">';
print "<td>".$langs->trans("ConsumeHolidaysAtTheEndOfTheMonthTheyAreTakenAt").' <span class="opacitymedium">('.$langs->trans("ConsumeHolidaysAtTheEndOfTheMonthTheyAreTakenAtBis").')</span></td>';
Expand All @@ -545,6 +547,23 @@
print "</td>";
print "</tr>";

// EN: Display toggle to require double approval for leave requests.
// FR: Affiche le bascule pour exiger une double validation des demandes de congés.
print '<tr class="oddeven">';
print "<td>".$langs->trans("HolidayRequireDoubleApproval")."</td>";
print '<td class="center">';
if ($conf->use_javascript_ajax) {
print ajax_constantonoff('HOLIDAY_REQUIRE_DOUBLE_APPROVAL', array(), null, 0, 0, 0, 2, 0, 1);
} else {
if (getDolGlobalString('HOLIDAY_REQUIRE_DOUBLE_APPROVAL')) {
print '<a href="'.$_SERVER['PHP_SELF'].'?action=set_other&token='.newToken().'&HOLIDAY_REQUIRE_DOUBLE_APPROVAL=1">'.img_picto($langs->trans("Enabled"), 'on').'</a>';
} else {
print '<a href="'.$_SERVER['PHP_SELF'].'?action=set_other&token='.newToken().'&HOLIDAY_REQUIRE_DOUBLE_APPROVAL=0">'.img_picto($langs->trans("Disabled"), 'off').'</a>';
}
}
print "</td>";
print "</tr>";

if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) {
$substitutionarray = pdf_getSubstitutionArray($langs, array('objectamount'), null, 2);
$substitutionarray['__(AnyTranslationKey)__'] = $langs->trans("Translation");
Expand Down
9 changes: 9 additions & 0 deletions htdocs/core/modules/modHoliday.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,15 @@ public function __construct($db)
$this->rights[$r][4] = 'approve';
$r++;

// EN: Add level 2 approval permission for double validation
// FR: Ajouter la permission d'approbation de niveau 2 pour la double validation
$this->rights[$r][0] = 20008;
$this->rights[$r][1] = 'PermissionHolidayDoubleApproval';
$this->rights[$r][2] = 'w';
$this->rights[$r][3] = 0;
$this->rights[$r][4] = 'approvelevel2';
$r++;

$this->rights[$r][0] = 20004; // Permission id (must not be already used)
$this->rights[$r][1] = 'Read leave requests for everybody'; // Permission label
$this->rights[$r][3] = 0; // Permission by default for new user (0/1)
Expand Down
131 changes: 127 additions & 4 deletions htdocs/holiday/card.php
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@
}

$approverid = GETPOSTINT('valideur');
// EN: Capture the second approver from the request / FR: Récupérer le second valideur depuis la requête
$approverid2 = GETPOSTINT('valideur2');
$description = trim(GETPOST('description', 'restricthtml'));

// Check that leave is for a user inside the hierarchy or advanced permission for all is set
Expand Down Expand Up @@ -278,6 +280,18 @@
setEventMessages($langs->transnoentitiesnoconv('InvalidValidator'), null, 'errors');
$error++;
}
// EN: Allow selection of the second approver / FR: Autoriser la sélection du second valideur

Check failure on line 283 in htdocs/holiday/card.php

View workflow job for this annotation

GitHub Actions / pre-commit / pre-commit

Line indented incorrectly; expected at least 2 tabs, found 1
if (getDolGlobalString('HOLIDAY_REQUIRE_DOUBLE_APPROVAL')) {

Check failure on line 284 in htdocs/holiday/card.php

View workflow job for this annotation

GitHub Actions / pre-commit / pre-commit

Line indented incorrectly; expected 2 tabs, found 1
// EN: Validate the chosen second approver / FR: Valider le second valideur sélectionné
if ($approverid2 < 1) {
setEventMessages($langs->trans('SecondApproverRequired'), null, 'errors');
$error++;
}
if (!empty($approverslist) && !in_array($approverid2, $approverslist)) {
setEventMessages($langs->trans('InvalidSecondValidatorCP'), null, 'errors');
$error++;
}
}

Check failure on line 294 in htdocs/holiday/card.php

View workflow job for this annotation

GitHub Actions / pre-commit / pre-commit

Closing brace indented incorrectly; expected 4 spaces, found 8

// Fill array 'array_options' with data from add form
$ret = $extrafields->setOptionalsFromPost(null, $object);
Expand All @@ -291,6 +305,13 @@
$object->fk_user = $fuserid;
$object->description = $description;
$object->fk_validator = $approverid;
// EN: Offer edition of the second approver / FR: Permettre l'édition du second valideur

Check failure on line 308 in htdocs/holiday/card.php

View workflow job for this annotation

GitHub Actions / pre-commit / pre-commit

Line indented incorrectly; expected at least 3 tabs, found 2
if (getDolGlobalString('HOLIDAY_REQUIRE_DOUBLE_APPROVAL')) {

Check failure on line 309 in htdocs/holiday/card.php

View workflow job for this annotation

GitHub Actions / pre-commit / pre-commit

Line indented incorrectly; expected 3 tabs, found 2
// EN: Keep the expected second approver / FR: Conserver le second valideur prévu
$object->fk_user_approve2 = ($approverid2 > 0 ? $approverid2 : 0);
} else {

Check failure on line 312 in htdocs/holiday/card.php

View workflow job for this annotation

GitHub Actions / pre-commit / pre-commit

Closing brace indented incorrectly; expected 8 spaces, found 12
$object->fk_user_approve2 = 0;
}
$object->fk_type = $type;
$object->date_debut = $date_debut;
$object->date_fin = $date_fin;
Expand Down Expand Up @@ -322,8 +343,26 @@
$object->oldcopy = dol_clone($object, 2); // @phan-suppress-current-line PhanTypeMismatchProperty

$object->fk_validator = GETPOSTINT('valideur');
// EN: Capture the second approver during quick edit / FR: Récupérer le second valideur lors de l'édition rapide
$approverid2 = GETPOSTINT('valideur2');
$localerror = 0;
if (getDolGlobalString('HOLIDAY_REQUIRE_DOUBLE_APPROVAL')) {
// EN: Validate and store the second approver during quick edit / FR: Valider et enregistrer le second valideur lors de l'édition rapide
if ($approverid2 < 1) {
setEventMessages($langs->trans('SecondApproverRequired'), null, 'warnings');
$localerror++;
}
$approverslist = $object->fetch_users_approver_holiday();
if (!empty($approverslist) && !in_array($approverid2, $approverslist)) {
setEventMessages($langs->trans('InvalidSecondValidatorCP'), null, 'warnings');
$localerror++;
}
$object->fk_user_approve2 = ($approverid2 > 0 ? $approverid2 : 0);
} else {
$object->fk_user_approve2 = 0;
}

if ($object->fk_validator != $object->oldcopy->fk_validator) {
if (!$localerror && ($object->fk_validator != $object->oldcopy->fk_validator || $object->fk_user_approve2 != $object->oldcopy->fk_user_approve2)) {
$verif = $object->update($user);

if ($verif <= 0) {
Expand All @@ -333,6 +372,8 @@
header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
exit;
}
} elseif ($localerror) {
$action = 'editvalidator';
}

$action = '';
Expand Down Expand Up @@ -376,6 +417,8 @@
// If this is the requester or has read/write rights
if ($permissiontoadd) {
$approverid = GETPOSTINT('valideur');
// EN: Capture the second approver during edition / FR: Récupérer le second valideur lors de l'édition
$approverid2 = GETPOSTINT('valideur2');
// TODO Check this approver user id has the permission for approval

$description = trim(GETPOST('description', 'restricthtml'));
Expand All @@ -400,6 +443,20 @@
$error++;
$action = 'edit';
}
if (getDolGlobalString('HOLIDAY_REQUIRE_DOUBLE_APPROVAL')) {
// EN: Validate the second approver while editing / FR: Valider le second valideur lors de l'édition
if ($approverid2 < 1) {
setEventMessages($langs->trans('SecondApproverRequired'), null, 'warnings');
$error++;
$action = 'edit';
}
$approverslist = $object->fetch_users_approver_holiday();
if (!empty($approverslist) && !in_array($approverid2, $approverslist)) {
setEventMessages($langs->trans('InvalidSecondValidatorCP'), null, 'warnings');
$error++;
$action = 'edit';
}
}

// If there is no Business Days within request
$nbopenedday = num_open_day($date_debut_gmt, $date_fin_gmt, 0, 1, $halfday);
Expand All @@ -416,6 +473,12 @@
$object->date_debut = $date_debut;
$object->date_fin = $date_fin;
$object->fk_validator = $approverid;
if (getDolGlobalString('HOLIDAY_REQUIRE_DOUBLE_APPROVAL')) {
// EN: Keep the updated second approver / FR: Conserver le second valideur à jour
$object->fk_user_approve2 = ($approverid2 > 0 ? $approverid2 : 0);
} else {
$object->fk_user_approve2 = 0;
}
$object->halfday = $halfday;

// Update
Expand Down Expand Up @@ -1207,6 +1270,10 @@

$object = new Holiday($db);
$include_users = $object->fetch_users_approver_holiday();
// EN: Normalize the approvers list / FR: Normaliser la liste des valideurs

Check failure on line 1273 in htdocs/holiday/card.php

View workflow job for this annotation

GitHub Actions / pre-commit / pre-commit

Line indented incorrectly; expected at least 2 tabs, found 1
if (!is_array($include_users)) {

Check failure on line 1274 in htdocs/holiday/card.php

View workflow job for this annotation

GitHub Actions / pre-commit / pre-commit

Line indented incorrectly; expected 2 tabs, found 1
$include_users = array();

Check failure on line 1275 in htdocs/holiday/card.php

View workflow job for this annotation

GitHub Actions / pre-commit / pre-commit

Line indented incorrectly; expected at least 3 tabs, found 2
}
if (empty($include_users)) {
print img_warning().' '.$langs->trans("NobodyHasPermissionToValidateHolidays");
} else {
Expand All @@ -1224,9 +1291,26 @@
}

//print $form->select_dolusers((GETPOST('valideur','int')>0?GETPOST('valideur','int'):$user->fk_user), "valideur", 1, ($user->admin ? '' : array($user->id)), 0, '', 0, 0, 0, 0, '', 0, '', '', 1); // By default, hierarchical parent
print '</td>';
print '</tr>';

print '</td>';
print '</tr>';
// EN: Allow selection of the second approver / FR: Autoriser la sélection du second valideur
if (getDolGlobalString('HOLIDAY_REQUIRE_DOUBLE_APPROVAL')) {
print '<tr>';
print '<td class="fieldrequired">'.$langs->trans("SecondApprovalResponsible").'</td>';
print '<td>';
if (empty($include_users)) {
print img_warning().' '.$langs->trans("NobodyHasPermissionToValidateHolidays");
} else {
$defaultselectuser2 = GETPOSTINT('valideur2');
if (empty($defaultselectuser2) && !empty($defaultselectuser)) {
$defaultselectuser2 = $defaultselectuser;
}
$s2 = $form->select_dolusers($defaultselectuser2, "valideur2", 1, '', 0, $include_users, '', '0,'.$conf->entity, 0, 0, '', 0, '', 'minwidth200 maxwidth500');
print img_picto('', 'user', 'class="pictofixedwidth"').$form->textwithpicto($s2, $langs->trans("AnyOtherInThisListCanValidate"));
}
print '</td>';
print '</tr>';
}
// Description
print '<tr>';
print '<td>'.$langs->trans("DescCP").'</td>';
Expand Down Expand Up @@ -1259,6 +1343,11 @@

$approverexpected = new User($db);
$approverexpected->fetch($object->fk_validator); // Use that should be the approver
$secondapproverexpected = new User($db);
if ($object->fk_user_approve2 > 0) {
// EN: Preload the second approver / FR: Précharger le second valideur
$secondapproverexpected->fetch($object->fk_user_approve2);
}

$userRequest = new User($db);
$userRequest->fetch($object->fk_user);
Expand Down Expand Up @@ -1491,11 +1580,29 @@
}
print '</td>';
print '</tr>';

// EN: Display the second approver / FR: Afficher le second valideur
if (getDolGlobalString('HOLIDAY_REQUIRE_DOUBLE_APPROVAL')) {
print '<tr>';
print '<td class="titlefield">'.$langs->trans("SecondApprovalResponsible").'</td>';
print '<td>';
if ($object->fk_user_approve2 > 0) {
print $secondapproverexpected->getNomUrl(-1);
} else {
print $langs->trans('None');
}
print '</td>';
print '</tr>';
}
} else {
print '<tr>';
print '<td class="titlefield">'.$langs->trans('ReviewedByCP').'</td>'; // Will be approved by
print '<td>';
$include_users = $object->fetch_users_approver_holiday();
// EN: Normalize the approvers list / FR: Normaliser la liste des valideurs
if (!is_array($include_users)) {
$include_users = array();
}
if (!in_array($object->fk_validator, $include_users)) { // Add the current validator to the list to not lose it when editing.
$include_users[] = $object->fk_validator;
}
Expand All @@ -1505,6 +1612,22 @@
$arrayofvalidatorstoexclude = (($user->admin || ($user->id != $userRequest->id)) ? '' : array($user->id)); // We exclude ourself from validator list. Not if we are admin or if we are on the leave of someone else
$s = $form->select_dolusers($object->fk_validator, "valideur", (($action == 'editvalidator') ? 0 : 1), $arrayofvalidatorstoexclude, 0, $include_users);
print $form->textwithpicto($s, $langs->trans("AnyOtherInThisListCanValidate"));
// EN: Offer edition of the second approver / FR: Permettre l'édition du second valideur
if (getDolGlobalString('HOLIDAY_REQUIRE_DOUBLE_APPROVAL')) {
if (!in_array($object->fk_user_approve2, $include_users)) {
$include_users[] = $object->fk_user_approve2;
}
// EN: Fetch the proposed second approver / FR: Récupérer le second valideur proposé
$defaultselectuser2 = $object->fk_user_approve2;
// EN: Preserve the posted value for the second approver / FR: Conserver la valeur transmise pour le second valideur
if ($action == 'editvalidator' && GETPOSTINT('valideur2') > 0) {
// EN: Refresh the second approver with the posted value / FR: Actualiser le second valideur avec la valeur transmise
$defaultselectuser2 = GETPOSTINT('valideur2');
}
$s2 = $form->select_dolusers($defaultselectuser2, "valideur2", (($action == 'editvalidator') ? 0 : 1), $arrayofvalidatorstoexclude, 0, $include_users);
print '<div class="paddingleft">'.$form->textwithpicto($s2, $langs->trans("AnyOtherInThisListCanValidate")).'</div>';
}

}
if ($action == 'editvalidator') {
print '<input type="submit" class="button button-save" name="savevalidator" value="'.$langs->trans("Save").'">';
Expand Down
Loading
Loading