class Osm::Event

Constants

EXTRA_ATTRIBUTES
LIST_ATTRIBUTES
SORT_BY

Public Class Methods

create(api, parameters) click to toggle source

Create an event in OSM If something goes wrong adding badges to OSM then the event returned will have been read from OSM @param [Osm::Api] api The api to use to make the request @return [Osm::Event, nil] the created event, nil if failed @raise [Osm::ObjectIsInvalid] If the Event is invalid

# File lib/osm/event.rb, line 219
def self.create(api, parameters)
  require_ability_to(api, :write, :events, parameters[:section_id])
  event = new(parameters)
  raise Osm::ObjectIsInvalid, 'event is invalid' unless event.valid?

  data = api.perform_query("events.php?action=addEvent&sectionid=#{event.section_id}", {
    'name' => event.name,
    'location' => event.location,
    'startdate' => event.start? ? event.start.strftime(Osm::OSM_DATE_FORMAT) : '',
    'enddate' => event.finish? ? event.finish.strftime(Osm::OSM_DATE_FORMAT) : '',
    'cost' => event.cost_tbc? ? '-1' : event.cost,
    'notes' => event.notes,
    'starttime' => event.start? ? event.start.strftime(Osm::OSM_TIME_FORMAT) : '',
    'endtime' => event.finish? ? event.finish.strftime(Osm::OSM_TIME_FORMAT) : '',
    'confdate' => event.confirm_by_date? ? event.confirm_by_date.strftime(Osm::OSM_DATE_FORMAT) : '',
    'allowChanges' => event.allow_changes ? 'true' : 'false',
    'disablereminders' => !event.reminders ? 'true' : 'false',
    'attendancelimit' => event.attendance_limit,
    'attendancereminder' => event.attendance_reminder,
    'limitincludesleaders' => event.attendance_limit_includes_leaders ? 'true' : 'false',
    'allowbooking' => event.allow_booking ? 'true' : 'false',
  })

  if (data.is_a?(Hash) && data.has_key?('id'))
    event.id = data['id'].to_i

    # The cached events for the section will be out of date - remove them
    cache_delete(api, ['events', event.section_id])

    # Add badge links to OSM
    badges_created = true
    event.badges.each do |badge|
      badges_created &= event.add_badge_link(api, badge)
    end

    if badges_created
      cache_write(api, ['event', event.id], event)
      return event
    else
      # Someting went wrong adding badges so return what OSM has
      return get(api, event.section_id, event.id)
    end
  else
    return nil
  end
end
get(api, section, event_id, options={}) click to toggle source

