class Osm::Member
Constants
- CID_ADDRESS_1
- CID_ADDRESS_2
- CID_ADDRESS_3
- CID_ADDRESS_4
- CID_EMAIL_1
- CID_EMAIL_2
- CID_FIRST_NAME
Constants for column id
- CID_GENDER
- CID_LAST_NAME
- CID_PHONE_1
- CID_PHONE_2
- CID_POSTCODE
- CID_RECIEVE_EMAIL_1
- CID_RECIEVE_EMAIL_2
- CID_RECIEVE_PHONE_1
- CID_RECIEVE_PHONE_2
- CID_SURGERY
- CORE_FIELD_IDS
- GID_CUSTOM
- GID_DOCTOR_CONTACT
- GID_EMERGENCY_CONTACT
- GID_FLOATING
- GID_MEMBER_CONTACT
- GID_PRIMARY_CONTACT
Constants for group id
- GID_SECONDARY_CONTACT
Public Class Methods
Get members 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 members for @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 @return [Array<Osm::Member>]
# File lib/osm/member.rb, line 139 def self.get_for_section(api, section, term=nil, options={}) require_ability_to(api, :read, :member, section, options) if term.nil? section = Osm::Section.get(api, section) if section.is_a?(Fixnum) term = section.waiting? ? -1 : Osm::Term.get_current_term_for_section(api, section) end cache_key = ['members', section.to_i, term.to_i] if !options[:no_cache] && cache_exist?(api, cache_key) return cache_read(api, cache_key) end result = Array.new api_response = api.perform_query('ext/members/contact/grid/?action=getMembers', { 'section_id' => section.to_i, 'term_id' => term.to_i, }) data = api_response['data'].is_a?(Hash) ? api_response['data'].values : [] structure = (api_response['meta'] || {})['structure'] || [] structure = Hash[ structure.map{ |i| [i['group_id'].to_i, i ] } ] # Make a hash of identifier to group data hash custom_labels = {} key_key = 'column_id' # the key in the data from OSM to use as the key in additional_information and labels hashes structure.each do |gid, group| columns = group['columns'] || [] custom_labels[gid.to_i] = Hash[ columns.map.select{ |a| gid.eql?(GID_CUSTOM) || !CORE_FIELD_IDS.include?(a['column_id'].to_i) }.map{ |c| [c[key_key], c['label']] } ] end data.each do |item| item_data = Hash[ item['custom_data'].map{ |k,v| [k.to_i, v] } ] member_contact = item_data[GID_MEMBER_CONTACT].nil? ? nil : Hash[ item_data[GID_MEMBER_CONTACT].map{ |k,v| [k.to_i, v] }.select{ |k,v| CORE_FIELD_IDS.include?(k) } ] member_custom = item_data[GID_MEMBER_CONTACT].nil? ? DirtyHashy.new : DirtyHashy[ item_data[GID_MEMBER_CONTACT].select{ |k,v| !CORE_FIELD_IDS.include?(k.to_i) }.map{ |k,v| [k.to_i, v] } ] primary_contact = item_data[GID_PRIMARY_CONTACT].nil? ? nil : Hash[ item_data[GID_PRIMARY_CONTACT].map{ |k,v| [k.to_i, v] }.select{ |k,v| CORE_FIELD_IDS.include?(k) } ] primary_custom = item_data[GID_PRIMARY_CONTACT].nil? ? DirtyHashy.new : DirtyHashy[ item_data[GID_PRIMARY_CONTACT].select{ |k,v| !CORE_FIELD_IDS.include?(k.to_i) }.map{ |k,v| [k.to_i, v] } ] secondary_contact = item_data[GID_SECONDARY_CONTACT].nil? ? nil : Hash[ item_data[GID_SECONDARY_CONTACT].map{ |k,v| [k.to_i, v] }.select{ |k,v| CORE_FIELD_IDS.include?(k) } ] secondary_custom = item_data[GID_SECONDARY_CONTACT].nil? ? DirtyHashy.new : DirtyHashy[ item_data[GID_SECONDARY_CONTACT].select{ |k,v| !CORE_FIELD_IDS.include?(k.to_i) }.map{ |k,v| [k.to_i, v] } ] emergency_contact = item_data[GID_EMERGENCY_CONTACT].nil? ? nil : Hash[ item_data[GID_EMERGENCY_CONTACT].map{ |k,v| [k.to_i, v] }.select{ |k,v| CORE_FIELD_IDS.include?(k) } ] emergency_custom = item_data[GID_EMERGENCY_CONTACT].nil? ? DirtyHashy.new : DirtyHashy[ item_data[GID_EMERGENCY_CONTACT].select{ |k,v| !CORE_FIELD_IDS.include?(k.to_i) }.map{ |k,v| [k.to_i, v] } ] doctor_contact = item_data[GID_DOCTOR_CONTACT].nil? ? nil : Hash[ item_data[GID_DOCTOR_CONTACT].map{ |k,v| [k.to_i, v] }.select{ |k,v| CORE_FIELD_IDS.include?(k) } ] doctor_custom = item_data[GID_DOCTOR_CONTACT].nil? ? DirtyHashy.new : DirtyHashy[ item_data[GID_DOCTOR_CONTACT].select{ |k,v| !CORE_FIELD_IDS.include?(k.to_i) }.map{ |k,v| [k.to_i, v] } ] floating_data = item_data[GID_FLOATING].nil? ? {} : Hash[ item_data[GID_FLOATING].map{ |k,v| [k.to_i, v] }.select{ |k,v| CORE_FIELD_IDS.include?(k) } ] custom_data = item_data[GID_CUSTOM].nil? ? DirtyHashy.new : DirtyHashy[ item_data[GID_CUSTOM].map{ |k,v| [k.to_i, v] } ] result.push Osm::Member.new( :id => Osm::to_i_or_nil(item['member_id']), :section_id => Osm::to_i_or_nil(item['section_id']), :first_name => item['first_name'], :last_name => item['last_name'], :grouping_id => Osm::to_i_or_nil(item['patrol_id']), :grouping_label => item['patrol'], :grouping_leader => item['patrol_role_level'], :grouping_leader_label => item['patrol_role_level_label'], :age => item['age'], :date_of_birth => Osm::parse_date(item['date_of_birth'], :ignore_epoch => true), :started_section => Osm::parse_date(item['joined']), :finished_section => Osm::parse_date(item['end_date']), :joined_movement => Osm::parse_date(item['started']), :gender => {'male'=>:male, 'female'=>:female, 'other'=>:other, 'unspecified'=>:unspecified}[(floating_data[CID_GENDER] || '').downcase], :contact => member_contact.nil? ? nil : MemberContact.new( first_name: item['first_name'], last_name: item['last_name'], address_1: member_contact[CID_ADDRESS_1], address_2: member_contact[CID_ADDRESS_2], address_3: member_contact[CID_ADDRESS_3], address_4: member_contact[CID_ADDRESS_4], postcode: member_contact[CID_POSTCODE], phone_1: member_contact[CID_PHONE_1], phone_2: member_contact[CID_PHONE_2], email_1: member_contact[CID_EMAIL_1], email_2: member_contact[CID_EMAIL_2], receive_phone_1: member_contact[CID_RECIEVE_PHONE_1].eql?('yes'), receive_phone_2: member_contact[CID_RECIEVE_PHONE_2].eql?('yes'), receive_email_1: member_contact[CID_RECIEVE_EMAIL_1].eql?('yes'), receive_email_2: member_contact[CID_RECIEVE_EMAIL_2].eql?('yes'), additional_information: member_custom, additional_information_labels: custom_labels[GID_MEMBER_CONTACT], ), :primary_contact => primary_contact.nil? ? nil : PrimaryContact.new( first_name: primary_contact[CID_FIRST_NAME], last_name: primary_contact[CID_LAST_NAME], address_1: primary_contact[CID_ADDRESS_1], address_2: primary_contact[CID_ADDRESS_2], address_3: primary_contact[CID_ADDRESS_3], address_4: primary_contact[CID_ADDRESS_4], postcode: primary_contact[CID_POSTCODE], phone_1: primary_contact[CID_PHONE_1], phone_2: primary_contact[CID_PHONE_2], email_1: primary_contact[CID_EMAIL_1], email_2: primary_contact[CID_EMAIL_2], receive_phone_1: primary_contact[CID_RECIEVE_PHONE_1].eql?('yes'), receive_phone_2: primary_contact[CID_RECIEVE_PHONE_2].eql?('yes'), receive_email_1: primary_contact[CID_RECIEVE_EMAIL_1].eql?('yes'), receive_email_2: primary_contact[CID_RECIEVE_EMAIL_2].eql?('yes'), additional_information: primary_custom, additional_information_labels: custom_labels[GID_PRIMARY_CONTACT], ), :secondary_contact => secondary_contact.nil? ? nil : SecondaryContact.new( first_name: secondary_contact[CID_FIRST_NAME], last_name: secondary_contact[CID_LAST_NAME], address_1: secondary_contact[CID_ADDRESS_1], address_2: secondary_contact[CID_ADDRESS_2], address_3: secondary_contact[CID_ADDRESS_3], address_4: secondary_contact[CID_ADDRESS_4], postcode: secondary_contact[CID_POSTCODE], phone_1: secondary_contact[CID_PHONE_1], phone_2: secondary_contact[CID_PHONE_2], email_1: secondary_contact[CID_EMAIL_1], email_2: secondary_contact[CID_EMAIL_2], receive_phone_1: secondary_contact[CID_RECIEVE_PHONE_1].eql?('yes'), receive_phone_2: secondary_contact[CID_RECIEVE_PHONE_2].eql?('yes'), receive_email_1: secondary_contact[CID_RECIEVE_EMAIL_1].eql?('yes'), receive_email_2: secondary_contact[CID_RECIEVE_EMAIL_2].eql?('yes'), additional_information: secondary_custom, additional_information_labels: custom_labels[GID_SECONDARY_CONTACT], ), :emergency_contact => emergency_contact.nil? ? nil : EmergencyContact.new( first_name: emergency_contact[CID_FIRST_NAME], last_name: emergency_contact[CID_LAST_NAME], address_1: emergency_contact[CID_ADDRESS_1], address_2: emergency_contact[CID_ADDRESS_2], address_3: emergency_contact[CID_ADDRESS_3], address_4: emergency_contact[CID_ADDRESS_4], postcode: emergency_contact[CID_POSTCODE], phone_1: emergency_contact[CID_PHONE_1], phone_2: emergency_contact[CID_PHONE_2], email_1: emergency_contact[CID_EMAIL_1], email_2: emergency_contact[CID_EMAIL_2], additional_information: emergency_custom, additional_information_labels: custom_labels[GID_EMERGENCY_CONTACT], ), :doctor => doctor_contact.nil? ? nil : DoctorContact.new( first_name: doctor_contact[CID_FIRST_NAME], last_name: doctor_contact[CID_LAST_NAME], surgery: doctor_contact[CID_SURGERY], address_1: doctor_contact[CID_ADDRESS_1], address_2: doctor_contact[CID_ADDRESS_2], address_3: doctor_contact[CID_ADDRESS_3], address_4: doctor_contact[CID_ADDRESS_4], postcode: doctor_contact[CID_POSTCODE], phone_1: doctor_contact[CID_PHONE_1], phone_2: doctor_contact[CID_PHONE_2], additional_information: doctor_custom, additional_information_labels: custom_labels[GID_DOCTOR_CONTACT], ), additional_information: custom_data, additional_information_labels: custom_labels[GID_CUSTOM], ) end cache_write(api, cache_key, result) return result end
Public Instance Methods
Compare member based on section_id, grouping_id, grouping_leader (descending), last_name then first_name
# File lib/osm/member.rb, line 559 def <=>(another) result = self.section_id <=> another.try(:section_id) result = self.grouping_id <=> another.try(:grouping_id) if result == 0 result = -(self.grouping_leader <=> another.try(:grouping_leader)) if result == 0 result = self.last_name <=> another.try(:last_name) if result == 0 result = self.first_name <=> another.try(:first_name) if result == 0 return result end
Get the months element of this scout's age @return [Fixnum] the number of months since this scout's last birthday
# File lib/osm/member.rb, line 419 def age_months return age[-2..-1].to_i end
Get the years element of this scout's age @return [Fixnum] the number of years this scout has been alive
# File lib/osm/member.rb, line 413 def age_years return age[0..1].to_i end
Create the user in OSM @param [Osm::Api] api The api to use to make the request @return [Boolan, nil] whether the member was successfully added or not (nil is returned if the user was created but not with all the data) @raise [Osm::ObjectIsInvalid] If the Member
is invalid @raise [Osm::Error] If the member already exists in OSM
# File lib/osm/member.rb, line 305 def create(api) raise Osm::Error, 'the member already exists in OSM' unless id.nil? raise Osm::ObjectIsInvalid, 'member is invalid' unless valid? require_ability_to(api, :write, :member, section_id) data = api.perform_query("users.php?action=newMember", { 'firstname' => first_name, 'lastname' => last_name, 'dob' => date_of_birth.strftime(Osm::OSM_DATE_FORMAT), 'started' => joined_movement.strftime(Osm::OSM_DATE_FORMAT), 'startedsection' => started_section.strftime(Osm::OSM_DATE_FORMAT), 'sectionid' => section_id, }) if (data.is_a?(Hash) && (data['result'] == 'ok') && (data['scoutid'].to_i > 0)) self.id = data['scoutid'].to_i # The cached members for the section will be out of date - remove them Osm::Term.get_for_section(api, section_id).each do |term| cache_delete(api, ['members', section_id, term.id]) end # Now it's created we need to give OSM the rest of the data updated = update(api, true) return updated ? true : nil else return false end end
Check if this is a current member of the section they were retrieved for @param date [Date] The date to check membership status for @return true, false
# File lib/osm/member.rb, line 457 def current?(date=Date.today) return nil if started_section.nil? and finished_section.nil? if finished_section.nil? started_section <= date elsif started_section.nil? finished_section >= date else (started_section <= date) && (finished_section >= date) end end
Check if the member is male @return [Boolean]
# File lib/osm/member.rb, line 450 def female? gender == :female end
Get the member's photo @param [Osm::Api] api The api to use to make the request @param [Boolean] black_and_white Whether you want the photo in blank and white (defaults to false unless the member is not active) @!macro options_get @raise [Osm:Error] if the member doesn't exist in OSM @return the photo of the member
# File lib/osm/member.rb, line 521 def get_photo(api, black_and_white=!current?, options={}) raise Osm::ObjectIsInvalid, 'member is invalid' unless valid? require_ability_to(api, :read, :member, section_id) raise Osm::Error, 'the member does not already exist in OSM' if id.nil? cache_key = ['member_photo', self.id, black_and_white] if !options[:no_cache] && cache_exist?(api, cache_key) return cache_read(api, cache_key) end url = "ext/members/contact/images/member.php?sectionid=#{section_id}&scoutid=#{self.id}&bw=#{black_and_white}" image = api.perform_query(url) cache_write(api, cache_key, image) unless image.nil? return image end
Check if the member is in the leaders grouping @return [Boolean]
# File lib/osm/member.rb, line 432 def leader? grouping_id.eql?(-2) end
Check if the member is male @return [Boolean]
# File lib/osm/member.rb, line 444 def male? gender == :male end
Get the My.SCOUT link for this member @param [Osm::Api] api The api to use to make the request @param [Symbol] link_to The page in My.SCOUT to link to (:payments, :events, :programme, :badges, :notice, :details, :census or :giftaid) @param [#to_i] item_id Allows you to link to a specfic item (only for :events) @return [String] the URL for this member's My.SCOUT @raise [Osm::ObjectIsInvalid] If the Member
is invalid @raise [Osm::ArgumentIsInvalid] If link_to is not an allowed Symbol @raise [Osm::Error] if the member does not already exist in OSM or the member's My.SCOUT key could not be retrieved from OSM
# File lib/osm/member.rb, line 547 def myscout_link(api, link_to=:badges, item_id=nil) raise Osm::ObjectIsInvalid, 'member is invalid' unless valid? require_ability_to(api, :read, :member, section_id) raise Osm::Error, 'the member does not already exist in OSM' if id.nil? raise Osm::ArgumentIsInvalid, 'link_to is invalid' unless [:payments, :events, :programme, :badges, :notice, :details, :census, :giftaid].include?(link_to) link = "#{api.base_url}/parents/#{link_to}.php?sc=#{self.id}&se=#{section_id}&c=#{myscout_link_key(api)}" link += "&e=#{item_id.to_i}" if item_id && link_to.eql?(:events) return link end
Get the Key to use in My.SCOUT links for this member @param [Osm::Api] api The api to use to make the request @return [String] the key @raise [Osm::ObjectIsInvalid] If the Member
is invalid @raise [Osm::Error] if the member does not already exist in OSM or the member's My.SCOUT key could not be retrieved from OSM
# File lib/osm/member.rb, line 501 def myscout_link_key(api) raise Osm::ObjectIsInvalid, 'member is invalid' unless valid? require_ability_to(api, :read, :member, section_id) raise Osm::Error, 'the member does not already exist in OSM' if id.nil? if @myscout_link_key.nil? data = api.perform_query("api.php?action=getMyScoutKey§ionid=#{section_id}&scoutid=#{self.id}") raise Osm::Error, 'Could not retrieve the key for the link from OSM' unless data['ok'] @myscout_link_key = data['key'] end return @myscout_link_key end
Get the full name @param [String] seperator What to split the member's first name and last name with @return [String] this scout's full name seperated by the optional seperator
# File lib/osm/member.rb, line 426 def name(seperator=' ') return [first_name, last_name].select{ |i| !i.blank? }.join(seperator) end
Update the member in OSM @param [Osm::Api] api The api to use to make the request @param [Boolean] force Whether to force updates (ie tell OSM every attribute changed even if we don't think it did) @return [Boolean] whether the member was successfully updated or not @raise [Osm::ObjectIsInvalid] If the Member
is invalid
# File lib/osm/member.rb, line 338 def update(api, force=false) raise Osm::ObjectIsInvalid, 'member is invalid' unless valid? require_ability_to(api, :write, :member, section_id) updated = true # Do core attributes attribute_map = [ ['first_name', 'firstname', first_name], ['last_name', 'lastname', last_name], ['grouping_id', 'patrolid', grouping_id], ['grouping_leader', 'patrolleader', grouping_leader], ['date_of_birth', 'dob', date_of_birth.strftime(Osm::OSM_DATE_FORMAT)], ['started_section', 'startedsection', started_section.strftime(Osm::OSM_DATE_FORMAT)], ['joined_movement', 'started', joined_movement.strftime(Osm::OSM_DATE_FORMAT)], ] # our name => OSM name attribute_map.select{ |attr,col,val| force || changed_attributes.include?(attr) }.each do |attr,col,val| data = api.perform_query("ext/members/contact/?action=update", { 'scoutid' => self.id, 'column' => col, 'value' => val, 'sectionid' => section_id, }) updated = updated && data.is_a?(Hash) && data['ok'].eql?(true) end # each attr to update # Do 'floating' attributes if force || changed_attributes.include?('gender') new_value = {male: 'Male', female: 'Female', other: 'Other'}[gender] || 'Unspecified' data = api.perform_query("ext/customdata/?action=updateColumn§ion_id=#{section_id}", { 'associated_id' => self.id, 'associated_type' => 'member', 'value' => new_value, 'column_id' => CID_GENDER, 'group_id' => GID_FLOATING, 'context' => 'members', }) updated = updated && data.is_a?(Hash) && data['data'].is_a?(Hash) && data['data']['value'].eql?(new_value) end # Do custom attributes additional_information.keys.select{ |a| force || additional_information.changes.keys.include?(a) }.each do |attr| new_value = additional_information[attr] data = api.perform_query("ext/customdata/?action=updateColumn§ion_id=#{section_id}", { 'associated_id' => self.id, 'associated_type' => 'member', 'value' => new_value, 'column_id' => attr, 'group_id' => GID_CUSTOM, 'context' => 'members', }) updated = updated && data.is_a?(Hash) && data['data'].is_a?(Hash) && data['data']['value'].to_s.eql?(new_value.to_s) end # each attr to update # Do contacts updated = (contact.nil? || contact.update(api, self, force)) && updated updated = (primary_contact.nil? || primary_contact.update(api, self, force)) && updated updated = (secondary_contact.nil? || secondary_contact.update(api, self, force)) && updated updated = (emergency_contact.nil? ||emergency_contact.update(api, self, force)) && updated updated = (doctor.nil? || doctor.update(api, self, force)) && updated # Finish off if updated reset_changed_attributes additional_information.clean_up! # The cached columns for the members will be out of date - remove them Osm::Term.get_for_section(api, section_id).each do |term| Osm::Model.cache_delete(api, ['members', section_id, term.id]) end end return updated end
Check if the member is in a non-leaders grouping @return [Boolean]
# File lib/osm/member.rb, line 438 def youth? grouping_id > 0 end