Esempio n. 1
0
    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)
Esempio n. 2
0
    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
Esempio n. 3
0
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)