Skip to content

Commit

Permalink
Inactive people by class (#7009)
Browse files Browse the repository at this point in the history
  • Loading branch information
DawoudIO authored May 8, 2024
2 parents cdd66b2 + 7855ad6 commit ee4855d
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
describe('template spec', () => {
it('filter-by-classification', () => {
cy.loginAdmin("OptionManager.php?mode=classes");
cy.get("#inactive4").uncheck();
cy.get("#inactive5").uncheck();
cy.reload();
cy.get("#inactive1").should('not.be.checked');
cy.get("#inactive2").should('not.be.checked');
cy.get("#inactive3").should('not.be.checked');
cy.get("#inactive4").should('not.be.checked');
cy.get("#inactive5").should('not.be.checked');

cy.visit("v2/people?familyActiveStatus=inactive");
cy.get("#members_filter input").type("edwin.adams@example.com");
cy.contains("No matching records found");

cy.visit("v2/people?familyActiveStatus=all");
cy.get("#members_filter input").type("edwin.adams@example.com");
cy.contains("(564)-714-4633");

cy.visit("v2/people");
cy.get("#members_filter input").type("edwin.adams@example.com");
cy.contains("(564)-714-4633");

cy.visit("OptionManager.php?mode=classes");
cy.get("#inactive4").check();
cy.reload();
cy.get("#inactive1").should('not.be.checked');
cy.get("#inactive2").should('not.be.checked');
cy.get("#inactive3").should('not.be.checked');
cy.get("#inactive4").should('be.checked');
cy.get("#inactive5").should('not.be.checked');

cy.visit("v2/people?familyActiveStatus=inactive");
cy.get("#members_filter input").type("edwin.adams@example.com");
cy.contains("No matching records found");

cy.visit("v2/people?familyActiveStatus=all");
cy.get("#members_filter input").type("edwin.adams@example.com");
cy.contains("(564)-714-4633");

cy.visit("v2/people");
cy.get("#members_filter input").type("edwin.adams@example.com");
cy.contains("(564)-714-4633");

cy.visit("OptionManager.php?mode=classes");
cy.get("#inactive5").check();
cy.reload();
cy.get("#inactive1").should('not.be.checked');
cy.get("#inactive2").should('not.be.checked');
cy.get("#inactive3").should('not.be.checked');
cy.get("#inactive4").should('be.checked');
cy.get("#inactive5").should('be.checked');

cy.visit("v2/people?familyActiveStatus=inactive");
cy.get("#members_filter input").type("edwin.adams@example.com");
cy.contains("(564)-714-4633");

cy.visit("v2/people?familyActiveStatus=all");
cy.get("#members_filter input").type("edwin.adams@example.com");
cy.contains("(564)-714-4633");

cy.visit("v2/people");
cy.get("#members_filter input").type("edwin.adams@example.com");
cy.contains("No matching records found");

cy.visit("OptionManager.php?mode=classes");
cy.get("#inactive4").uncheck();
cy.get("#inactive5").uncheck();
cy.reload();
cy.get("#inactive1").should('not.be.checked');
cy.get("#inactive2").should('not.be.checked');
cy.get("#inactive3").should('not.be.checked');
cy.get("#inactive4").should('not.be.checked');
cy.get("#inactive5").should('not.be.checked');
});
});
3 changes: 2 additions & 1 deletion src/ChurchCRM/dto/SystemConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ private static function buildConfigs(): array
's2FAApplicationName' => new ConfigItem(2070, 's2FAApplicationName', 'text', gettext('ChurchCRM'), gettext('Specify the application name to be displayed in authenticator app')),
'bSendUserDeletedEmail' => new ConfigItem(2071, 'bSendUserDeletedEmail', 'boolean', '0', gettext('Send an email notifying users when their account has been deleted')),
'sGoogleMapsRenderKey' => new ConfigItem(2072, 'sGoogleMapsRenderKey', 'text', '', gettext('Google Maps API Key used for rendering maps in browser'), 'https://developers.google.com/maps/documentation/javascript/get-api-key'),
'sInactiveClassification' => new ConfigItem(2073, 'sInactiveClassification', 'text', '', gettext('Comma separated list of classifications that should appear as inactive')),
'sDefaultZip' => new ConfigItem(2074, 'sDefaultZip', 'text', '', gettext('Default Zip')),
];
}
Expand All @@ -275,7 +276,7 @@ private static function buildCategories(): array
gettext('Church Information') => ['sChurchName', 'sChurchAddress', 'sChurchCity', 'sChurchState', 'sChurchZip', 'sChurchCountry', 'sChurchPhone', 'sChurchEmail', 'sHomeAreaCode', 'sTimeZone', 'iChurchLatitude', 'iChurchLongitude', 'sChurchWebSite', 'sChurchFB', 'sChurchTwitter'],
gettext('User Setup') => ['iMinPasswordLength', 'iMinPasswordChange', 'iMaxFailedLogins', 'iSessionTimeout', 'aDisallowedPasswords', 'bEnableLostPassword', 'bEnable2FA', 'bRequire2FA', 's2FAApplicationName', 'bSendUserDeletedEmail'],
gettext('Email Setup') => ['sSMTPHost', 'bSMTPAuth', 'sSMTPUser', 'sSMTPPass', 'iSMTPTimeout', 'sToEmailAddress', 'bPHPMailerAutoTLS', 'sPHPMailerSMTPSecure'],
gettext('People Setup') => ['sDirClassifications', 'sDirRoleHead', 'sDirRoleSpouse', 'sDirRoleChild', 'sDefaultCity', 'sDefaultState', 'sDefaultZip', 'sDefaultCountry', 'bShowFamilyData', 'bHidePersonAddress', 'bHideFriendDate', 'bHideFamilyNewsletter', 'bHideWeddingDate', 'bHideLatLon', 'bForceUppercaseZip', 'bEnableSelfRegistration', 'bAllowEmptyLastName', 'iPersonNameStyle', 'iProfilePictureListSize', 'sNewPersonNotificationRecipientIDs', 'IncludeDataInNewPersonNotifications', 'sGreeterCustomMsg1', 'sGreeterCustomMsg2'],
gettext('People Setup') => ['sDirClassifications', 'sDirRoleHead', 'sDirRoleSpouse', 'sDirRoleChild', 'sDefaultCity', 'sDefaultState', 'sDefaultZip', 'sDefaultCountry', 'bShowFamilyData', 'bHidePersonAddress', 'bHideFriendDate', 'bHideFamilyNewsletter', 'bHideWeddingDate', 'bHideLatLon', 'bForceUppercaseZip', 'bEnableSelfRegistration', 'bAllowEmptyLastName', 'iPersonNameStyle', 'iProfilePictureListSize', 'sNewPersonNotificationRecipientIDs', 'IncludeDataInNewPersonNotifications', 'sGreeterCustomMsg1', 'sGreeterCustomMsg2', 'sInactiveClassification'],
gettext('Enabled Features') => ['bEnabledFinance', 'bEnabledSundaySchool', 'bEnabledEvents', 'bEnabledCalendar', 'bEnabledFundraiser', 'bEnabledEmail', 'bEnabledMenuLinks'],
gettext('Map Settings') => ['sGeoCoderProvider', 'sGoogleMapsGeocodeKey', 'sGoogleMapsRenderKey', 'sBingMapKey', 'sGMapIcons', 'iMapZoom'],
gettext('Report Settings') => ['sQBDTSettings', 'leftX', 'incrementY', 'sTaxReport1', 'sTaxReport2', 'sTaxReport3', 'sTaxSigner', 'sReminder1', 'sReminderSigner', 'sReminderNoPledge', 'sReminderNoPayments', 'sConfirm1', 'sConfirm2', 'sConfirm3', 'sConfirm4', 'sConfirm5', 'sConfirm6', 'sDear', 'sConfirmSincerely', 'sConfirmSigner', 'sPledgeSummary1', 'sPledgeSummary2', 'sDirectoryDisclaimer1', 'sDirectoryDisclaimer2', 'bDirLetterHead', 'sZeroGivers', 'sZeroGivers2', 'sZeroGivers3', 'iPDFOutputType'],
Expand Down
17 changes: 17 additions & 0 deletions src/OptionManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
require 'Include/Functions.php';

