From 773ba5a1016972b08034d7aee6675a0812f67f02 Mon Sep 17 00:00:00 2001 From: Nathan Coad Date: Tue, 27 May 2014 10:28:28 +1000 Subject: [PATCH] Work on bed allocations --- booking.constants.inc | 21 ++++- booking.helper.inc | 67 ++++++++++++++++ booking.install | 9 +++ booking.register.inc | 52 ++++++------ booking.rooms.inc | 172 ++++++++++++++++++++++++++++------------ booking.studygroups.inc | 81 ++----------------- 6 files changed, 255 insertions(+), 147 deletions(-) diff --git a/booking.constants.inc b/booking.constants.inc index 3ec8513..81333f9 100644 --- a/booking.constants.inc +++ b/booking.constants.inc @@ -68,7 +68,7 @@ function _get_tshirt_options() { /** * Helper function to look up description of studygroup role * @param $input integer containing role id - * @return string for corresponding room location + * @return string for corresponding role */ function _booking_studygroup_role_lookup($input = NULL) { @@ -108,6 +108,25 @@ function _booking_room_location_lookup($input = NULL) return $location; } +/** + * Helper function to look up description of bed type + * @param $input integer containing bed type id + * @return string for corresponding bed type + */ +function _booking_room_bedtype_lookup($input = NULL) +{ + $bed = array(); + $bed[] = ''; + $bed[] = t('Single'); + $bed[] = t('Double'); + $bed[] = t('Queen'); + + if ($input != NULL) + return $bed[$input]; + else + return $role; +} + /** * Helper function to reliably (without using any external APIs) provide a list of options for the country field used in the registration form */ diff --git a/booking.helper.inc b/booking.helper.inc index 6a553b9..ad94384 100644 --- a/booking.helper.inc +++ b/booking.helper.inc @@ -354,6 +354,73 @@ function _date_range_to_string($date_start, $date_end) { return $final_string; } +/** + * Function to correctly clone an associative array storing objects + * Taken from http://stackoverflow.com/questions/1532618/is-there-a-function-to-make-a-copy-of-a-php-array-to-another + */ +function _booking_clone_array($copied_array) { + return array_map(function($element) { + return ( + ((is_array($element)) + ? call_user_func(__FUNCTION__, $element) + : ((is_object($element)) + ? clone $element + : $element + ) + ) + ); + }, $copied_array); +} + + +/** + * Function to randomise the ordering of an array + * taken from http://stackoverflow.com/questions/4102777/php-random-shuffle-array-maintaining-key-value + */ +function _booking_shuffle_assoc($list) { + if (!is_array($list)) return $list; + + $keys = array_keys($list); + shuffle($keys); + $random = array(); + foreach ($keys as $key) { + $random[$key] = $list[$key]; + } + return $random; +} + +/** + * Function to mark an attendee as processed for group calculations + * @param $input string containing passport number to be verified + */ +function _booking_assign_attendee_group($nid, $session_id, $gender, $age, &$attendee_list, &$session_count) +{ + + if (empty($nid)) + { + drupal_set_message(t('Attempting to process a non-existent node id.')); + return; + } + + //mark this person as processed in the working list + $attendee_list[$nid]->processed = 1; + $attendee_list[$nid]->session = $session_id; + + //record the category of person + $session_count[$session_id][$gender]++; + $session_count[$session_id]['total']++; + + //record the age bracket + //$age = _booking_get_age_years($attendee_list[$nid]->booking_dob); + + if ($age < 20) + $session_count[$session_id]['under20']++; + elseif($age >= 20 && $age < 25) + $session_count[$session_id]['20to25']++; + else + $session_count[$session_id]['over25']++; +} + /** * Function for cleaning up study groups for people that have withdrawn their registration diff --git a/booking.install b/booking.install index 7277be9..c39e4f0 100644 --- a/booking.install +++ b/booking.install @@ -375,6 +375,15 @@ function booking_update_7217() { db_add_field('booking_room_definition', 'booking_room_queenbeds', $spec); } +/** +* Add bed type to mapping table +*/ +function booking_update_7218() { + $spec = array('type' => 'int', 'unsigned' => TRUE, 'not null' => FALSE, 'disp-width' => '10', 'default' => 0); + db_add_field('booking_room_mapping', 'booking_room_bedtype', $spec); +} + + /** * Implementation of hook_install(). */ diff --git a/booking.register.inc b/booking.register.inc index 1820d49..4c2c5a8 100644 --- a/booking.register.inc +++ b/booking.register.inc @@ -1065,6 +1065,9 @@ function booking_load_query($node_ids = NULL, $fetchAssoc = FALSE) $query->join('booking_price', 'pr', 'p.booking_payment_id = pr.pid'); //add travel form info if it exists $query->leftJoin('booking_travel', 't', 'p.nid = t.booking_person_nid'); + //add room info + $query->leftJoin('booking_room_mapping', 'rm', 'p.nid = rm.booking_nodeid'); + $query->leftJoin('booking_room_definition', 'r', 'rm.booking_roomid = r.rid'); //add the joins to flatten out study groups into columns if (variable_get('booking_enable_studygroups', 0) == 1) @@ -1089,7 +1092,9 @@ function booking_load_query($node_ids = NULL, $fetchAssoc = FALSE) //add the database fields we always want to retrieve $query->fields('p') ->fields('t') - ->fields('pr', array('booking_price', 'booking_price_descrip','booking_late_price')); + ->fields('pr', array('booking_price', 'booking_price_descrip','booking_late_price')) + ->fields('rm', array('booking_roomid', 'booking_room_bedtype')) + ->fields('r', array('rid','booking_room_location_id', 'booking_room_number')); //now add the study group fields if applicable if (variable_get('booking_enable_studygroups', 0) == 1) @@ -1103,8 +1108,6 @@ function booking_load_query($node_ids = NULL, $fetchAssoc = FALSE) //$query->addField('s' . $i, 'booking_is_leader', 'session' . $i . '_leader'); //$query->addField('s' . $i, 'booking_is_reserveleader', 'session' . $i . '_reserveleader'); //$query->addField('s' . $i, 'booking_is_helper', 'session' . $i . '_helper'); - - } } @@ -1615,6 +1618,25 @@ function booking_view($node, $view_mode) { $rows[] = array(t('Previous Mission Experience:'), $node->booking_mission_experience_details); } $rows[] = array(t('Temporary UUID:'), $node->booking_tempid); + + //if room allocation is defined, display that + if (! empty($node->rid)) + { + $room_rows = array(); + $room_rows[] = array(t('Room Location'), _booking_room_location_lookup($node->booking_room_location_id)); + $room_rows[] = array(t('Room Number'), $node->booking_room_number); + $room_rows[] = array(t('Bed Type'), _booking_room_bedtype_lookup($node->booking_room_bedtype)); + + $node->content['room-heading'] = array( + '#markup' => "

Room Details

", + '#weight' => 2, + ); + + $node->content['room-details'] = array( + '#markup' => theme('table', array('header' => $header, 'rows' => $room_rows)), + '#weight' => 3, + ); + } //add the travel info if it has been defined for this attendee if (! empty($node->tid)) @@ -1632,12 +1654,12 @@ function booking_view($node, $view_mode) { $node->content['travel-heading'] = array( '#markup' => "

Travel Details

", - '#weight' => 2, + '#weight' => 4, ); $node->content['travel-details'] = array( '#markup' => theme('table', array('header' => $header, 'rows' => $travel_rows)), - '#weight' => 3, + '#weight' => 5, ); } @@ -1654,25 +1676,9 @@ function booking_view($node, $view_mode) { for ($i = 1; $i <= variable_get('booking_studygroup_count','0'); $i++) { - //calculate the session references $sessionid = "session" . $i; $roleid = $sessionid . "_role"; - /* - $role = ""; - - - $leaderid = $sessionid . "_leader"; - $helperid = $sessionid . "_helper"; - $reserveleaderid = $sessionid . "_reserveleader"; - - if ($node->$leaderid == 'Y') - $role = "Leader"; - elseif ($node->$helperid == 'Y') - $role = "Helper"; - elseif ($node->$reserveleaderid == 'Y') - $role = "Reserve Leader"; - */ $group_rows[] = array(t('' . $studygroups[$i]->booking_studygroup_descrip . ' group number'), $node->$sessionid); $group_rows[] = array(t('Role'), _booking_studygroup_role_lookup($node->$roleid)); @@ -1680,12 +1686,12 @@ function booking_view($node, $view_mode) { $node->content['group-heading'] = array( '#markup' => "

Study Groups

", - '#weight' => 4, + '#weight' => 6, ); $node->content['group-details'] = array( '#markup' => theme('table', array('header' => $header, 'rows' => $group_rows)), - '#weight' => 5, + '#weight' => 7, ); } diff --git a/booking.rooms.inc b/booking.rooms.inc index 0a7674d..200ce5b 100644 --- a/booking.rooms.inc +++ b/booking.rooms.inc @@ -144,26 +144,32 @@ function booking_rooms_define_form_submit($form, &$form_state) { /** * Function for allocating rooms */ -function booking_rooms_allocate_form() { +function booking_rooms_allocate_form($node, &$form_state) { global $event; $form = array(); $attendee_select = array(); $options = array(); $counter = 0; - + //make a list of all attendees $attendee_select[] = ''; - $query = db_query("SELECT nid, booking_firstname, booking_lastname FROM {booking_person} " . + $query = db_query("SELECT nid, booking_firstname, booking_lastname, booking_gender FROM {booking_person} " . "where booking_event_id = :eid and booking_status=1 order by booking_lastname, booking_firstname", array(':eid' => $event->eid)); foreach($query as $row) - $attendee_select[$row->nid] = $row->booking_firstname . ' ' . $row->booking_lastname; + $attendee_select[$row->nid] = $row->booking_firstname . ' ' . $row->booking_lastname . ' ['. $row->booking_gender . ']'; //query for room definitions $room_query = db_query("SELECT * FROM {booking_room_definition}"); + //query for existing room allocations + $room_mapping_query = db_query("SELECT * FROM {booking_room_mapping} WHERE booking_eventid = :eid", array(':eid' => $event->eid)); + $room_mapping = $room_mapping_query->fetchAll(); + + watchdog('booking', "
Loading existing room allocations:\n@info
", array('@info' => print_r( $room_mapping, true))); + //attach the custom css $form['#attached']['css'] = array( drupal_get_path('module', 'booking') . '/booking.css', @@ -180,88 +186,94 @@ function booking_rooms_allocate_form() { 'booking_room_queenbed_p2' => array('data' => t('Queen Bed Person 2')), ); + $default_row = array(); + $default_row['booking_room_location'] = ""; + $default_row['booking_room_number'] = ""; + $default_row['booking_room_singlebed'] = ""; + $default_row['booking_room_doublebed_p1'] = ""; + $default_row['booking_room_doublebed_p2'] = ""; + $default_row['booking_room_queenbed_p1'] = ""; + $default_row['booking_room_queenbed_p2'] = ""; + foreach ($room_query as $data) { - /* - $row = array ( - 'data' => array( - _booking_room_location_lookup($data->booking_room_location_id), - $data->booking_room_number, - ) - ); - */ + //load the existing bed mappings for this room + $existing_beds = array(); + for ($i = 1; $i <= 3; $i++) + { + foreach ($room_mapping as $mapping) + { + if ($mapping->booking_roomid == $data->rid && $mapping->booking_room_bedtype == $i) + { + $existing_beds[$i][] = $mapping->booking_nodeid; + } + } + } + + watchdog('booking', "
Existing bed mappings:\n@info
", array('@info' => print_r( $existing_beds, true))); + //create a row that contains just the room location and number - $row = array(); + $row = _booking_clone_array($default_row); $row['booking_room_location'] = _booking_room_location_lookup($data->booking_room_location_id); $row['booking_room_number'] = $data->booking_room_number; - $row['booking_room_singlebed'] = ""; - $row['booking_room_doublebed_p1'] = ""; - $row['booking_room_doublebed_p2'] = ""; - $row['booking_room_queenbed_p1'] = ""; - $row['booking_room_queenbed_p2'] = ""; $row['#attributes'] = array('id' => array("new-group-row")); - $options[$counter++] = $row; - + //create an additional row for each single bed - for ($i = 1; $i <= $data->booking_room_singlebeds; $i++) + for ($i = 0; $i < $data->booking_room_singlebeds; $i++) { - $row = array(); - $row['booking_room_location'] = ""; - $row['booking_room_number'] = ""; + //retrieve the default value if one exists + $default = (!empty($existing_beds[1][$i])) ? $existing_beds[1][$i] : 0; + + $row = _booking_clone_array($default_row); $row['booking_room_singlebed'] = array('data' => array( '#type' => 'select', '#options' => $attendee_select, - '#name' => 'booking_room_singlebed[' . $data->rid . '][' . $i . ']', - )); - $row['booking_room_doublebed_p1'] = ""; - $row['booking_room_doublebed_p2'] = ""; - $row['booking_room_queenbed_p1'] = ""; - $row['booking_room_queenbed_p2'] = ""; + '#name' => 'booking_room_singlebed[' . $data->rid . '][' . $i . ']', + '#value' => $default, + )); $options[$counter++] = $row; } //create an additional row for each double bed - for ($i = 1; $i <= $data->booking_room_doublebeds; $i++) + //$j is our counter that increments twice as fast as $i to cater for both beds + $j = 0; + for ($i = 0; $i < $data->booking_room_doublebeds; $i++) { - $row = array(); - $row['booking_room_location'] = ""; - $row['booking_room_number'] = ""; - $row['booking_room_singlebed'] = ""; + $row = _booking_clone_array($default_row); $row['booking_room_doublebed_p1'] = array('data' => array( '#type' => 'select', '#options' => $attendee_select, '#name' => 'booking_room_doublebed_p1[' . $data->rid . '][' . $i . ']', + '#value' => (!empty($existing_beds[2][$j])) ? $existing_beds[2][$j++] : 0, )); $row['booking_room_doublebed_p2'] = array('data' => array( '#type' => 'select', '#options' => $attendee_select, '#name' => 'booking_room_doublebed_p2[' . $data->rid . '][' . $i . ']', - )); - $row['booking_room_queenbed_p1'] = ""; - $row['booking_room_queenbed_p2'] = ""; + '#value' => (!empty($existing_beds[2][$j])) ? $existing_beds[2][$j++] : 0, + )); $options[$counter++] = $row; } //create an additional row for each queen bed + //$j is our counter that increments twice as fast as $i to cater for both beds + $j = 0; for ($i = 1; $i <= $data->booking_room_queenbeds; $i++) { - $row = array(); - $row['booking_room_location'] = ""; - $row['booking_room_number'] = ""; - $row['booking_room_singlebed'] = ""; - $row['booking_room_doublebed_p1'] = ""; - $row['booking_room_doublebed_p2'] = ""; + $row = _booking_clone_array($default_row); $row['booking_room_queenbed_p1'] = array('data' => array( '#type' => 'select', '#options' => $attendee_select, - '#name' => 'booking_room_queenbed_p1[' . $data->rid . '][' . $i . ']', + '#name' => 'booking_room_queenbed_p1[' . $data->rid . '][' . $i . ']', + '#value' => (!empty($existing_beds[3][$j])) ? $existing_beds[3][$j++] : 0, )); $row['booking_room_queenbed_p2'] = array('data' => array( '#type' => 'select', '#options' => $attendee_select, - '#name' => 'booking_room_queenbed_p2[' . $data->rid . '][' . $i . ']', + '#name' => 'booking_room_queenbed_p2[' . $data->rid . '][' . $i . ']', + '#value' => (!empty($existing_beds[3][$j])) ? $existing_beds[3][$j++] : 0, )); $options[$counter++] = $row; } @@ -276,8 +288,11 @@ function booking_rooms_allocate_form() { ); //so we can access the dropdown elements - $form['booking_room_singlebeds'] = array( '#type' => 'value', ); - $form['booking_room_doublebeds'] = array( '#type' => 'value', ); + $form['booking_room_singlebed'] = array( '#type' => 'value', ); + $form['booking_room_queenbed_p1'] = array( '#type' => 'value', ); + $form['booking_room_queenbed_p2'] = array( '#type' => 'value', ); + $form['booking_room_doublebed_p1'] = array( '#type' => 'value', ); + $form['booking_room_doublebed_p2'] = array( '#type' => 'value', ); $form['submit'] = array ( '#type' => 'submit', @@ -289,4 +304,63 @@ function booking_rooms_allocate_form() { ); } - \ No newline at end of file + +/** + * Process the submission for room assignment + */ +function booking_rooms_allocate_form_submit($form, &$form_state) { + global $event; + $counter = 0; + $checkboxes = $form_state['values']['table']; + //$singlebed_ids = $form_state['values']['booking_room_singlebed']; + $values = $form_state['input']; + + $bed_inputs = array( + 'booking_room_singlebed' => 1, + 'booking_room_doublebed_p1' => 2, + 'booking_room_doublebed_p2' => 2, + 'booking_room_queenbed_p1' => 3, + 'booking_room_queenbed_p2' => 3, + ); + + //watchdog('booking', "
Room assignment submission:\n@info
", array('@info' => print_r( $singlebed_ids, true))); + + //go through the different bed types + foreach ($bed_inputs as $type => $type_id) + { + //watchdog('booking', "Bed type !type with id !id", array('!type' => $type, '!id' => $type_id)); + //watchdog('booking', "
Room assignment submission:\n@info
", array('@info' => print_r( $form_state['values'][$type], true))); + + //if this bed type wasn't defined in the form, skip it + if (empty($form_state['values'][$type])) + continue; + + //go through each room + foreach($form_state['values'][$type] as $key => $value) + { + //go through each bed + foreach ($value as $index => $nid) + { + //if this is actually a person to process + if ($nid > 0) + { + drupal_set_message(t('Assigning person id !id to a !type bed in room id !room.', + array('!id' => $nid, '!room' => $key, '!type' => $type_id))); + + //TODO: Check there isn't already a mapping for this person + + $result = db_insert('booking_room_mapping') + ->fields(array( + 'booking_roomid' => $key, + 'booking_eventid' => $event->eid, + 'booking_nodeid' => $nid, + 'booking_room_bedtype' => $type_id, + )) + ->execute(); + + } + } //each bed + } //each room + } //each bed type + +} \ No newline at end of file diff --git a/booking.studygroups.inc b/booking.studygroups.inc index 0b1575c..f357ff2 100644 --- a/booking.studygroups.inc +++ b/booking.studygroups.inc @@ -572,73 +572,6 @@ function booking_studygroups_edit_form_submit($form, &$form_state) { */ -/** - * Function to correctly clone an associative array storing objects - * Taken from http://stackoverflow.com/questions/1532618/is-there-a-function-to-make-a-copy-of-a-php-array-to-another - */ -function booking_clone_array($copied_array) { - return array_map(function($element) { - return ( - ((is_array($element)) - ? call_user_func(__FUNCTION__, $element) - : ((is_object($element)) - ? clone $element - : $element - ) - ) - ); - }, $copied_array); -} - - -/** - * Function to randomise the ordering of an array - * taken from http://stackoverflow.com/questions/4102777/php-random-shuffle-array-maintaining-key-value - */ -function booking_shuffle_assoc($list) { - if (!is_array($list)) return $list; - - $keys = array_keys($list); - shuffle($keys); - $random = array(); - foreach ($keys as $key) { - $random[$key] = $list[$key]; - } - return $random; -} - -/** - * Function to mark an attendee as processed for group calculations - * @param $input string containing passport number to be verified - */ -function booking_assign_attendee_group($nid, $session_id, $gender, $age, &$attendee_list, &$session_count) -{ - - if (empty($nid)) - { - drupal_set_message(t('Attempting to process a non-existent node id.')); - return; - } - - //mark this person as processed in the working list - $attendee_list[$nid]->processed = 1; - $attendee_list[$nid]->session = $session_id; - - //record the category of person - $session_count[$session_id][$gender]++; - $session_count[$session_id]['total']++; - - //record the age bracket - //$age = _booking_get_age_years($attendee_list[$nid]->booking_dob); - - if ($age < 20) - $session_count[$session_id]['under20']++; - elseif($age >= 20 && $age < 25) - $session_count[$session_id]['20to25']++; - else - $session_count[$session_id]['over25']++; -} - /** * Function for calculating who belongs to which study group */ @@ -731,7 +664,7 @@ function booking_studygroups_calculate() { //create a temporary copy of the attendee list to work with for this study group $working_list = array(); - $working_list = booking_shuffle_assoc(booking_clone_array($attendees)); + $working_list = _booking_shuffle_assoc(_booking_clone_array($attendees)); //set up the iterator $obj = new ArrayObject( $working_list ); $it = $obj->getIterator(); @@ -764,7 +697,7 @@ function booking_studygroups_calculate() { //mark this position as being used $age = _booking_get_age_years($working_list[$person->booking_node_id]->booking_dob); - booking_assign_attendee_group($person->booking_node_id, $person->booking_session_id, 'male', $age, $working_list, $session_count); + _booking_assign_attendee_group($person->booking_node_id, $person->booking_session_id, 'male', $age, $working_list, $session_count); //get any potential spouse or boyfriend/girlfriend $spouse_id = $working_list[$person->booking_node_id]->booking_partner_id; @@ -778,7 +711,7 @@ function booking_studygroups_calculate() { )); //allocate the spouse to the same session $age = _booking_get_age_years($working_list[$spouse_id]->booking_dob); - booking_assign_attendee_group($spouse_id, $person->booking_session_id, 'female', $age, $working_list, $session_count); + _booking_assign_attendee_group($spouse_id, $person->booking_session_id, 'female', $age, $working_list, $session_count); } elseif ($bf_gf_id > 0) { @@ -787,7 +720,7 @@ function booking_studygroups_calculate() { '!num' => $session_count[$person->booking_session_id]['total']) )); //allocate the boyfriend/girlfriend to the same session - booking_assign_attendee_group($bf_gf_id, $person->booking_session_id, $working_list[$bf_gf_id]->booking_gender == 'M' ? 'male' : 'female', + _booking_assign_attendee_group($bf_gf_id, $person->booking_session_id, $working_list[$bf_gf_id]->booking_gender == 'M' ? 'male' : 'female', _booking_get_age_years($working_list[$bf_gf_id]->booking_dob), $working_list, $session_count); } } @@ -864,7 +797,7 @@ function booking_studygroups_calculate() { $partner_id = $current->booking_partner_id; $bf_gf_id = $current->booking_bf_gf_nid; - booking_assign_attendee_group($it->key(), $i, $gender, $age, $working_list, $session_count); + _booking_assign_attendee_group($it->key(), $i, $gender, $age, $working_list, $session_count); //check if the attendee was married if ($partner_id > 0) @@ -873,7 +806,7 @@ function booking_studygroups_calculate() { drupal_set_message(t('Assigning spouse (id !spouse) of id !id to session !session (currently with !num people).', array('!id' => $it->key(), '!session' => $i, '!spouse' => $current->booking_partner_id, '!num' => $session_count[$i]['total']))); - booking_assign_attendee_group($partner_id, $i, $working_list[$partner_id]->booking_gender == 'M' ? 'male' : 'female', + _booking_assign_attendee_group($partner_id, $i, $working_list[$partner_id]->booking_gender == 'M' ? 'male' : 'female', _booking_get_age_years($working_list[$partner_id]->booking_dob), $working_list, $session_count); } @@ -884,7 +817,7 @@ function booking_studygroups_calculate() { drupal_set_message(t('Assigning bf/gf (id !spouse) of id !id to session !session (currently with !num people).', array('!id' => $it->key(), '!session' => $i, '!spouse' => $current->booking_bf_gf_nid, '!num' => $session_count[$i]['total']))); - booking_assign_attendee_group($bf_gf_id, $i, $working_list[$bf_gf_id]->booking_gender == 'M' ? 'male' : 'female', + _booking_assign_attendee_group($bf_gf_id, $i, $working_list[$bf_gf_id]->booking_gender == 'M' ? 'male' : 'female', _booking_get_age_years($working_list[$bf_gf_id]->booking_dob), $working_list, $session_count); } }