From b51f6a60d12335fcccb28da5278c30a8e1d8d5b9 Mon Sep 17 00:00:00 2001 From: Nathan Coad Date: Thu, 26 Jun 2014 23:41:58 +1000 Subject: [PATCH] Added confirmation to study group auto updates --- booking.helper.inc | 98 +++++++++++++++----------- booking.module | 43 +++++++++++- booking.rooms.inc | 61 ---------------- booking.studygroups.inc | 151 ++++++++++++++++++++++++++++------------ 4 files changed, 206 insertions(+), 147 deletions(-) diff --git a/booking.helper.inc b/booking.helper.inc index 77c92b4..29d924c 100644 --- a/booking.helper.inc +++ b/booking.helper.inc @@ -480,6 +480,65 @@ function _booking_assign_attendee_group($nid, $session_id, $gender, $age, &$atte } +/** + * Validate there is available capacity for the specified room and bed type + * @return TRUE if there is sufficient capacity, otherwise FALSE + */ +function _booking_room_capacity_check($room_id, $room_bedtype, $room_definition_object = NULL) { + global $event; + + $bed_inputs = array( + 1 => 'booking_room_singlebeds', + 2 => 'booking_room_doublebeds', + 3 => 'booking_room_queenbeds', + ); + + //make sure the value exists before validating it + if (!empty($room_bedtype)) + { + //if we already have the object available, don't query for it again + if ($room_definition_object == NULL) + { + $details = db_query("SELECT * FROM {booking_room_definition} WHERE rid = :rid", + array(':rid' => $room_id))->fetchObject(); + } + else + $details = $room_definition_object; + + //get all person-to-room mappings relating to this room and bed type + $mappings = db_query("SELECT count(*) as num FROM {booking_room_mapping} " . + "WHERE booking_eventid = :eid AND booking_roomid = :rid AND booking_room_bedtype = :type", + array(':eid' => $event->eid, ':rid' => $room_id, ':type' => $room_bedtype))->fetchObject(); + + $db_field = $bed_inputs[$room_bedtype]; + $max_beds = $details->$db_field; + + //if the beds are dual occupency, pretend there's twice as many of them + if ($room_bedtype == 2 || $room_bedtype == 3) + { + $max_beds = $max_beds * 2; + } + + //check that there is sufficient capacity to allocate another person to this room and bed type + if ($mappings->num < $max_beds) + { + watchdog('booking','Sufficient capacity is available in location !id, room !room, with bed type !type. !count beds remaining of this type', + array('!id' => $details->booking_room_location_id, '!room' => $details->booking_room_number, + '!type' => _booking_room_bedtype_lookup($room_bedtype), '!count' => $max_beds - $mappings->num)); + + return true; + } + else + { + watchdog('booking',"Couldn't locate sufficient capacity in location !id, room !room, with bed type !type. !count beds remaining of this type", + array('!id' => $details->booking_room_location_id, '!room' => $details->booking_room_number, + '!type' => _booking_room_bedtype_lookup($room_bedtype), '!count' => $max_beds - $mappings->num)); + } + } + + return false; +} + /** * Function for cleaning up room allocations for people that have withdrawn their registration * @param $nid - the node id for the person @@ -994,45 +1053,6 @@ function _booking_paypal_form_builder($node, &$form_state, $person, $invoiceid, return $form; } -/** - * Function for generating the "lucky number" to be used on the lanyard - */ -function booking_generate_luckynumbers() { - global $event; - - $i = 0; - - //query for the mappings relating to $readinggroup_studygroup_id - $attendee_query = db_query("SELECT * FROM {booking_person} WHERE booking_event_id = :eid", - array(':eid' => $event->eid)); - $attendees = $attendee_query->fetchAll(); - - //assuming there's less than 900 people, generate numbers within that range and shuffle the order - $numbers = range(100,999); - shuffle($numbers); - - foreach ($attendees as $attendee) - { - $luckynum = $numbers[$i++]; - - drupal_set_message(t('Updating user !id to have lucky number !num.', - array('!id' => $attendee->nid, '!num' => $luckynum))); - - //run an update query - - db_update('booking_person') - ->fields(array ( - 'booking_luckynum' => $luckynum, - )) - ->condition('nid', $attendee->nid) - ->execute(); - - } - drupal_set_message(t('Finished.')); - - return t("

Generate Lucky Numbers

"); - -} /** * Helper function to format registrations details for summary in the confirmation email diff --git a/booking.module b/booking.module index c5aa23c..8294993 100644 --- a/booking.module +++ b/booking.module @@ -394,7 +394,7 @@ function booking_menu() { 'title' => 'Update Study Groups', 'description' => 'Calculate updated Study Group memberships', 'page callback' => 'drupal_get_form', - 'page arguments' => array('booking_studygroups_update', 3), + 'page arguments' => array('booking_studygroups_update_form', 3), 'access arguments' => array('edit study groups'), //'type' => MENU_LOCAL_ACTION, ); @@ -742,3 +742,44 @@ function booking_node_presave($node) { //watchdog('booking', 'Presave of person: @info', array('@info' => var_export($node, TRUE))); } } + + +/** + * Function for generating the "lucky number" to be used on the lanyard + */ +function booking_generate_luckynumbers() { + global $event; + + $i = 0; + + //query for the mappings relating to $readinggroup_studygroup_id + $attendee_query = db_query("SELECT * FROM {booking_person} WHERE booking_event_id = :eid", + array(':eid' => $event->eid)); + $attendees = $attendee_query->fetchAll(); + + //assuming there's less than 900 people, generate numbers within that range and shuffle the order + $numbers = range(100,999); + shuffle($numbers); + + foreach ($attendees as $attendee) + { + $luckynum = $numbers[$i++]; + + drupal_set_message(t('Updating user !id to have lucky number !num.', + array('!id' => $attendee->nid, '!num' => $luckynum))); + + //run an update query + + db_update('booking_person') + ->fields(array ( + 'booking_luckynum' => $luckynum, + )) + ->condition('nid', $attendee->nid) + ->execute(); + + } + drupal_set_message(t('Finished.')); + + return t("

Generate Lucky Numbers

"); + +} diff --git a/booking.rooms.inc b/booking.rooms.inc index 2842d1d..5a9c989 100644 --- a/booking.rooms.inc +++ b/booking.rooms.inc @@ -332,67 +332,6 @@ function booking_room_edit_form_validate($form, &$form_state) { } } -/** - * Validate there is available capacity for the specified room and bed type - * @return TRUE if there is sufficient capacity, otherwise FALSE - */ -function _booking_room_capacity_check($room_id, $room_bedtype, $room_definition_object = NULL) { - global $event; - - $bed_inputs = array( - 1 => 'booking_room_singlebeds', - 2 => 'booking_room_doublebeds', - 3 => 'booking_room_queenbeds', - ); - - //make sure the value exists before validating it - if (!empty($room_bedtype)) - { - //if we already have the object available, don't query for it again - if ($room_definition_object == NULL) - { - $details = db_query("SELECT * FROM {booking_room_definition} WHERE rid = :rid", - array(':rid' => $room_id))->fetchObject(); - } - else - $details = $room_definition_object; - - //get all person-to-room mappings relating to this room and bed type - $mappings = db_query("SELECT count(*) as num FROM {booking_room_mapping} " . - "WHERE booking_eventid = :eid AND booking_roomid = :rid AND booking_room_bedtype = :type", - array(':eid' => $event->eid, ':rid' => $room_id, ':type' => $room_bedtype))->fetchObject(); - - $db_field = $bed_inputs[$room_bedtype]; - $max_beds = $details->$db_field; - - //if the beds are dual occupency, pretend there's twice as many of them - if ($room_bedtype == 2 || $room_bedtype == 3) - { - $max_beds = $max_beds * 2; - } - - //check that there is sufficient capacity to allocate another person to this room and bed type - if ($mappings->num < $max_beds) - { - watchdog('booking','Sufficient capacity is available in location !id, room !room, with bed type !type. !count beds remaining of this type', - array('!id' => $details->booking_room_location_id, '!room' => $details->booking_room_number, - '!type' => _booking_room_bedtype_lookup($room_bedtype), '!count' => $max_beds - $mappings->num)); - - return true; - } - else - { - watchdog('booking',"Couldn't locate sufficient capacity in location !id, room !room, with bed type !type. !count beds remaining of this type", - array('!id' => $details->booking_room_location_id, '!room' => $details->booking_room_number, - '!type' => _booking_room_bedtype_lookup($room_bedtype), '!count' => $max_beds - $mappings->num)); - } - } - - return false; - -} - - /** * Process the submission to update allocated room and bed for a person */ diff --git a/booking.studygroups.inc b/booking.studygroups.inc index 7e0b90d..d720e4b 100644 --- a/booking.studygroups.inc +++ b/booking.studygroups.inc @@ -115,7 +115,7 @@ function booking_available_leadhelp_select_form($node, &$form_state, $group_id) //also restrict to males from the current event $db_and = db_and(); $db_and->condition('p.booking_event_id', $event->eid, '='); - //$db_and->condition('p.booking_gender', 'M', '='); + $db_and->condition('p.booking_gender', 'M', '='); $db_and->condition($db_or); $query->condition($db_and); @@ -134,18 +134,26 @@ function booking_available_leadhelp_select_form($node, &$form_state, $group_id) foreach ($group_mapping as $group) { $role = $group->booking_studygroup_role; + /* //add to the listing of all the roles this person is doing if ($group->booking_node_id == $data->nid && $role > 0) { $text = _booking_studygroup_role_lookup($role); $role_listing .= $text . " group " . $group->booking_studygroup_id . " #" . $group->booking_session_id . "; "; } - + */ //also record if they are doing anything for our current group if ($group->booking_node_id == $data->nid && $group->booking_studygroup_id == $group_id) { $assigned_role = $role; $session_id = $group->booking_session_id; + //list any role for this current group + if ($role > 0) + { + $text = _booking_studygroup_role_lookup($role); + $role_listing .= "" . $text . " group " . $group->booking_studygroup_id . " #" . $group->booking_session_id . "; "; + } + } } @@ -963,7 +971,7 @@ function booking_studygroups_calculate() { /** * Function for calculating who belongs to which study group */ -function booking_studygroups_update($node, &$form_state, $sid) { +function booking_studygroups_update_form($node, &$form_state, $sid) { global $event; //master attendee list @@ -980,6 +988,10 @@ function booking_studygroups_update($node, &$form_state, $sid) { $intro_text = ""; $reading_group_id = variable_get('booking_readinggroup_id','7'); + //store our calculated updates in this array which will then get serialized and added to the form for processing + $updates_to_confirm = array(); + $inserts_to_confirm = array(); + //verify that $nid is a number if (! preg_match('/^[0-9]+$/', $sid)) { drupal_set_message("Error: Invalid group ID '" . $sid . "' supplied. Unable to update study group session.", 'error', FALSE); @@ -1012,6 +1024,7 @@ function booking_studygroups_update($node, &$form_state, $sid) { array(':eid' => $event->eid)); $attendees = $query->fetchAllAssoc('nid'); + //TODO: Move statistics generation to separate function //calculate the ratios of males to females, and various age groups $statistics = _booking_generate_statistics($attendees); $gender_ratio = ($statistics['males'] / $statistics['females']) * ($max_people / 2); @@ -1259,11 +1272,9 @@ function booking_studygroups_update($node, &$form_state, $sid) { $age_type = 'over25'; //make sure this person is going to fit in with our calculated gender ratios - _booking_loop_carefully($session_count, $gender, $start, $maximums[$gender], $group->booking_num_group_sessions, 3, $calculation_messages); - + _booking_loop_carefully($session_count, $gender, $start, $maximums[$gender], $group->booking_num_group_sessions, 3, $calculation_messages); //make sure this person is going to fit in with our calculated age ratios _booking_loop_carefully($session_count, $age_type, $start, $maximums[$age_type], $group->booking_num_group_sessions, 3, $calculation_messages); - //check for maximum group size _booking_loop_carefully($session_count, 'total', $start, $max_people, $group->booking_num_group_sessions, 4, $calculation_messages); @@ -1286,12 +1297,8 @@ function booking_studygroups_update($node, &$form_state, $sid) { $i++; } //finished looping through attendees for this study group - - //iterate over the attendee list and write to the database the session they're assigned to - //use the multi-insert query type at https://drupal.org/node/310079 - $insert_query = db_insert('booking_studygroup_mapping')->fields(array('booking_eventid', 'booking_node_id', - 'booking_studygroup_id', 'booking_session_id', 'booking_studygroup_role')); + //now calculate the updates for the database foreach($working_list as $person) { //watchdog('booking', "
Working list role person:\n@info
", array('@info' => print_r( $person, true))); @@ -1300,6 +1307,8 @@ function booking_studygroups_update($node, &$form_state, $sid) { // if already in $group_mapping then just run an update query here $found = FALSE; + $message = ""; + foreach ($group_mapping as $mapping) { //check if we can find a study group session already for this user and this study group (eg Monday Tuesday or Wednesday) @@ -1313,9 +1322,13 @@ function booking_studygroups_update($node, &$form_state, $sid) { $message = t('Found existing study group session for user !id (!name). Changing old session !old to !session. Role id is !role', array('!id' => $person->nid, '!old' => $mapping->booking_session_id, '!session' => $person->session, '!role' => $person->booking_studygroup_role, '!name' => $person->booking_firstname . " " . $person->booking_lastname)); - $update_messages[] = $message; - //drupal_set_message($message, 'status', FALSE); - watchdog('booking', $message); + + $update = array( + 'booking_session_id' => $person->session, + 'booking_studygroup_role' => $person->booking_studygroup_role, + ); + + $updates_to_confirm[] = array('sid' => $mapping->sid, 'fields' => $update); //update the entry /* @@ -1325,63 +1338,56 @@ function booking_studygroups_update($node, &$form_state, $sid) { 'booking_studygroup_role' => $person->booking_studygroup_role, )) ->condition('sid', $mapping->sid) - ->execute(); - */ + ->execute(); + */ + } elseif ($mapping->booking_session_id !== $person->session && $group->sid == $reading_group_id) { $message = t('Found existing reading group session for user !id (!name). Changing old session !old to !session. Role id is !role', array('!id' => $person->nid, '!old' => $mapping->booking_session_id, '!session' => $person->session, '!role' => $person->booking_studygroup_role, '!name' => $person->booking_firstname . " " . $person->booking_lastname)); - $update_messages[] = $message; - //drupal_set_message($message, 'status', FALSE); - watchdog('booking', $message); - - //update the entry - /* - db_update('booking_studygroup_mapping') - ->fields(array( + + $update = array( 'booking_session_id' => $person->session, 'booking_studygroup_role' => $person->booking_studygroup_role, - )) - ->condition('sid', $mapping->sid) - ->execute(); - */ + ); + + $updates_to_confirm[] = array('sid' => $mapping->sid, 'fields' => $update); + } - else - { - //drupal_set_message(t('Found existing study group session for user !id, but old session !old matches new value !session.', - // array('!id' => $person->nid, '!old' => $mapping->booking_session_id, '!session' => $person->session))); - } - //stop looping through the list break; - } - } + + } //end checking for existing group session + } //end looping through study group mappings //if we didn't find an existing record, add it to the list to insert if (! $found && $person->session <> 0) { - $message = t('Found no existing study group session for user id !id (!name). Adding to list of inserts.', + $message = t('Found no existing study group session for user id !id (!name). Adding to list of inserts for session !session.', array('!id' => $person->nid, '!sid' => $mapping->sid, '!session' => $person->session, '!name' => $person->booking_firstname . " " . $person->booking_lastname )); - //drupal_set_message($message, 'status', FALSE); - $update_messages[] = $message; - watchdog('booking', $message); - $record = array( + $inserts_to_confirm[] = array( 'booking_eventid' => $event->eid, 'booking_node_id' => $person->nid, 'booking_studygroup_id' => $group->sid, 'booking_session_id' => $person->session, 'booking_studygroup_role' => $person->booking_studygroup_role, - ); - $insert_query->values($record); + ); + } - } - //$insert_query->execute(); + //log any update we made + if ($message !== "") + { + $update_messages[] = $message; + //watchdog('booking', $message); + } + + } //end loop through working copy of attendee list //watchdog('booking', "
Session statistics list:\n@info
", array('@info' => print_r( $session_count, true))); @@ -1389,7 +1395,9 @@ function booking_studygroups_update($node, &$form_state, $sid) { unset($session_count); unset($working_list); - drupal_set_message(t('Finished processing study group !group.', array('!group' => $group->booking_studygroup_descrip))); + $final_message = t('Finished processing study group !group.', array('!group' => $group->booking_studygroup_descrip)); + drupal_set_message($final_message); + watchdog('booking', "
" . $final_message . "\n" . implode("\n", $update_messages) . "
"); } //finished processing study groups @@ -1423,6 +1431,18 @@ function booking_studygroups_update($node, &$form_state, $sid) { '#title' => '', '#markup' => "

" . implode("
\n", $update_messages) . "

", ); + $form['update_string'] = array ( + '#type' => 'hidden', + '#value' => serialize($updates_to_confirm), + ); + $form['insert_string'] = array ( + '#type' => 'hidden', + '#value' => serialize($inserts_to_confirm), + ); + $form['confirm'] = array ( + '#type' => 'submit', + '#value' => t('Confirm Updates'), + ); return array ( 'first_para' => array ( '#type' => 'markup', @@ -1433,6 +1453,45 @@ function booking_studygroups_update($node, &$form_state, $sid) { } +/** + * Process the submission to accept calculated study group membership updates + */ +function booking_studygroups_update_form_submit($form, &$form_state) { + global $event; + $values = $form_state['input']; + + $raw_updates = unserialize($values['update_string']); + $raw_inserts = unserialize($values['insert_string']); + watchdog('booking', "
Study group insert confirmation array:\n@info
", array('@info' => print_r( $raw_inserts, true))); + watchdog('booking', "
Study group update confirmation array:\n@info
", array('@info' => print_r( $raw_updates, true))); + + //process the updates + foreach($raw_updates as $update) + { + $rows = db_update('booking_studygroup_mapping') + ->fields($update['fields']) + ->condition('sid', $update['sid']) + ->execute(); + //watchdog('booking', "Updated sid !sid affecting !rows rows.", array('!sid' => $update['sid'], '!rows' => $rows)); + } + + //handle the database inserts using the multi-insert query type at https://drupal.org/node/310079 + $insert_query = db_insert('booking_studygroup_mapping')->fields(array('booking_eventid', 'booking_node_id', + 'booking_studygroup_id', 'booking_session_id', 'booking_studygroup_role')); + + foreach($raw_inserts as $insert) + { + $insert_query->values($insert); + } + $insert_query->execute(); + + drupal_set_message(t('Study group update confirmation processed.')); + //redirect the user back to the study groups page + $form_state['redirect'] = array('admin/booking/studygroups'); + +} + + /** * Function for viewing a printable format of who belongs to which study group */