use ChurchCRM\Authentication\AuthenticationManager;
use ChurchCRM\dto\SystemConfig;
use ChurchCRM\model\ChurchCRM\ListOption;
use ChurchCRM\Utils\InputUtils;
use ChurchCRM\Utils\LoggerUtils;
use ChurchCRM\Utils\RedirectUtils;

$mode = trim($_GET['mode']);
Expand Down Expand Up @@ -313,6 +315,13 @@
<table cellpadding="3" width="30%" align="center">

<?php
$aInactiveClassificationIds = explode(',', SystemConfig::getValue('sInactiveClassification'));
$aInactiveClasses = array_filter($aInactiveClassificationIds, fn ($k) => is_numeric($k));

if (count($aInactiveClassificationIds) !== count($aInactiveClasses)) {
LoggerUtils::getAppLogger()->warning('Encountered invalid configuration(s) for sInactiveClassification, please fix this');
}

for ($row = 1; $row <= $numRows; $row++) {
?>
<tr align="center">
Expand All @@ -338,6 +347,7 @@
if ($numRows > 0) {
echo "<a href=\"OptionManagerRowOps.php?mode=$mode&Order=$aSeqs[$row]&ListID=$listID&ID=" . $aIDs[$row] . '&Action=delete"><i class="fa fa-times"></i></a>';
} ?>

</td>
<td class="TextColumn">
<span class="SmallText">
Expand All @@ -354,6 +364,13 @@
<?php
if ($mode == 'grproles') {
echo '<td class="TextColumn"><input class="form-control input-small" type="button" class="btn btn-default" value="' . gettext('Make Default') . "\" Name=\"default\" onclick=\"javascript:document.location='OptionManagerRowOps.php?mode=" . $mode . '&ListID=' . $listID . '&ID=' . $aIDs[$row] . "&Action=makedefault';\" ></td>";
}
if ($mode === 'classes') {
echo "<td>";
$check = in_array($aIDs[$row], $aInactiveClasses) ? "checked" : "";
echo "<input id='inactive$aIDs[$row]' type=\"checkbox\" onclick=\"$.get('OptionManagerRowOps.php?mode=$mode&Order=$aSeqs[$row]&ListID=$listID&ID=" . $aIDs[$row] . "&Action=Inactive')\" $check >";
echo gettext("Inactive");
echo "</td>";
} ?>

</tr>
Expand Down
20 changes: 20 additions & 0 deletions src/OptionManagerRowOps.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
require 'Include/Functions.php';

use ChurchCRM\Authentication\AuthenticationManager;
use ChurchCRM\dto\SystemConfig;
use ChurchCRM\Utils\InputUtils;
use ChurchCRM\Utils\LoggerUtils;
use ChurchCRM\Utils\RedirectUtils;

// Get the Order, ID, Mode, and Action from the querystring
Expand Down Expand Up @@ -149,6 +151,24 @@
RunQuery($sSQL);
break;

case 'Inactive':
$aInactiveClassificationIds = explode(',', SystemConfig::getValue('sInactiveClassification'));
$aInactiveClasses = array_filter($aInactiveClassificationIds, fn ($k) => is_numeric($k));

if (count($aInactiveClassificationIds) !== count($aInactiveClasses)) {
LoggerUtils::getAppLogger()->warning('Encountered invalid configuration(s) for sInactiveClassification, please fix this');
}

if (in_array($iID, $aInactiveClasses)) {
unset($aInactiveClasses[array_search($iID, $aInactiveClasses)]);
} else {
$aInactiveClasses[] = $iID;
}

$sInactiveClasses = implode(',', $aInactiveClasses);
SystemConfig::setValue('sInactiveClassification', $sInactiveClasses);

break;
// If no valid action was specified, abort
default:
RedirectUtils::redirect('v2/dashboard');
Expand Down
23 changes: 21 additions & 2 deletions src/v2/routes/people.php
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
<?php

use ChurchCRM\dto\SystemConfig;
use ChurchCRM\dto\SystemURLs;
use ChurchCRM\model\ChurchCRM\ListOptionQuery;
use ChurchCRM\model\ChurchCRM\PersonQuery;
use ChurchCRM\Utils\InputUtils;
use ChurchCRM\Utils\LoggerUtils;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Routing\RouteCollectorProxy;
Expand Down Expand Up @@ -58,10 +60,27 @@ function listPeople(Request $request, Response $response, array $args): Response
$familyActiveStatus = 'all';
}

