Skip to content

Commit

Permalink
Ability to filter by status when displaying/recording attendance. Als…
Browse files Browse the repository at this point in the history
…o fixes for attendance ordering. Also Fix #121 wrong extras calculation.
  • Loading branch information
tbar0970 committed Feb 3, 2016
1 parent 32f96c9 commit a42dc40
Show file tree
Hide file tree
Showing 8 changed files with 193 additions and 117 deletions.
118 changes: 83 additions & 35 deletions db_objects/attendance_record_set.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class Attendance_Record_Set
public $congregationid = NULL;
public $groupid = 0;
public $age_bracket = NULL;
public $status = NULL;
public $show_photos = FALSE;
private $_persons = NULL;
private $_attendance_records = Array();
Expand Down Expand Up @@ -101,19 +102,41 @@ function load($date, $cohort, $age_bracket, $status)
}
$this->age_bracket = $age_bracket;
$this->status = $status;
if ($this->status) {
list($statusType, $statusID) = explode('-', $status);
if (($statusType == 'g') && ($cohortType != 'g')) {
trigger_error("Cannot restrict congregational attendance by a group membership status");
return;
}
}

$db =& $GLOBALS['db'];
$sql = 'SELECT personid, present
$sql = 'SELECT ar.personid, ar.present
FROM attendance_record ar
JOIN person p ON ar.personid = p.id
WHERE date = '.$db->quote($date).'
AND groupid = '.(int)$this->groupid;
LEFT JOIN person_group_membership pgm
ON pgm.groupid = ar.groupid AND pgm.personid = p.id
WHERE ar.date = '.$db->quote($date).'
AND ar.groupid = '.(int)$this->groupid;
if ($this->congregationid) {
$sql .= '
AND p.congregationid = '.$db->quote($this->congregationid);
}
$statusType = $statusID = NULL;
if ($this->status) {
$sql .= '
AND p.status = '.$db->quote($this->status);
list($statusType, $statusID) = explode('-', $status);
switch ($statusType) {
case 'p':
$sql .= '
AND p.status = '.(int)$statusID;
break;
case 'g':
$sql .= '
AND pgm.membership_status = '.(int)$statusID;
break;
default:
trigger_error("invalid status filter $status"); return;
}
}
if (strlen($this->age_bracket)) {
$sql .= '
Expand All @@ -123,23 +146,21 @@ function load($date, $cohort, $age_bracket, $status)
check_db_result($this->_attendance_records);

$order = defined('ATTENDANCE_LIST_ORDER') ? constant('ATTENDANCE_LIST_ORDER') : self::LIST_ORDER_DEFAULT;
$conds = Array('!status' => 'archived');
if (strlen($this->age_bracket)) {
$conds['age_bracket'] = $this->age_bracket;
}
if (strlen($this->status)) {
$field = $statusType == 'g' ? 'membership_status' : 'status';
$conds[$field] = $statusID;
}
if ($this->congregationid) {
$conds = Array('congregationid' => $this->congregationid, '!status' => 'archived');
if (strlen($this->age_bracket)) {
$conds['age_bracket'] = $this->age_bracket;
}
$conds['congregationid'] = $this->congregationid;
$this->_persons = $GLOBALS['system']->getDBObjectData('person', $conds, 'AND', $order);
} else {
$group =& $GLOBALS['system']->getDBObject('person_group', $this->groupid);
$this->_persons = $group->getMembers(FALSE, $order);
if (strlen($this->age_bracket)) {
// Not the most efficient but it's a problem when it's a problem
foreach ($this->_persons as $i => $person) {
if ($person['age_bracket'] != $this->age_bracket) unset($this->_persons[$i]);
}
}
$this->_persons = $group->getMembers($conds, $order);
}

}