Get an event @param [Osm::Api] api The api to use to make the request @param [Osm::Section, Fixnum, to_i] section The section (or its ID) to get the events for @param [Fixnum, to_i] event_id The id of the event to get @!macro options_get @return [Osm::Event, nil] the event (or nil if it couldn't be found

# File lib/osm/event.rb, line 199
def self.get(api, section, event_id, options={})
  require_ability_to(api, :read, :events, section, options)
  section_id = section.to_i
  event_id = event_id.to_i
  cache_key = ['event', event_id]

  if !options[:no_cache] && cache_exist?(api, cache_key)
    return cache_read(api, cache_key)
  end

  event_data = api.perform_query("events.php?action=getEvent&sectionid=#{section_id}&eventid=#{event_id}")
  return self.new_event_from_data(event_data)
end
get_for_section(api, section, options={}) click to toggle source

Get events for a section @param [Osm::Api] api The api to use to make the request @param [Osm::Section, Fixnum, to_i] section The section (or its ID) to get the events for @!macro options_get @option options [Boolean] :include_archived (optional) if true then archived events will also be returned @return [Array<Osm::Event>]

# File lib/osm/event.rb, line 109
def self.get_for_section(api, section, options={})
  require_ability_to(api, :read, :events, section, options)
  section_id = section.to_i
  cache_key = ['events', section_id]
  events = nil

  if !options[:no_cache] && cache_exist?(api, cache_key)
    ids = cache_read(api, cache_key)
    events = get_from_ids(api, ids, 'event', section, options, :get_for_section)
  end

  if events.nil?
    data = api.perform_query("events.php?action=getEvents&sectionid=#{section_id}&showArchived=true")
    events = Array.new
    ids = Array.new
    unless data['items'].nil?
      data['items'].map { |i| i['eventid'].to_i }.each do |event_id|
        event_data = api.perform_query("events.php?action=getEvent&sectionid=#{section_id}&eventid=#{event_id}")
        files_data = api.perform_query("ext/uploads/events/?action=listAttachments&sectionid=#{section_id}&eventid=#{event_id}")
        files = files_data.is_a?(Hash) ? files_data['files'] : files_data
        files = [] unless files.is_a?(Array)

        event = self.new_event_from_data(event_data)
        event.files = files
        events.push event
        ids.push event.id
        cache_write(api, ['event', event.id], event)
      end
    end
    cache_write(api, cache_key, ids)
  end

  return events if options[:include_archived]
  return events.reject do |event|
    event.archived?
  end
end
get_list(api, section, options={}) click to toggle source

Get event list for a section (not all details for each event) @param [Osm::Api] api The api to use to make the request @param [Osm::Section, Fixnum, to_i] section The section (or its ID) to get the events for @!macro options_get @return [Array<Hash>]

# File lib/osm/event.rb, line 152
def self.get_list(api, section, options={})
  require_ability_to(api, :read, :events, section, options)
  section_id = section.to_i
  cache_key = ['events_list', section_id]
  events_cache_key = ['events', section_id]
  events = nil

  unless options[:no_cache]

    # Try getting from cache
    if cache_exist?(api, cache_key)
      return cache_read(api, cache_key)
    end
  
    # Try generating from cached events
    if cache_exist?(api, events_cache_key)
      ids = cache_read(api, events_cache_key)
      events = get_from_ids(api, ids, 'event', section, options, :get_for_section).map do |e|
        e.attributes.symbolize_keys.select do |k,v|
          LIST_ATTRIBUTES.include?(k)
        end
      end
    end

  end

  # Fetch from OSM
  if events.nil?
    data = api.perform_query("events.php?action=getEvents&sectionid=#{section_id}&showArchived=true")
    events = Array.new
    unless data['items'].nil?
      data['items'].map do |event_data|
        events.push(attributes_from_data(event_data))
      end
    end
  end

  cache_write(api, cache_key, events)
  return events
end

Private Class Methods

attributes_from_data(event_data) click to toggle source
# File lib/osm/event.rb, line 524
def self.attributes_from_data(event_data)
  {
    :id => Osm::to_i_or_nil(event_data['eventid']),
    :section_id => Osm::to_i_or_nil(event_data['sectionid']),
    :name => event_data['name'],
    :start => Osm::make_datetime(event_data['startdate'], event_data['starttime']),
    :finish => Osm::make_datetime(event_data['enddate'], event_data['endtime']),
    :cost => event_data['cost'].eql?('-1') ? 'TBC' : event_data['cost'],
    :location => event_data['location'],
    :notes => event_data['notes'],
    :archived => event_data['archived'].eql?('1'),
    :public_notepad => event_data['publicnotes'],
    :confirm_by_date => Osm::parse_date(event_data['confdate']),
    :allow_changes => event_data['allowchanges'].eql?('1'),
    :reminders => !event_data['disablereminders'].eql?('1'),
    :attendance_limit => event_data['attendancelimit'].to_i,
    :attendance_limit_includes_leaders => event_data['limitincludesleaders'].eql?('1'),
    :attendance_reminder => event_data['attendancereminder'].to_i,
    :allow_booking => event_data['allowbooking'].eql?('1'),
  }
end
new_event_from_data(event_data) click to toggle source
# File lib/osm/event.rb, line 546
def self.new_event_from_data(event_data)
  event = Osm::Event.new(attributes_from_data(event_data))
  event.notepad = event_data['notepad']

  columns = []
  config_raw = event_data['config']
  config_raw = '[]' if config_raw.blank?
  column_data = ActiveSupport::JSON.decode(config_raw)
  column_data = [] unless column_data.is_a?(Array)
  column_data.each do |field|
    columns.push Column.new(:id => field['id'], :name => field['name'], :label => field['pL'], :parent_required => field['pR'].to_s.eql?('1'), :event => event)
  end
  event.columns = columns

  badges = []
  badges_data = event_data['badgelinks']
  badges_data = [] unless badges_data.is_a?(Array)
  badges_data.each do |field|
    badges.push BadgeLink.new(
      badge_type: field['badgetype'].to_sym,
      badge_section: field['section'].to_sym,
      requirement_id: field['column_id'],
      badge_name: field['badgeLongName'],
      requirement_label: field['columnnameLongName'],
      data: field['data'],
      badge_id: field['badge_id'],
      badge_version: field['badge_version'],
    )
  end
  event.badges = badges

  return event
end

Public Instance Methods

add_column(api, name, label='', required=false) click to toggle source

Add a column to the event in OSM @param [Osm::Api] api The api to use to make the request @param [String] label The label for the field in OSM @param [String] name The label for the field in My.SCOUT (if this is blank then parents can't edit it) @param [Boolean] required Whether the parent is required to enter something @return [Boolean] whether the update succedded @raise [Osm::ArgumentIsInvalid] If the name is blank

# File lib/osm/event.rb, line 460
def add_column(api, name, label='', required=false)
  require_ability_to(api, :write, :events, section_id)
  raise Osm::ArgumentIsInvalid, 'name is invalid' if name.blank?

  data = api.perform_query("events.php?action=addColumn&sectionid=#{section_id}&eventid=#{id}", {
    'columnName' => name,
    'parentLabel' => label,
    'parentRequire' => (required ? 1 : 0),
  })

  # The cached events for the section will be out of date - remove them
  cache_delete(api, ['events', section_id])
  cache_delete(api, ['event', id])
  cache_delete(api, ['event_attendance', id])

  self.columns = self.class.new_event_from_data(data).columns

  return data.is_a?(Hash) && (data['eventid'].to_i == id)
end
cost_free?() click to toggle source

Whether the cost is zero @return [Boolean] whether the cost is zero

# File lib/osm/event.rb, line 510
def cost_free?
  cost.eql?('0.00')
end
cost_tbc?() click to toggle source

Whether the cost is to be confirmed @return [Boolean] whether the cost is TBC

# File lib/osm/event.rb, line 504
def cost_tbc?
  cost.eql?('TBC')
end
delete(api) click to toggle source

Delete event from OSM @param [Osm::Api] api The api to use to make the request @return [Boolean] whether the delete succedded

# File lib/osm/event.rb, line 366
def delete(api)
  require_ability_to(api, :write, :events, section_id)

  data = api.perform_query("events.php?action=deleteEvent&sectionid=#{section_id}&eventid=#{id}")

  if data.is_a?(Hash) && data['ok']
    cache_delete(api, ['event', id])
    return true
  end
  return false
end
get_attendance(api, term=nil, options={}) click to toggle source

Get event attendance @param [Osm::Api] api The api to use to make the request @param [Osm::Term, Fixnum, to_i, nil] term The term (or its ID) to get the members for, passing nil causes the current term to be used @!macro options_get @option options [Boolean] :include_archived (optional) if true then archived activities will also be returned @return [Array<Osm::Event::Attendance>]

# File lib/osm/event.rb, line 385
def get_attendance(api, term=nil, options={})
  require_ability_to(api, :read, :events, section_id, options)
  term_id = term.nil? ? Osm::Term.get_current_term_for_section(api, section_id).id : term.to_i
  cache_key = ['event_attendance', id, term_id]

  if !options[:no_cache] && cache_exist?(api, cache_key)
    return cache_read(api, cache_key)
  end

  data = api.perform_query("events.php?action=getEventAttendance&eventid=#{id}&sectionid=#{section_id}&termid=#{term_id}")
  data = data['items'] || []

  payment_values = {
    'Manual' => :manual,
    'Automatic' => :automatic,
  }
  attending_values = {
    'Yes' => :yes,
    'No' => :no,
    'Invited' => :invited,
    'Show in My.SCOUT' => :shown,
    'Reserved' => :reserved,
  }

  attendance = []
  data.each_with_index do |item, index|
    attendance.push Osm::Event::Attendance.new(
      :event => self,
      :member_id => Osm::to_i_or_nil(item['scoutid']),
      :grouping_id => Osm::to_i_or_nil(item['patrolid'].eql?('') ? nil : item['patrolid']),
      :first_name => item['firstname'],
      :last_name => item['lastname'],
      :date_of_birth => item['dob'].nil? ? nil : Osm::parse_date(item['dob'], :ignore_epoch => true),
      :attending => attending_values[item['attending']],
      :payment_control => payment_values[item['payment']],
      :fields => item.select { |key, value| key.to_s.match(/\Af_\d+\Z/) }
                     .inject({}){ |h,(k,v)| h[k[2..-1].to_i] = v; h },
      :payments => item.select { |key, value| key.to_s.match(/\Ap\d+\Z/) }
                       .inject({}){ |h,(k,v)| h[k[1..-1].to_i] = v; h },
      :row => index,
    )
  end

  cache_write(api, cache_key, attendance)
  return attendance
end
limited_attendance?() click to toggle source

Whether thete is a limit on attendance for this event @return [Boolean] whether thete is a limit on attendance for this event

# File lib/osm/event.rb, line 482
def limited_attendance?
  (attendance_limit != 0)
end
spaces(api) click to toggle source

Get the number of spaces left for the event @param [Osm::Api] api The api to use to make the request @return [Fixnum, nil] the number of spaces left (nil if there is no attendance limit)

# File lib/osm/event.rb, line 497
def spaces(api)
  return nil unless limited_attendance?
  return attendance_limit - attendees(api)
end
spaces?(api) click to toggle source

Whether there are spaces left for the event @param [Osm::Api] api The api to use to make the request @return [Boolean] whether there are spaces left for the event

# File lib/osm/event.rb, line 489
def spaces?(api)
  return true unless limited_attendance?
  return attendance_limit > attendees(api)
end
update(api) click to toggle source

Update event in OSM @param [Osm::Api] api The api to use to make the request @return [Boolean] whether the update succedded (will return true if no updates needed to be made)

# File lib/osm/event.rb, line 269
def update(api)
  require_ability_to(api, :write, :events, section_id)
   updated = true

  # Update main attributes
  update_main_attributes = false
  %w{ id name location start finish cost cost_tbc notes confirm_by_date allow_changes reminders attendance_limit attendance_limit_includes_leaders allow_booking }.each do |a|
    if changed_attributes.include?(a)
      update_main_attributes = true
      break # no use checking the others
    end
  end
  if update_main_attributes
    data = api.perform_query("events.php?action=addEvent&sectionid=#{section_id}", {
      'eventid' => id,
      'name' => name,
      'location' => location,
      'startdate' => start? ? start.strftime(Osm::OSM_DATE_FORMAT) : '',
      'enddate' => finish? ? finish.strftime(Osm::OSM_DATE_FORMAT) : '',
      'cost' => cost_tbc? ? '-1' : cost,
      'notes' => notes,
      'starttime' => start? ? start.strftime(Osm::OSM_TIME_FORMAT) : '',
      'endtime' => finish? ? finish.strftime(Osm::OSM_TIME_FORMAT) : '',
      'confdate' => confirm_by_date? ? confirm_by_date.strftime(Osm::OSM_DATE_FORMAT) : '',
      'allowChanges' => allow_changes ? 'true' : 'false',
      'disablereminders' => !reminders ? 'true' : 'false',
      'attendancelimit' => attendance_limit,
      'attendancereminder' => attendance_reminder,
      'limitincludesleaders' => attendance_limit_includes_leaders ? 'true' : 'false',
      'allowbooking' => allow_booking ? 'true' : 'false',
    })
    updated &= data.is_a?(Hash) && (data['id'].to_i == id)
  end

  # Private notepad
  if changed_attributes.include?('notepad')
    data = api.perform_query("events.php?action=saveNotepad&sectionid=#{section_id}", {
      'eventid' => id,
      'notepad' => notepad,
    })
    updated &= data.is_a?(Hash)
  end

  # MySCOUT notepad
  if changed_attributes.include?('public_notepad')
    data = api.perform_query("events.php?action=saveNotepad&sectionid=#{section_id}", {
      'eventid' => id,
      'pnnotepad' => public_notepad,
    })
    updated &= data.is_a?(Hash)
  end

  # Badges
  if changed_attributes.include?('badges')
    original_badges = @original_attributes['badges'] || []

    # Deleted badges
    badges_to_delete = []
    original_badges.each do |badge|
      unless badges.include?(badge)
        badges_to_delete.push badge
      end
    end
    badges_to_delete.each do |badge|
      data = api.perform_query("ext/badges/records/index.php?action=deleteBadgeLink&sectionid=#{section_id}", {
        'section' => badge.badge_section,
        'sectionid' => section_id,
        'type' => 'event',
        'id' => id,
        'badge_id' => badge.badge_id,
        'badge_version' => badge.badge_version,
        'column_id' => badge.requirement_id,
      })
      updated &= data.is_a?(Hash) && data['status']
    end

    # Added badges
    badges.each do |badge|
      unless original_badges.include?(badge)
        updated &= add_badge_link(api, badge)
      end
    end
  end # includes badges

  if updated
    reset_changed_attributes
    # The cached event will be out of date - remove it
    cache_delete(api, ['event', id])
    return true
  else
    return false
  end
end

Private Instance Methods

attendees(api) click to toggle source
# File lib/osm/event.rb, line 516
def attendees(api)
  attendees = 0
  get_attendance(api).each do |a|
    attendees += 1 unless attendance_limit_includes_leaders && (a.grouping_id == -2)
  end
  return attendees
end