$sInactiveClassificationIds = SystemConfig::getValue('sInactiveClassification');

if ($sInactiveClassificationIds === '') {
//works the same if group doesn't exist and keeps queries tidier
$sInactiveClassificationIds = '-1';
}

//parsing the string and reconstruct it back should be enough to mitigate the sql injection vector in here.
$aInactiveClassificationIds = explode(',', $sInactiveClassificationIds);
$aInactiveClasses = array_filter($aInactiveClassificationIds, fn ($k) => is_numeric($k));

if (count($aInactiveClassificationIds) !== count($aInactiveClasses)) {
LoggerUtils::getAppLogger()->warning('Encountered invalid configuration(s) for sInactiveClassification, please fix this');
}

$sInactiveClasses = implode(',', $aInactiveClasses);

if ($familyActiveStatus === 'active') {
$members->leftJoinFamily()->where('family_fam.fam_DateDeactivated is null');
$members->leftJoinFamily()->where('(family_fam.fam_DateDeactivated is null) and (per_cls_id not in (' . $sInactiveClasses . ') )');
} elseif ($familyActiveStatus === 'inactive') {
$members->leftJoinFamily()->where('family_fam.fam_DateDeactivated is not null');
$members->leftJoinFamily()->where('(family_fam.fam_DateDeactivated is not null) or (per_cls_id in (' . $sInactiveClasses . ') )');
}

$members->find();
Expand Down

0 comments on commit ee4855d

Please sign in to comment.