Expand Down Expand Up @@ -254,29 +275,32 @@ public static function getPersonIDsForCohorts($cohortids)
if ($type == 'c') $congids[] = $id;
if ($type == 'g') $groupids[] = $id;
}
$SQL = 'SELECT p.id, p.first_name, p.last_name, p.status, c.id as congregationid, c.name as congregation, '
$SQL = 'SELECT person.id, person.first_name, person.last_name, person.status, c.id as congregationid, c.name as congregation, '
.($groupids ? 'group_concat(pgm.groupid) as groupids' : '"" AS groupids').'
FROM person p
JOIN family f on p.familyid = f.id
LEFT JOIN congregation c ON p.congregationid = c.id
FROM person person
JOIN family f on person.familyid = f.id
LEFT JOIN congregation c ON person.congregationid = c.id
';
if ($groupids) {
$SQL .= '
LEFT JOIN person_group_membership pgm
ON pgm.personid = p.id
ON pgm.personid = person.id
AND pgm.groupid in ('.implode(', ', array_map(Array($db, 'quote'), $groupids)).')
LEFT JOIN person_group_membership_status pgms
ON pgms.id = pgm.membership_status
';
}
$SQL .= '
WHERE
';
$wheres = Array();
if ($congids) $wheres[] = '(p.congregationid IN ('.implode(', ', array_map(Array($db, 'quote'), $congids)).'))';
if ($congids) $wheres[] = '(person.congregationid IN ('.implode(', ', array_map(Array($db, 'quote'), $congids)).'))';
if ($groupids) $wheres[] = '(pgm.groupid IS NOT NULL)';
$SQL .= implode(" OR ", $wheres);
$order = defined('ATTENDANCE_LIST_ORDER') ? constant('ATTENDANCE_LIST_ORDER') : self::LIST_ORDER_DEFAULT;
$order = preg_replace("/(^|[^.])status($| |,)/", '\\1p.status\\2', $order);
$SQL .= "GROUP BY p.id \n";
// Since we are getting persons for multiple cohorts, "status" has to mean person status here.
$order = preg_replace("/(^|[^.])status($| |,)/", '\\1person.status\\2', $order);
$SQL .= "GROUP BY person.id \n";
$SQL .= ' ORDER BY '.$order."\n";
$res= $db->queryAll($SQL, null, null, true);
check_db_result($res);
Expand Down Expand Up @@ -555,7 +579,7 @@ function getStatsForPeriod($start_date, $end_date, $cohortid)
return $stats;
}

