def save_activity_properties(self, id=None, title=None, external_link='', internal_link='', print_on_demand_link='', description='', tags='', capacity=0, default_booking_state=0, activity_group_id=1, gps_lat=0, gps_long=0, equipment_needed=False, education_needed=False, certificate_needed=False, bg_color='', guides_per_slot=0, guides_per_day=0 ): ensurePostRequest(request, name=__name__) is_new = None == id or '' == id if is_new: activity = dict(type='activity') # TODO: need to set subtype on activity or is it handled by group belonging? id = genUID(type='activity') else: activity = common_couch.getActivity(holly_couch, id) activity['title'] = title activity['description'] = cleanHtml(description) activity['external_link'] = external_link activity['internal_link'] = internal_link activity['print_on_demand_link'] = print_on_demand_link activity['tags'] = tags activity['capacity'] = capacity # #activity.default_booking_state=default_booking_state activity['activity_group_id'] = activity_group_id # activity.gps_lat = gps_lat # activity.gps_long = gps_long activity['equipment_needed'] = equipment_needed activity['education_needed'] = education_needed activity['certificate_needed'] = certificate_needed activity['bg_color'] = bg_color activity['guides_per_slot'] = guides_per_slot activity['guides_per_day'] = guides_per_day holly_couch[id] = activity raise redirect('/activity/view_activity', activity_id=id)
def newOrExistingVgroupId(self, a_id): """returns the id if it exists or if a_id is empty or none, a new id is generated and returned.""" is_new = False r_id = a_id if ((None == a_id) or (a_id == '')): is_new = True r_id = genUID(type='visiting_group') return is_new, r_id
def remember_booking_change(holly_couch, booking_id=None, booking_day_id=None, visiting_group_id=None, note_id=None, change_op=None, change_text='', changed_by='', booking_content=''): """ For a better view of booking history, its better we have an enum (int) telling what kind of change we have: * schedule *unschedule *book_slot *new_booking_request *delete_booking_request *booking_properties_change *booking_request_change *booking_state_change *block_soft *block_hard *unblock *workflow_state_change """ bh = dict(type='booking_history') if type(change_op) ==types.StringType: change_op = change_op_lookup[change_op] bh['change_op'] = change_op bh['booking_content']=booking_content bh['change'] = change_text bh['changed_by'] = getLoggedInDisplayName(request) bh['timestamp'] = str(datetime.datetime.now()) bh['booking_id'] = booking_id bh['booking_day_id'] = booking_day_id if visiting_group_id != None: bh['visiting_group_id'] = visiting_group_id if note_id != None: bh['note_id'] = note_id holly_couch[genUID(type='booking_history')] = bh
def update_visiting_group_program_request(self, program_request_info='', contact_person='', contact_person_email='', contact_person_phone='', vgroup_id='', program_request_input='', have_skippers=False, miniscout=False, ready_to_process=False, age_group_input='', saveButton='', submitButton=''): # TODO: once property data has changed, we somehow need to propagate that property data to all places where the properties are used BUT I dont think we really waht to propagate it unless we do some state-change, # we probably want to check the data before it is allowed to progress into other parts of the system. # TODO: We lost a lot of work, but our aim is to introduce the validation_error_messages list to contain all problems we have encountered. # what about making a subclassed list which can add speciealy formatted messages? # also, we should hav a comprehensive from-date-to-date checker # # dont forget to check for empty fm/em/evening # also common_couch code should be added # # make a validation_error_contect object that can be passed around and a date range checker and similar. # essentially we want to store section(1,2,3) property name and message. How to fix it. # # # log.info("update_visiting_group_program_request()") ensurePostRequest(request, __name__) validation_error_messages = ValidationErrorMessages() visiting_group_id = str(vgroup_id) visiting_group_o = common_couch.getVisitingGroup(holly_couch, visiting_group_id) may_change_request_data = (0 == visiting_group_o['boknstatus']) visiting_group_o['contact_person'] = contact_person visiting_group_o['contact_person_email'] = contact_person_email visiting_group_o['contact_person_phone'] = contact_person_phone if may_change_request_data: visiting_group_o['program_request_info'] = program_request_info visiting_group_o['program_request_miniscout'] = miniscout visiting_group_o['program_request_have_skippers'] = have_skippers visiting_group_o['program_request_age_group'] = age_group_input visiting_group_o['program_request'] = program_request_input #...iterate through age_group_data, items is a list of dicts... age_group_data = json.loads(age_group_input) age_group_data_items = age_group_data['items'] #...We should process the properties of the submitted form, not the other way around for tmp_age_group in age_group_data_items: process_property = tmp_age_group['property'] log.debug('processing property:' + process_property ) tmp_vgroup_property = None property_found = False property_id = None for tmp_vgroup_property_id, tmp_vgroup_property in visiting_group_o['visiting_group_properties'].items(): if tmp_vgroup_property['property'] == process_property: property_found = True property_id = tmp_vgroup_property log.debug('*** property %ss match found, property_id=%s' % (process_property, property_id)) break if property_found: log.debug('old: ' + str(process_property) + '=' + str(tmp_vgroup_property['value'])) # TODO: maybe sanitize so value must be an int? tmp_vgroup_property['value'] = tmp_age_group['value'] #...check that dates are within valid ranges ok_1, tmp_vgroup_property['from_date'] = sanitizeDate(tmp_age_group['from_date'], default_date=tmp_vgroup_property['from_date'] ) if not ok_1: validation_error_messages.report('properties', u'Från-datum som tillhör åldersgrupp %s har fel format.' % tmp_vgroup_property['property'], problematic_value=tmp_age_group['from_date'], explanation_key='date_format' ) ok_2, tmp_vgroup_property['to_date'] = sanitizeDate(tmp_age_group['to_date'], default_date=tmp_vgroup_property['to_date'] ) if not ok_2: validation_error_messages.report('properties', u'Till-datum som tillhör åldersgrupp %s har fel format.' % tmp_vgroup_property['property'], problematic_value=tmp_age_group['to_date'], explanation_key='date_format' ) ok_3 = (tmp_vgroup_property['to_date'] >= tmp_vgroup_property['from_date'] ) if not ok_3: validation_error_messages.report('properties', u'Till-datum kan inte inträffa före från-datum, se datumen i åldersgruppen %s.' % tmp_vgroup_property['property'], problematic_value=tmp_age_group['from_date'] + ' - ' + tmp_age_group['from_date'], explanation_key='date_order' ) ok_4 = tmp_vgroup_property['from_date'] >= visiting_group_o['from_date'] if not ok_4: validation_error_messages.report('properties', u'Från-datum %s som tillhör åldersgrupp %s kan inte inträffa före från-datum %s för din grupp.' % (tmp_vgroup_property['from_date'], tmp_vgroup_property['property'], visiting_group_o['from_date']), problematic_value=tmp_vgroup_property['from_date'], explanation_key='date_range') ok_5 = tmp_vgroup_property['to_date'] <= visiting_group_o['to_date'] if not ok_5: validation_error_messages.report('properties', u'Till-datum %s som tillhör åldersgrupp %s kan inte inträffa efter från-datum %s för din grupp.' % (tmp_vgroup_property['to_date'], tmp_vgroup_property['property'], visiting_group_o['to_date']), problematic_value=tmp_vgroup_property['to_date'], explanation_key='date_range') log.debug('new: ' + process_property + '=' + str(tmp_age_group['value'])) #visiting_group_o['visiting_group_properties'][property_id] = tmp_vgroup_property else: # property not found, new property log.debug('property not found, what do we do?') if 0 == tmp_age_group['value']: log.debug('never mind, value is zero') else: #...we need to add an entry in the dict, first we need to know the lowest key number lowest_key_number = 0 for tmp_key in visiting_group_o['visiting_group_properties'].keys(): if tmp_key > lowest_key_number: lowest_key_number = int(tmp_key) lowest_key_number +=1 # TODO: Date sanitation here too ok_6, new_from_date = sanitizeDate(tmp_age_group['from_date'], default_date=visiting_group_o['from_date'] ) if not ok_6: validation_error_messages.report('properties', u'Från-datum som tillhör åldersgrupp %s har fel format.' % tmp_vgroup_property['property'], problematic_value=tmp_age_group['from_date'], explanation_key='date_format' ) ok_7, new_to_date = sanitizeDate(tmp_age_group['to_date'], default_date=visiting_group_o['to_date'] ) if not ok_7: validation_error_messages.report('properties', u'Till-datum som tillhör åldersgrupp %s har fel format.' % tmp_vgroup_property['property'], problematic_value=tmp_age_group['to_date'], explanation_key='date_format' ) ok_8 = (new_from_date <= new_to_date) if not ok_8: validation_error_messages.report('properties', u'Till-datum kan inte inträffa före från-datum, se datumen i åldersgruppen %s.' % tmp_vgroup_property['property'], problematic_value=tmp_age_group['from_date'] + ' - ' + tmp_age_group['from_date'], explanation_key='date_order' ) ok_9 = tmp_age_group['from_date'] >= visiting_group_o['from_date'] if not ok_9: validation_error_messages.report('properties', u'Från-datum %s som tillhör åldersgrupp %s kan inte inträffa före från-datum %s för din grupp.' % (tmp_vgroup_property['from_date'], tmp_vgroup_property['property'], visiting_group_o['from_date']), problematic_value=tmp_vgroup_property['from_date'], explanation_key='date_range') ok_10 = tmp_age_group['to_date'] <= visiting_group_o['to_date'] if not ok_10: validation_error_messages.report('properties', u'Till-datum %s som tillhör åldersgrupp %s kan inte inträffa efter från-datum %s för din grupp.' % (tmp_vgroup_property['to_date'], tmp_vgroup_property['property'], visiting_group_o['to_date']), problematic_value=tmp_vgroup_property['to_date'], explanation_key='date_range') new_property_row = {u'description': tmp_age_group['age_group'], u'value': tmp_age_group['value'], u'from_date': new_from_date, u'to_date': new_to_date, u'property': tmp_age_group['property'], u'unit': tmp_age_group['unit']} x = visiting_group_o['visiting_group_properties'] x[str(lowest_key_number)] = new_property_row visiting_group_o['visiting_group_properties'] = x visiting_group_o['validation_error_messages'] = validation_error_messages visiting_group_o['validation_error_explanations'] = validation_error_messages.explanations holly_couch[visiting_group_o['_id']] = visiting_group_o # TODO: We should have a two step process: first construct all bookings (make a list) and if it all is successfull and no validation errors, thats when we actually write them to the db. # for the program request , iterate through it if may_change_request_data and not validation_error_messages.hasErrors(): if 'True' == ready_to_process: program_request_list = json.loads(program_request_input) for tmp_request in program_request_list['items']: log.debug('found request...' + str(tmp_request)) request_for_age_groups = [x[4:] for x in ['age_sma','age_spar','age_uppt','age_aven','age_utm','age_rov','age_led'] if tmp_request[x]] if len(request_for_age_groups) > 0: #...TODO: sanitize requested_date and make sure it is in range ok_r1, requested_date = sanitizeDate(tmp_request['requested_date'][:10], default_date='') if not ok_r1: validation_error_messages.report('booking request', u'Det angivna önskade datumet %s har fel format.' % tmp_request['requested_date'], problematic_value=tmp_request['requested_date'], explanation_key='date_format') if not ((requested_date >= visiting_group_o['from_date']) and (requested_date <= visiting_group_o['to_date'])): validation_error_messages.report('booking request', u'Det efterfrågade datumet %s är inte mellan din grupps från- och till- datum.' % tmp_request['requested_date'], problematic_value=tmp_request['requested_date'], explanation_key='date_range') # TODO: reuse the parsing of the date requested_date_o = time.strptime(requested_date, "%Y-%m-%d" ) requested_time = tmp_request['requested_time'] requested_activity_id = tmp_request['requested_activity'] no_activity_selected = ('' == requested_activity_id) # TODO: what if there is no requested activity? # TODO: how do users choose not to which anything after they have made a request? I think we actually will need a NULL request and this is where we among other things check the null request. booking_day_o = getBookingDayOfDate(holly_couch, requested_date) log.debug(booking_day_o) day_schema_id = booking_day_o['day_schema_id'] #...TODO day shema will probably always be the same so just query once per schema schema_o = common_couch.getDaySchema(holly_couch, day_schema_id) #...given fm/em/evening, look up the matching slot_id. Probably the schema will be needed (and maybe index 0,1,2,3...) tmp_activity_row = schema_o['schema'][requested_activity_id] #...look through the list, lets say we have a time and we need the slot id matching that time # then the reasonable way is too look through all list entries being dicts and return slot id when time match found activity_selection_map = dict() activity_selection_map['activity.30'] = u'Storbåt' time_selection_lookup = dict(FM='10:00:00', EM='15:00:00', EVENING='20:00:00') #...EVENING should be called Kväll # It should be possible to book just 'any' water program # these maps with id-text transaltion should maybe be available in the templating engine # dont forget to give the date formatter to the templating engine time_selection_translator = dict(EVENING=u'kväll') if validation_error_messages.hasErrors(): holly_couch[visiting_group_o['_id']] = visiting_group_o raise redirect(request.referrer) for tmp_slot_info in tmp_activity_row[1:]: if (tmp_slot_info['time_from'] < time_selection_lookup[requested_time]) and (tmp_slot_info['time_to'] > time_selection_lookup[requested_time]): match_slot_id = tmp_slot_info['slot_id'] log.debug('match for slot_id: ' + match_slot_id) # lets create a booking! # TODO: refactor the creation of a new booking new_booking = dict(type='booking', valid_from='', valid_to='', requested_date=requested_date, slot_id=match_slot_id, booking_day_id=booking_day_o['_id'], subtype='program') new_booking['visiting_group_id'] = str(vgroup_id) new_booking['valid_from'] = visiting_group_o['from_date'] new_booking['valid_to'] = visiting_group_o['to_date'] new_booking['reuested_date'] = requested_date new_booking['visiting_group_name'] = visiting_group_o['name'] new_booking['last_changed_by_id'] = getLoggedInUserId(request) activity_o = common_couch.getActivity(holly_couch, requested_activity_id) # TODO: the line below gts the properties wrong content = u'%s (önskar %s %d/%d %s) %s' % ( ' '.join(['$$%s'%a for a in request_for_age_groups ]) ,activity_selection_map.get(requested_activity_id, activity_o['title']), int(time.strftime("%d", requested_date_o)), int(time.strftime("%m", requested_date_o)), time_selection_translator.get(requested_time, requested_time), tmp_request['note'] ) new_booking['content'] = content new_booking['cache_content'] = computeCacheContent(holly_couch[visiting_group_id], content) new_booking['activity_id'] = requested_activity_id new_booking['booking_state'] = activity_o['default_booking_state'] slot_map = getSchemaSlotActivityMap(holly_couch, booking_day_o, subtype='program') slot = slot_map[match_slot_id] new_uid = genUID(type='booking') #...here we create the booking holly_couch[new_uid] = new_booking #...remember the created booking remember_new_booking_request(holly_couch, booking=new_booking, changed_by=getLoggedInUserId(request)) break visiting_group_o['boknstatus'] = 5 # TODO: use constant holly_couch[visiting_group_o['_id']] = visiting_group_o raise redirect(request.referrer)