Skip to content
Merged
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 - Option to select the label of operation (#31200)
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 "Responsible de seconde approbation" responsible field on holiday card
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
127 changes: 125 additions & 2 deletions htdocs/holiday/card.php
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@
}

$approverid = GETPOSTINT('valideur');
// Capture the second approver from the request
$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++;
}
// Allow selection of the second approver
if (getDolGlobalString('HOLIDAY_REQUIRE_DOUBLE_APPROVAL')) {
// Validate the chosen second approver
if ($approverid2 < 1) {
setEventMessages($langs->trans('SecondApproverRequired'), null, 'errors');
$error++;
}
if (!empty($approverslist) && !in_array($approverid2, $approverslist)) {
setEventMessages($langs->trans('InvalidSecondValidatorCP'), null, 'errors');
$error++;
}
}

// 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;
// Offer edition of the second approver

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
// Keep the expected second approver

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

View workflow job for this annotation

GitHub Actions / pre-commit / pre-commit

Line indented incorrectly; expected at least 4 tabs, found 3
$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');
// Capture the second approver during quick edit
$approverid2 = GETPOSTINT('valideur2');
$localerror = 0;
if (getDolGlobalString('HOLIDAY_REQUIRE_DOUBLE_APPROVAL')) {
// Validate and store the second approver during quick edit
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');
// Capture the second approver during edition
$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')) {
// Validate the second approver while editing
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')) {
// Keep the updated second approver
$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();
// Normalize the approvers list
if (!is_array($include_users)) {
$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 @@ -1226,7 +1293,24 @@
//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>';

// Allow selection of the second approver
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');

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

View workflow job for this annotation

GitHub Actions / phan / Run phan

PhanTypeMismatchArgument Argument 4 ($exclude) is '' of type '' but \Form::select_dolusers() takes int[]|null defined at htdocs/core/class/html.form.class.php:2207
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) {
// Preload the second approver
$secondapproverexpected->fetch($object->fk_user_approve2);
}

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

// Display the second approver

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

View workflow job for this annotation

GitHub Actions / pre-commit / pre-commit

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

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

View workflow job for this annotation

GitHub Actions / pre-commit / pre-commit

Line indented incorrectly; expected 5 tabs, found 4
print '<tr>';

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

View workflow job for this annotation

GitHub Actions / pre-commit / pre-commit

Line indented incorrectly; expected at least 6 tabs, found 5
print '<td class="titlefield">'.$langs->trans("SecondApprovalResponsible").'</td>';

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

View workflow job for this annotation

GitHub Actions / pre-commit / pre-commit

Line indented incorrectly; expected at least 6 tabs, found 5
print '<td>';

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

View workflow job for this annotation

GitHub Actions / pre-commit / pre-commit

Line indented incorrectly; expected at least 6 tabs, found 5
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();
// Normalize the approvers list
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;
}
if (empty($include_users)) {

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

View workflow job for this annotation

GitHub Actions / phpstan / php-stan (8.2)

Variable $include_users in empty() always exists and is not falsy.
print img_warning().' '.$langs->trans("NobodyHasPermissionToValidateHolidays");
} else {
$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"));
// Offer edition of the second approver
if (getDolGlobalString('HOLIDAY_REQUIRE_DOUBLE_APPROVAL')) {
if (!in_array($object->fk_user_approve2, $include_users)) {
$include_users[] = $object->fk_user_approve2;
}
// Fetch the proposed second approver
$defaultselectuser2 = $object->fk_user_approve2;
// Preserve the posted value for the second approver
if ($action == 'editvalidator' && GETPOSTINT('valideur2') > 0) {
// Refresh the second approver with the posted value
$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