function getAttendances($congregationids, $groupid, $age_bracket, $start_date, $end_date)
function getAttendances($congregationids, $groupid, $params, $start_date, $end_date)
{
$SQL = 'SELECT person.id, person.last_name, person.first_name, '.($groupid ? 'pgms.label AS membership_status, ' : '').' person.status, ar.date, ar.present
FROM person person
Expand All @@ -565,14 +589,15 @@ function getAttendances($congregationids, $groupid, $age_bracket, $start_date, $
$SQL .= '
JOIN person_group_membership pgm ON pgm.personid = person.id AND pgm.groupid = '.(int)$groupid;
}
// restricting the attendance dates within a subquery improves performance significantly.
$SQL .= '
LEFT JOIN attendance_record ar ON ar.personid = person.id
AND ar.date BETWEEN '.$GLOBALS['db']->quote($start_date).' AND '.$GLOBALS['db']->quote($end_date);
if ($congregationids) {
$SQL .= ' AND ar.groupid = 0';
}
LEFT JOIN (
SELECT personid, date, present
FROM attendance_record ar
WHERE ar.date BETWEEN '.$GLOBALS['db']->quote($start_date).' AND '.$GLOBALS['db']->quote($end_date).'
AND ar.groupid = '.(int)$groupid.'
) ar ON ar.personid = person.id';
if ($groupid) {
$SQL .= ' AND ar.groupid = '.(int)$groupid;
$SQL .= '
LEFT JOIN person_group_membership_status pgms ON pgms.id = pgm.membership_status';
}
Expand All @@ -582,13 +607,36 @@ function getAttendances($congregationids, $groupid, $age_bracket, $start_date, $
$SQL .= '
AND person.congregationid IN ('.implode(', ', array_map(Array($GLOBALS['db'], 'quote'), $congregationids)).') ';
}
if ($age_bracket !== '') {
if (array_get($params, 'age_bracket', '') !== '') {
$SQL .= '
AND person.age_bracket = '.$GLOBALS['db']->quote($age_bracket);
AND person.age_bracket = '.$GLOBALS['db']->quote($params['age_bracket']);
}
$status = array_get($params, 'status', '');
if (strlen($status)) {
list($statusType, $statusID) = explode('-', $status);
if (($statusType == 'g') && empty($groupid)) {
trigger_error("Cannot filter by group membership status for congregational attendance");
return Array(Array(), Array(), Array());
}
switch ($statusType) {
case 'g':
$SQL .= '
AND pgm.membership_status = '.$GLOBALS['db']->quote($statusID);
break;
case 'p':
$SQL .= '
AND person.status = '.$GLOBALS['db']->quote($statusID);
break;

}
}

$order = defined('ATTENDANCE_LIST_ORDER') ? constant('ATTENDANCE_LIST_ORDER') : self::LIST_ORDER_DEFAULT;
$order = preg_replace("/(^|[^.])status($| |,)/", '\\1person.status\\2', $order);
if ($congregationids) {
$order = preg_replace("/(^|[^.])status($| |,)/", '\\1person.status\\2', $order);
} else {
$order = preg_replace("/(^|[^.])status($| |,)/", '\\1pgms.rank\\2', $order);
}
$SQL .= '
ORDER BY '.$order;
$dates = Array();
Expand Down
14 changes: 7 additions & 7 deletions db_objects/person.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ static function allowedToAdd()
return TRUE;
}

public static function getStatusOptions()
{
return explode(',', PERSON_STATUS_OPTIONS)
+ Array('contact' => 'Contact', 'archived' => 'Archived');
}

protected static function _getFields()
{
$allowEmptyCong = TRUE;
Expand Down Expand Up @@ -83,8 +89,7 @@ protected static function _getFields()
),
'status' => Array(
'type' => 'select',
'options' => explode(',', PERSON_STATUS_OPTIONS)
+ Array('contact' => 'Contact', 'archived' => 'Archived'),
'options' => self::getStatusOptions(),
'default' => 'contact' /* but see below */,
'class' => 'person-status',
'allow_empty' => false,
Expand Down Expand Up @@ -601,11 +606,6 @@ static function printMultipleFinder($name, $val=Array())
<?php
}

function getStatusOptions()
{
return $this->fields['status']['options'];
}

static function getStatusStats()
{
$dummy = new Person();
Expand Down
64 changes: 15 additions & 49 deletions db_objects/person_group.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,61 +102,27 @@ function toString()
return $this->values['name'];
}

function getMembers($incl_archived=TRUE, $order_by=NULL)
function getMembers($params=Array(), $order_by=NULL)
{
$db =& $GLOBALS['db'];
$sql = 'SELECT person.*, gm.membership_status AS membership_status_id, ms.label as membership_status, gm.created as joined_group, c.name as congregation
FROM person_group_membership gm
JOIN person person ON gm.personid = person.id
';
if ($order_by != NULL) {
$sql .= '
JOIN family f ON f.id = person.familyid
';
}
$sql .= '
LEFT JOIN congregation c ON c.id = person.congregationid
LEFT JOIN person_group_membership_status ms ON ms.id = gm.membership_status
WHERE gm.groupid = '.$db->quote((int)$this->id).'
';
if (!$incl_archived) {
$sql .= ' AND person.status <> "archived"
';
}
if ($order_by == NULL) {
$order_by = 'ms.rank, person.last_name, person.first_name';
$order_by = 'pgms.rank, person.last_name, person.first_name';
} else {
// replace 'status' with membership status rank.
// but retain 'person.status' unchanged.
$order_by = preg_replace("/(^|[^.])status($| |,)/", '\\1ms.rank\\2', $order_by);
$order_by = preg_replace("/(^|[^.])status($| |,)/", '\\1pgms.rank\\2', $order_by);
}
$sql .= 'ORDER BY '.$order_by;
$res = $db->queryAll($sql, null, null, true);
check_db_result($res);
foreach ($res as $k => &$v) {
$v['joined_group'] = format_date($v['joined_group']);
}
return $res;
}

function getMemberIDs($incl_archived=TRUE)
{
$db =& $GLOBALS['db'];
$sql = 'SELECT p.id
FROM person_group_membership gm
JOIN person p ON gm.personid = p.id
LEFT JOIN congregation c ON c.id = p.congregationid
LEFT JOIN person_group_membership_status ms ON ms.id = gm.membership_status
WHERE gm.groupid = '.$db->quote((int)$this->id).'
';
if (!$incl_archived) {
$sql .= ' AND p.status <> "archived"
';
}
$sql .= 'ORDER BY p.last_name, p.first_name';
$res = $db->queryCol($sql);
check_db_result($res);
return $res;
$person = new Person();
$comps = $person->getInstancesQueryComps($params, 'AND', $order_by);
$comps['from'] .= '
JOIN person_group_membership pgm ON pgm.personid = person.id
LEFT JOIN person_group_membership_status pgms ON pgms.id = pgm.membership_status
';
if (strlen($comps['where'])) $comps['where'] .= ' AND ';
$comps['where'] .= ' pgm.groupid = '.(int)$this->id;
$comps['select'][] = 'pgm.membership_status as membership_status_id';
$comps['select'][] = 'pgms.label as membership_status';
$comps['select'][] = 'pgm.created as joined_group';
return $person->_getInstancesData($comps);
}

function addMember($personid, $membership_status=NULL, $overwrite_existing=FALSE)
Expand Down
1 change: 1 addition & 0 deletions include/system_controller.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ public function _handleError($errno, $errstr, $errfile, $errline)
}

