def save_attachment(self, target_id, _id, text, attachment): timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M') if _id == '': attachment_o = dict(type='attachment', _id=genUID(type='attachment'), target_id=target_id, attachment_state=0, tags=list(), history=list(), text='') attachment_change='new' attachment_o['timestamp'] = timestamp else: attachment_o = common_couch.getAttachment(holly_couch, _id) history = attachment_o['history'] if history == None: history = list() else: history.append([timestamp, attachment_o['text']]) attachment_o['history'] = history attachment_change = 'changed' attachment_o['last_changed_by'] = getLoggedInUserId(request) attachment_o['text'] = text holly_couch[attachment_o['_id']] = attachment_o file = request.POST['attachment'] if file != '': holly_couch.put_attachment(attachment_o, attachment.file, filename=attachment.filename) # TODO FIX BELOW #remember_attachment_change(holly_couch, target_id=target_id, attachment_id=attachment_o['_id'], changed_by=getLoggedInUserId(request), attachment_change=attachment_change) # TODO: where do we go from here? redirect_to = '/' if 'visiting_group' in attachment_o['target_id']: redirect_to = '/visiting_group/show_visiting_group?visiting_group_id='+attachment_o['target_id'] raise redirect(redirect_to)
def save_note(self, target_id, _id, text): timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M') if _id == '': note_o = dict(type='note', _id=genUID(type='note'), target_id=target_id, note_state=0, tags=list(), history=list(), text='') note_change='new' note_o['timestamp'] = timestamp else: note_o = common_couch.getNote(holly_couch, _id) history = note_o['history'] if history == None: history = list() else: history.append([timestamp, note_o['text']]) note_o['history'] = history note_change = 'changed' note_o['last_changed_by'] = getLoggedInUserId(request) note_o['text'] = text holly_couch[note_o['_id']] = note_o remember_note_change(holly_couch, target_id=target_id, note_id=note_o['_id'], changed_by=getLoggedInUserId(request), note_change=note_change) # TODO: where do we go from here? redirect_to = '/' if 'visiting_group' in note_o['target_id']: redirect_to = '/visiting_group/show_visiting_group?visiting_group_id='+note_o['target_id'] raise redirect(redirect_to)
def do_set_state(self, holly_couch, booking_id, booking_o, state): #...only PL can set state=20 (approved) or -10 (disapproved) if state=='20' or state=='-10' or booking_o['booking_state'] == 20 or booking_o['booking_state']==-10: ok = has_level('pl').check_authorization(request.environ) # TODO: fix # if not ok: # flash('Only PL can do that. %s' % request.referrer, 'warning') # raise redirect(request.referrer) activity = holly_couch[booking_o['activity_id']] booking_day = holly_couch[booking_o['booking_day_id']] booking_o['booking_state'] = state booking_o['last_changed_by_id'] = getLoggedInUserId(request) holly_couch[booking_id] = booking_o remember_workflow_state_change(holly_couch, booking=booking_o, state=state, booking_day_date=booking_day['date'], activity_title=activity['title'])
def save_visiting_group_properties(self, visiting_group_id=None, name='', info='', from_date=None, to_date=None, contact_person='', contact_person_email='', contact_person_phone='', visiting_group_properties=None, camping_location='', boknr='', password='', subtype=''): log.info('save_visiting_group_properties') ensurePostRequest(request, __name__) is_new = ((None == visiting_group_id) or (visiting_group_id == '')) #...this is a hack so we can direct the id of the visiting group for special groups if not is_new: if 'visiting_group' not in visiting_group_id: is_new = True id_c = 'visiting_group.'+visiting_group_id else: id_c = genUID(type='visiting_group') if is_new: # TODO: make sure subtype is in one of if not subtype in ['program','course','staff']: flash('error with subtype') raise redirect(request.referrer) visiting_group_c = dict(type='visiting_group', subtype=subtype, tags=[], boknstatus=0, vodbstatus=0) #...populate sheets and computed sheets? else: id_c = visiting_group_id visiting_group_c = holly_couch[id_c] #visiting_group_c['type'] = 'visiting_group' visiting_group_c['name'] = name visiting_group_c['info'] = cleanHtml(info) ok, ok_from_date = sanitizeDate(from_date) if not ok: # TODO better error handling here flash('error with from-date') raise redirect(request.referrer) visiting_group_c['from_date'] = ok_from_date ok, ok_to_date = sanitizeDate(to_date) if not ok: # TODO: better error handling here flash('error with to-date') raise redirect(request.referrer) visiting_group_c['to_date'] = ok_to_date visiting_group_c['contact_person'] = contact_person visiting_group_c['contact_person_email'] = contact_person_email visiting_group_c['contact_person_phone'] = contact_person_phone # TODO: boknr maybe shouldnt be changeble if program or vodb state has passed by preliminary (10) ? visiting_group_c['boknr'] = boknr # TODO: password for group should be set in special page if password != '': visiting_group_c['password'] = password visiting_group_c['camping_location'] = camping_location #...now we have to update all cached content, so we need all bookings that belong to this visiting group visiting_group_c['visiting_group_properties'] = populatePropertiesAndRemoveUnusedProperties(visiting_group_c, visiting_group_properties) updateBookingsCacheContentAfterPropertyChange(holly_couch, visiting_group_c, getLoggedInUserId(request)) vodb_tag_times_tags = computeAllUsedVisitingGroupsTagsForTagSheet(visiting_group_c['tags'], visiting_group_c.get('vodb_tag_sheet',dict(items=[]))['items']) updateVisitingGroupComputedSheets(visiting_group_c, visiting_group_c['visiting_group_properties'], sheet_map=dict(vodb_eat_sheet=vodb_eat_times_options, vodb_live_sheet=vodb_live_times_options, vodb_tag_sheet=vodb_tag_times_tags)) holly_couch[id_c] = visiting_group_c if visiting_group_c.has_key('visiting_group_id'): raise redirect('/visiting_group/show_visiting_group?visiting_group_id='+visiting_group_c['visiting_group_id']) raise redirect('/visiting_group/view_all')
def delete_tag(self, id, tag): log.info("delete_tag()") ensurePostRequest(request, __name__) vgroup = common_couch.getVisitingGroup(holly_couch, id) old_tags = vgroup.get('tags',[]) new_tags = [t for t in old_tags if t.strip() != tag.strip()] vgroup['tags'] = new_tags holly_couch[id] = vgroup remember_tag_change(holly_couch, old_tags=old_tags, new_tags=new_tags, visiting_group_id=id, visiting_group_name=vgroup['name'], changed_by=getLoggedInUserId(request)) return dict(tags=new_tags)
def add_tags(self, id, tags): log.info("add_tags()") ensurePostRequest(request, __name__) vgroup = common_couch.getVisitingGroup(holly_couch, id) old_tags = vgroup.get('tags',[]) remember_old_tags = [t for t in old_tags] new_tags = [t.strip() for t in tags.split(',')] for t in new_tags: if t not in old_tags: old_tags.append(t) vgroup['tags'] = old_tags holly_couch[id] = vgroup remember_tag_change(holly_couch, old_tags=remember_old_tags, new_tags=old_tags, visiting_group_id=id, visiting_group_name=vgroup['name'], changed_by=getLoggedInUserId(request)) return dict(tags=old_tags)
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)
def save_vodb_group_properties(self, _id='', boknr='', name='', info='', camping_location='', vodb_contact_name='', vodb_contact_phone='', vodb_contact_email='', vodb_contact_address='', from_date='', to_date='', subtype='', visiting_group_properties=None): #...how do we handle new groups? Like new visiting_group, right? # better have type=visiting_group for all groups and then have subtypes=group, course, daytrip, funk, etc for filtering/deciding on additional capabillities id = _id is_new, vgroup_id = self.newOrExistingVgroupId(id) #...load or create new vgroup if is_new: # program_state = 0 # vodb_state = 0 if not subtype in ['program','course','staff']: tg.flash('error with subtype') raise redirect(request.referrer) visiting_group_o = dict(type='visiting_group', subtype=subtype, tags=[], boknstatus=0, vodbstatus=0) else: visiting_group_o = holly_couch[vgroup_id] #...fill in data visiting_group_o['name'] = name visiting_group_o['info'] = info visiting_group_o['from_date'] = str(from_date) visiting_group_o['to_date'] = str(to_date) visiting_group_o['vodb_contact_name'] = vodb_contact_name visiting_group_o['vodb_contact_email'] = vodb_contact_email visiting_group_o['vodb_contact_phone'] = vodb_contact_phone visiting_group_o['vodb_contact_address'] = vodb_contact_address visiting_group_o['boknr'] = boknr # if is_new: # visiting_group_o['boknstatus'] = program_state # visiting_group_o['vodbstatus'] = vodb_state visiting_group_o['camping_location'] = camping_location # TODO: figure out the order of updating things if something goes wrong. #...update properties visiting_group_o['visiting_group_properties'] = populatePropertiesAndRemoveUnusedProperties(visiting_group_o, visiting_group_properties) updateBookingsCacheContentAfterPropertyChange(holly_couch, visiting_group_o, getLoggedInUserId(request)) vodb_tag_times_tags = computeAllUsedVisitingGroupsTagsForTagSheet(visiting_group_o['tags'], visiting_group_o.get('vodb_tag_sheet',dict(items=[]))['items']) updateVisitingGroupComputedSheets(visiting_group_o, visiting_group_o['visiting_group_properties'], sheet_map=dict(vodb_eat_sheet=vodb_eat_times_options, vodb_live_sheet=vodb_live_times_options, vodb_tag_sheet=vodb_tag_times_tags)) holly_couch[vgroup_id] = visiting_group_o if visiting_group_o.has_key('_id'): raise redirect('/vodb_group/view_vodb_group?visiting_group_id='+visiting_group_o['_id']) raise redirect('/vodb_group/view_all')
def save_vodb_group_properties(self, vodb_group_id='', boknr='', name='', info='', camping_location='', vodb_contact_name='', vodb_contact_phone='', vodb_contact_email='', vodb_contact_address='', from_date='', to_date='', subtype='', visiting_group_properties=None): ensurePostRequest(request, __name__) log.debug('save_vodb_group_properties') id = vodb_group_id is_new, vgroup_id = self.newOrExistingVgroupId(id) #...load or create new vgroup if is_new: log.info("saving new group") # program_state = 0 # vodb_state = 0 if not subtype in ['program','course','staff']: flash('error with subtype') raise redirect(request.referrer) visiting_group_o = dict(type='visiting_group', subtype=subtype, tags=[], boknstatus=0, vodbstatus=0) else: visiting_group_o = holly_couch[vgroup_id] #...fill in data visiting_group_o['name'] = name visiting_group_o['info'] = cleanHtml(info) visiting_group_o['from_date'] = sanitizeDate(from_date)[1] # TODO better error handling visiting_group_o['to_date'] = sanitizeDate(to_date)[1] # TODO better error handling visiting_group_o['vodb_contact_name'] = vodb_contact_name visiting_group_o['vodb_contact_email'] = vodb_contact_email visiting_group_o['vodb_contact_phone'] = vodb_contact_phone visiting_group_o['vodb_contact_address'] = vodb_contact_address visiting_group_o['boknr'] = boknr visiting_group_o['camping_location'] = camping_location # TODO: figure out the order of updating things if something goes wrong. #...update properties visiting_group_o['visiting_group_properties'] = populatePropertiesAndRemoveUnusedProperties(visiting_group_o, visiting_group_properties) updateBookingsCacheContentAfterPropertyChange(holly_couch, visiting_group_o, getLoggedInUserId(request)) vodb_tag_times_tags = computeAllUsedVisitingGroupsTagsForTagSheet(visiting_group_o['tags'], visiting_group_o.get('vodb_tag_sheet',dict(items=[]))['items']) updateVisitingGroupComputedSheets(visiting_group_o, visiting_group_o['visiting_group_properties'], sheet_map=dict(vodb_eat_sheet=vodb_eat_times_options, vodb_live_sheet=vodb_live_times_options, vodb_tag_sheet=vodb_tag_times_tags)) holly_couch[vgroup_id] = visiting_group_o if visiting_group_o.has_key('_id'): raise redirect('/vodb_group/view_vodb_group?visiting_group_id='+visiting_group_o['_id']) raise redirect('/vodb_group/view_all')