$bt = debug_backtrace();
array_shift($bt); // remove reference to this handleError function
foreach ($bt as &$b) {
if (!empty($b['args'])) {
foreach ($b['args'] as &$v) {
Expand Down
6 changes: 2 additions & 4 deletions members/views/view_0_groups.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,8 @@ function printView()
trigger_error("Group ID missing");
return;
}

$personIDs = $this->group->getMemberIDs(FALSE);
$order = 'last_name, first_name';
$persons = $GLOBALS['system']->getDBObjectData('member', Array('id' => $personIDs), 'OR', $order);

$persons = $this->group->getMembers(Array('!status' => 'archived'));
$emails = Array();
foreach ($persons as $member) {
if ($e = $member['email']) $emails[] = $e;
Expand Down
6 changes: 5 additions & 1 deletion views/view_5_groups.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ function printView()


<?php
$persons = $this->_group->getMembers(!empty($_SESSION['show_archived_group_members']));
$mParams = empty($_SESSION['show_archived_group_members']) ? Array() : Array('!status' => 'archived');
$persons = $this->_group->getMembers($mParams);
list ($status_options, $default_status) = Person_Group::getMembershipStatusOptionsAndDefault();
?>
<h3>Group Members (<?php echo count($persons); ?>)</h3>
Expand Down Expand Up @@ -156,6 +157,9 @@ function printView()
}

if (!empty($persons)) {
foreach ($persons as $k => &$v) {
$v['joined_group'] = format_date($v['joined_group']);
}
$special_fields = Array('joined_group', 'congregation');
if (count($status_options) > 1) {
array_unshift($special_fields, 'membership_status');
Expand Down
Loading

0 comments on commit a42dc40

Please sign in to comment.