lib/osm/member.rb in osm-1.2.17 vs lib/osm/member.rb in osm-1.2.18.dev
- old
+ new
@@ -1,222 +1,284 @@
module Osm
class Member < Osm::Model
+ # Constants for group id
+ GID_PRIMARY_CONTACT = 1
+ GID_SECONDARY_CONTACT = 2
+ GID_EMERGENCY_CONTACT = 3
+ GID_DOCTOR_CONTACT = 4
+ GID_CUSTOM = 5
+ GID_MEMBER_CONTACT = 6
+ GID_FLOATING = 7
+ # Constants for column id
+ CUSTOM_FIELD_IDS_START_AT = 55
+ CORE_FIELD_IDS_FINISH_AT = CUSTOM_FIELD_IDS_START_AT - 1
+ CORE_FIELD_IDS = (1..54).to_a
+ CID_FIRST_NAME = 2
+ CID_LAST_NAME = 3
+ CID_ADDRESS_1 = 7
+ CID_ADDRESS_2 = 8
+ CID_ADDRESS_3 = 9
+ CID_ADDRESS_4 = 10
+ CID_POSTCODE = 11
+ CID_EMAIL_1 = 12
+ CID_RECIEVE_EMAIL_1 = 13
+ CID_EMAIL_2 = 14
+ CID_RECIEVE_EMAIL_2 = 15
+ CID_PHONE_1 = 18
+ CID_RECIEVE_PHONE_1 = 19
+ CID_PHONE_2 = 20
+ CID_RECIEVE_PHONE_2 = 21
+ CID_GENDER = 34
+ CID_SURGERY = 54
+
# @!attribute [rw] id
# @return [Fixnum] the id for the member
# @!attribute [rw] section_id
# @return [Fixnum] the section the member belongs to
- # @!attribute [rw] type
- # @return [String] ?
# @!attribute [rw] first_name
# @return [String] the member's first name
# @!attribute [rw] last_name
# @return [String] the member's last name
- # @!attribute [rw] email1
- # @return [String] the 1st email address for the member
- # @!attribute [rw] email2
- # @return [String] the 2nd email address for the member
- # @!attribute [rw] email3
- # @return [String] the 3rd email address for the member
- # @!attribute [rw] email4
- # @return [String] the 4th email address for the member
- # @!attribute [rw] phone1
- # @return [String] the 1st phone number for the member
- # @!attribute [rw] phone2
- # @return [String] the 2nd phone number for the member
- # @!attribute [rw] phone3
- # @return [String] the 3rd phone number for the member
- # @!attribute [rw] phone4
- # @return [String] the 4th phone number for the member
- # @!attribute [rw] address
- # @return [String] the member's address
- # @!attribute [rw] address2
- # @return [String] the member's 2nd address
- # @!attribute [rw] date_of_birth
- # @return [Date] the member's date of birth
- # @!attribute [rw] started
- # @return [Date] when the member started Scouting
- # @!attribute [rw] joining_in_years
- # @return [Fixnum] ?
- # @!attribute [rw] parents
- # @return [String] the member's parent's names
- # @!attribute [rw] notes
- # @return [String] notes relating to the member
- # @!attribute [rw] medical
- # @return [String] the member's key medical details
- # @!attribute [rw] religion
- # @return [String] the member's religion
- # @!attribute [rw] school
- # @return [String] the school the member attends
- # @!attribute [rw] ethnicity
- # @return [String] the member's ethnicity
- # @!attribute [rw] subs
- # @return [String] details about the member's subs
- # @!attribute [rw] custom1
- # @return [String] the custom1 data for the member
- # @!attribute [rw] custom2
- # @return [String] the custom2 data for the member
- # @!attribute [rw] custom3
- # @return [String] the custom3 data for the member
- # @!attribute [rw] custom4
- # @return [String] the custom4 data for the member
- # @!attribute [rw] custom5
- # @return [String] the custom5 data for the member
- # @!attribute [rw] custom6
- # @return [String] the custom6 data for the member
- # @!attribute [rw] custom7
- # @return [String] the custom7 data for the member
- # @!attribute [rw] custom8
- # @return [String] the custom8 data for the member
- # @!attribute [rw] custom9
- # @return [String] the custom9 data for the member
# @!attribute [rw] grouping_id
- # @return [Fixnum] the grouping within the section that the member belongs to
+ # @return [Fixnum] the ID of the grouping within the section that the member belongs to
+ # @!attribute [rw] grouping_label
+ # @return [String] the name of the grouping within the section that the member belongs to
# @!attribute [rw] grouping_leader
- # @return [Fixnum] whether the member is the grouping leader (0=no, 1=seconder/APL, 2=sixer/PL)
- # @!attribute [rw] joined
- # @return [Date] when the member joined the section
+ # @return [Fixnum] whether the member is the grouping leader (0=no, 1=seconder/APL, 2=sixer/PL, 3=senior PL)
+ # @!attribute [rw] grouping_leader_label
+ # @return [String] whether the member is the grouping leader
# @!attribute [rw] age
- # @return [String] the member's current age (yy/mm)
- # @!attribute [rw] joined_years
- # @return [Fixnum] how many years the member has been in Scouting
- # @!attribute [rw] has_photo
- # @return [Boolean] whether the scout has a photo in OSM
+ # @return [String] the member's current age (yy/mm)
+ # @!attribute [rw] gender
+ # @return [Symbol] the member's gender (:male, :female, :other or :unspecified)
+ # @!attribute [rw] date_of_birth
+ # @return [Date] the member's date of birth
+ # @!attribute [rw] started_section
+ # @return [Date] when the member started the section they were retrieved for
+ # @!attribute [rw] finished_section
+ # @return [Date] when the member finished the section they were retrieved for
+ # @!attribute [rw] joined_movement
+ # @return [Date] when the member joined the movement
+ # @!attribute [rw] custom
+ # @return [DirtyHashy] the custom data (key is OSM's variable name, value is the data)
+ # @!attribute [rw] custom_labels
+ # @return [DirtyHashy] the labels for the custom data (key is OSM's variable name, value is the label)
+ # @!attribute [rw] contact
+ # @return [Osm::Member::MemberContact] the member's contact details
+ # @!attribute [rw] primary_contact
+ # @return [Osm::Member::PrimaryContact] the member's primary contact (primary contact 1 in OSM)
+ # @!attribute [rw] secondary_contact
+ # @return [Osm::Member::PrimaryContact] the member's secondary contact (primary contact 2 in OSM)
+ # @!attribute [rw] emergency_contact
+ # @return [Osm::Member::EmergencyContact] the member's emergency contact
+ # @!attribute [rw] doctor
+ # @return [Osm::Member::DoctorContact] the member's doctor
attribute :id, :type => Integer
attribute :section_id, :type => Integer
- attribute :type, :type => String
attribute :first_name, :type => String
attribute :last_name, :type => String
- attribute :email1, :type => String, :default => ''
- attribute :email2, :type => String, :default => ''
- attribute :email3, :type => String, :default => ''
- attribute :email4, :type => String, :default => ''
- attribute :phone1, :type => String, :default => ''
- attribute :phone2, :type => String, :default => ''
- attribute :phone3, :type => String, :default => ''
- attribute :phone4, :type => String, :default => ''
- attribute :address, :type => String, :default => ''
- attribute :address2, :type => String, :default => ''
- attribute :date_of_birth, :type => Date
- attribute :started, :type => Date
- attribute :joining_in_years, :type => Integer
- attribute :parents, :type => String, :default => ''
- attribute :notes, :type => String, :default => ''
- attribute :medical, :type => String, :default => ''
- attribute :religion, :type => String, :default => ''
- attribute :school, :type => String, :default => ''
- attribute :ethnicity, :type => String, :default => ''
- attribute :subs, :type => String, :default => ''
- attribute :custom1, :type => String, :default => ''
- attribute :custom2, :type => String, :default => ''
- attribute :custom3, :type => String, :default => ''
- attribute :custom4, :type => String, :default => ''
- attribute :custom5, :type => String, :default => ''
- attribute :custom6, :type => String, :default => ''
- attribute :custom7, :type => String, :default => ''
- attribute :custom8, :type => String, :default => ''
- attribute :custom9, :type => String, :default => ''
attribute :grouping_id, :type => Integer
+ attribute :grouping_label, :type => String
attribute :grouping_leader, :type => Integer
- attribute :joined, :type => Date
+ attribute :grouping_leader_label, :type => String
attribute :age, :type => String
- attribute :joined_years, :type => Integer
- attribute :has_photo, :type => Boolean, :default => false
+ attribute :date_of_birth, :type => Date
+ attribute :started_section, :type => Date
+ attribute :finished_section, :type => Date
+ attribute :joined_movement, :type => Date
+ attribute :gender, :type => Object
+ attribute :custom, :type => Object, :default => DirtyHashy.new
+ attribute :custom_labels, :type => Object, :default => DirtyHashy.new
+ attribute :contact, :type => Object
+ attribute :primary_contact, :type => Object
+ attribute :secondary_contact, :type => Object
+ attribute :emergency_contact, :type => Object
+ attribute :doctor, :type => Object
if ActiveModel::VERSION::MAJOR < 4
- attr_accessible :id, :section_id, :type, :first_name, :last_name, :email1, :email2, :email3, :email4,
- :phone1, :phone2, :phone3, :phone4, :address, :address2, :date_of_birth, :started,
- :joining_in_years, :parents, :notes, :medical, :religion, :school, :ethnicity, :subs,
- :custom1, :custom2, :custom3, :custom4, :custom5, :custom6, :custom7, :custom8, :custom9,
- :grouping_id, :grouping_leader, :joined, :age, :joined_years,
- :has_photo
+ attr_accessible :id, :section_id, :first_name, :last_name, :grouping_id, :grouping_leader,
+ :date_of_birth, :started_section, :finished_section, :joined_movement, :age,
+ :grouping_label, :grouping_leader_label, :gender, :custom, :custom_labels,
+ :contact, :primary_contact, :secondary_contact, :emergency_contact, :doctor
end
validates_numericality_of :id, :only_integer=>true, :greater_than=>0, :unless => Proc.new { |r| r.id.nil? }
validates_numericality_of :section_id, :only_integer=>true, :greater_than=>0
validates_numericality_of :grouping_id, :only_integer=>true, :greater_than_or_equal_to=>-2
- validates_numericality_of :grouping_leader, :only_integer=>true, :greater_than_or_equal_to=>0, :less_than_or_equal_to=>2
- validates_numericality_of :joined_years, :only_integer=>true, :greater_than_or_equal_to=>-1, :allow_nil=>true
- validates_numericality_of :joining_in_years, :only_integer=>true, :greater_than_or_equal_to=>-1, :allow_nil=>true
+ validates_numericality_of :grouping_leader, :only_integer=>true, :greater_than_or_equal_to=>0, :less_than_or_equal_to=>14, :allow_nil => true
validates_presence_of :first_name
validates_presence_of :last_name
+ validates_presence_of :grouping_label, :allow_blank => true
+ validates_presence_of :grouping_leader_label, :allow_blank => true
+ validates_presence_of :custom, :allow_blank => true
+ validates_presence_of :custom_labels, :allow_blank => true
validates_presence_of :date_of_birth
- validates_presence_of :started
- validates_presence_of :joined
- validates_format_of :age, :with => /\A[0-9]{2}\/(0[0-9]|1[012])\Z/, :message => 'age is not in the correct format (yy/mm)', :allow_blank => true
- validates_inclusion_of :has_photo, :in => [true, false]
+ validates_presence_of :started_section
+ validates_presence_of :finished_section, :allow_nil=>true
+ validates_presence_of :joined_movement
+ validates_format_of :age, :with => /\A[0-9]{1,3} \/ (?:0?[0-9]|1[012])\Z/, :message => 'age is not in the correct format (yy / mm)', :allow_blank => true
+ validates_inclusion_of :gender, :in => [:male, :female, :other, :unspecified], :allow_nil => true
+ validates :contact, :validity=>true
+ validates :primary_contact, :validity=>true
+ validates :secondary_contact, :validity=>true
+ validates :emergency_contact, :validity=>true
+ validates :doctor, :validity=>true
# 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>]
def self.get_for_section(api, section, term=nil, options={})
require_ability_to(api, :read, :member, section, options)
- section = Osm::Section.get(api, section) if section.is_a?(Fixnum)
- term = -1 if section.waiting?
- term_id = term.nil? ? Osm::Term.get_current_term_for_section(api, section).id : term.to_i
- cache_key = ['members', section.id, term_id]
+ 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
- data = api.perform_query("users.php?action=getUserDetails§ionid=#{section.id}&termid=#{term_id}")
- summary_data = api.perform_query("ext/members/contact/?action=getListOfMembers&sort=patrolid§ionid=#{section.id}&termid=#{term_id}§ion=#{section.type}") || {}
+ result = Array.new
- summary_data = summary_data['items'] || []
- summary_data = Hash[summary_data.map { |i| [i['scoutid'].to_i, i] }]
+ api_response = api.perform_query('ext/members/contact/grid/?action=getMembers', {
+ 'section_id' => section.to_i,
+ 'term_id' => term.to_i,
+ })
- result = Array.new
- data['items'].each do |item|
- id = Osm::to_i_or_nil(item['scoutid'])
+ 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 = {}
+ structure.each do |gid, group|
+ columns = group['columns']
+ columns.map!{ |c| [c['column_id'].to_i, c['label']] }
+ columns.select!{ |a| (gid == GID_CUSTOM) || (a[0] > CORE_FIELD_IDS_FINISH_AT) }
+ labels = DirtyHashy[ columns ]
+ custom_labels[gid.to_i] = labels
+ end
+
+ data.each do |item|
+ item_data = Hash[ item['custom_data'].map{ |k,v| [k.to_i, v] } ]
+ member_contact = Hash[ item_data[GID_MEMBER_CONTACT].map{ |k,v| [k.to_i, v] }.select{ |i| i[0] < CUSTOM_FIELD_IDS_START_AT } ]
+ primary_contact = Hash[ item_data[GID_PRIMARY_CONTACT].map{ |k,v| [k.to_i, v] }.select{ |i| i[0] < CUSTOM_FIELD_IDS_START_AT } ]
+ secondary_contact = Hash[ item_data[GID_SECONDARY_CONTACT].map{ |k,v| [k.to_i, v] }.select{ |i| i[0] < CUSTOM_FIELD_IDS_START_AT } ]
+ emergency_contact = Hash[ item_data[GID_EMERGENCY_CONTACT].map{ |k,v| [k.to_i, v] }.select{ |i| i[0] < CUSTOM_FIELD_IDS_START_AT } ]
+ doctor_contact = Hash[ item_data[GID_DOCTOR_CONTACT].map{ |k,v| [k.to_i, v] }.select{ |i| i[0] < CUSTOM_FIELD_IDS_START_AT } ]
+ floating_data = Hash[ item_data[GID_FLOATING].map{ |k,v| [k.to_i, v] }.select{ |i| i[0] < CUSTOM_FIELD_IDS_START_AT } ]
+
result.push Osm::Member.new(
- :section_id => section.id,
- :id => id,
- :type => item['type'],
- :first_name => item['firstname'],
- :last_name => item['lastname'],
- :email1 => item['email1'],
- :email2 => item['email2'],
- :email3 => item['email3'],
- :email4 => item['email4'],
- :phone1 => item['phone1'],
- :phone2 => item['phone2'],
- :phone3 => item['phone3'],
- :phone4 => item['phone4'],
- :address => item['address'],
- :address2 => item['address2'],
- :date_of_birth => Osm::parse_date(item['dob'], :ignore_epoch => true),
- :started => Osm::parse_date(item['started']),
- :joining_in_years => item['joining_in_yrs'].to_i,
- :parents => item['parents'],
- :notes => item['notes'],
- :medical => item['medical'],
- :religion => item['religion'],
- :school => item['school'],
- :ethnicity => item['ethnicity'],
- :subs => item['subs'],
- :custom1 => item['custom1'],
- :custom2 => item['custom2'],
- :custom3 => item['custom3'],
- :custom4 => item['custom4'],
- :custom5 => item['custom5'],
- :custom6 => item['custom6'],
- :custom7 => item['custom7'],
- :custom8 => item['custom8'],
- :custom9 => item['custom9'],
- :grouping_id => Osm::to_i_or_nil(item['patrolid']),
- :grouping_leader => Osm::to_i_or_nil(item['patrolleader']),
- :joined => Osm::parse_date(item['joined']),
- :age => item['age'].gsub(' ', ''),
- :joined_years => item['yrs'].to_i,
- :has_photo => summary_data[id]['pic']
+ :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 => 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],
+ receive_phone_2: member_contact[CID_RECIEVE_PHONE_2],
+ receive_email_1: member_contact[CID_RECIEVE_EMAIL_1],
+ receive_email_2: member_contact[CID_RECIEVE_EMAIL_2],
+ custom: DirtyHashy[ item_data[GID_MEMBER_CONTACT].map{ |k,v| [k.to_i, v] }.select{ |i| i[0] > CORE_FIELD_IDS_FINISH_AT } ],
+ custom_labels: custom_labels[GID_MEMBER_CONTACT],
+ ),
+ :primary_contact => 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],
+ receive_phone_2: primary_contact[CID_RECIEVE_PHONE_2],
+ receive_email_1: primary_contact[CID_RECIEVE_EMAIL_1],
+ receive_email_2: primary_contact[CID_RECIEVE_EMAIL_2],
+ custom: DirtyHashy[ item_data[GID_PRIMARY_CONTACT].map{ |k,v| [k.to_i, v] }.select{ |i| i[0] > CORE_FIELD_IDS_FINISH_AT } ],
+ custom_labels: custom_labels[GID_PRIMARY_CONTACT],
+ ),
+ :secondary_contact => PrimaryContact.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],
+ receive_phone_2: secondary_contact[CID_RECIEVE_PHONE_2],
+ receive_email_1: secondary_contact[CID_RECIEVE_EMAIL_1],
+ receive_email_2: secondary_contact[CID_RECIEVE_EMAIL_2],
+ custom: DirtyHashy[ item_data[GID_SECONDARY_CONTACT].map{ |k,v| [k.to_i, v] }.select{ |i| i[0] > CORE_FIELD_IDS_FINISH_AT } ],
+ custom_labels: custom_labels[GID_SECONDARY_CONTACT],
+ ),
+ :emergency_contact => 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],
+ custom: DirtyHashy[ item_data[GID_EMERGENCY_CONTACT].map{ |k,v| [k.to_i, v] }.select{ |i| i[0] > CORE_FIELD_IDS_FINISH_AT } ],
+ custom_labels: custom_labels[GID_EMERGENCY_CONTACT],
+ ),
+ :doctor => 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],
+ custom: DirtyHashy[ item_data[GID_DOCTOR_CONTACT].map{ |k,v| [k.to_i, v] }.select{ |i| i[0] > CORE_FIELD_IDS_FINISH_AT } ],
+ custom_labels: custom_labels[GID_DOCTOR_CONTACT],
+ ),
+ custom: DirtyHashy[ item_data[GID_CUSTOM].map{ |k,v| [k.to_i, v] } ],
+ custom_labels: custom_labels[GID_CUSTOM],
)
end
cache_write(api, cache_key, result)
return result
@@ -390,10 +452,61 @@
# @return [Boolean]
def youth?
grouping_id > 0
end
+ # Check if the member is male
+ # @return [Boolean]
+ def male?
+ gender == :male
+ end
+
+ # Check if the member is male
+ # @return [Boolean]
+ def female?
+ gender == :female
+ 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 [Boolean]
+ def current?(date=Date.today)
+ if finished_section.nil?
+ return (started_section <= date)
+ else
+ return (started_section <= date) && (finished_section >= date)
+ end
+ end
+
+ # @!method all_emails
+ # Get an array of all email addresses from all contacts for the member (not emergency or doctor)
+ # @return [Array<String>]
+ # @!method all_emails_with_name
+ # Get an array of all email addresses from all contacts for the member in a format which includes the contact's name (not emergency or doctor)
+ # @return [Array<String>]
+ # @!method enabled_emails
+ # Get an array of all email addresses from all contacts for the member (not emergency or doctor)
+ # @return [Array<String>]
+ # @!method enabled_emails_with_name
+ # Get an array of all email addresses from all contacts for the member in a format which includes the contact's name (not emergency or doctor)
+ # @return [Array<String>]
+ # @!method all_phones
+ # Get an array of all phone numbers from all contacts for the member (not emergency or doctor)
+ # @return [Array<String>]
+ # @!method enabled_phones
+ # Get an array of enabled phone numbers from all contacts for the member (not emergency or doctor)
+ # @return [Array<String>]
+ [:all_emails, :all_emails_with_name, :enabled_emails, :enabled_emails_with_name, :all_phones, :enabled_phones].each do |meth|
+ define_method meth do
+ items = []
+ [:contact, :primary_contact, :secondary_contact].each do |cont|
+ items.push *send(cont).send(meth)
+ end
+ return items
+ end
+ 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
@@ -411,19 +524,18 @@
return @myscout_link_key
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
+ # @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 has no photo or doesn't exist in OSM
+ # @raise [Osm:Error] if the member doesn't exist in OSM
# @return the photo of the member
- def get_photo(api, black_and_white=false, options={})
+ 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?
- raise Osm::Error, "the member doesn't have a photo in OSM" unless has_photo
cache_key = ['member_photo', self.id, black_and_white]
if !options[:no_cache] && cache_exist?(api, cache_key)
return cache_read(api, cache_key)
@@ -453,18 +565,238 @@
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
- # Compare Activity based on section_id, grouping_id, grouping_leader (descending), last_name then first_name
+ # Compare member based on section_id, grouping_id, grouping_leader (descending), last_name then first_name
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
+
+
+ module EmailableContact
+ # Get an array of all emails for the contact
+ # @return [Array<String>]
+ def all_emails
+ [email_1, email_2].select{ |e| !e.blank? }
+ end
+
+ # Get an array of enabled emails for the contact
+ # @return [Array<String>]
+ def enabled_emails
+ emails = []
+ emails.push email_1 if receive_email_1
+ emails.push email_2 if receive_email_2
+ emails.select{ |e| !e.blank? }
+ end
+
+ # Get an array of all emails for the contact in a format which includes their name
+ # @return [Array<String>]
+ def all_emails_with_name
+ [email_1, email_2].select{ |e| !e.blank? }.map{ |e| "\"#{name}\" <#{e}>" }
+ end
+
+ # Get an array of enabled emails for the contact in a format which includes their name
+ # @return [Array<String>]
+ def enabled_emails_with_name
+ emails = []
+ emails.push email_1 if receive_email_1
+ emails.push email_2 if receive_email_2
+ emails.select{ |e| !e.blank? }.map{ |e| "\"#{name}\" <#{e}>" }
+ end
+ end
+
+ module PhoneableContact
+ # Get an array of enabled phone numbers for the contact
+ def enabled_phones
+ phones = []
+ phones.push phone_1.gsub(/[^\d\+]/, '') if receive_phone_1
+ phones.push phone_2.gsub(/[^\d\+]/, '') if receive_phone_2
+ phones.select{ |n| !n.blank? }.map{ |n| n }
+ end
+ end
+
+
+ class Contact < Osm::Model
+ # @!attribute [rw] first_name
+ # @return [String] the contact's first name
+ # @!attribute [rw] last_name
+ # @return [String] the contact's last name
+ # @!attribute [rw] address_1
+ # @return [String] the 1st line of the address
+ # @!attribute [rw] address_2
+ # @return [String] the 2nd line of the address
+ # @!attribute [rw] address_3
+ # @return [String] the 3rd line of the address
+ # @!attribute [rw] address_4
+ # @return [String] the 4th line of the address
+ # @!attribute [rw] postcode
+ # @return [String] the postcode of the address
+ # @!attribute [rw] phone_1
+ # @return [String] the primary phone number
+ # @!attribute [rw] phone_2
+ # @return [String] the secondary phone number
+ # @!attribute [rw] custom
+ # @return [DirtyHashy] the custom data (key is OSM's variable name, value is the data)
+ # @!attribute [rw] custom_labels
+ # @return [DirtyHashy] the labels for the custom data (key is OSM's variable name, value is the label)
+
+ attribute :first_name, :type => String
+ attribute :last_name, :type => String
+ attribute :address_1, :type => String
+ attribute :address_2, :type => String
+ attribute :address_3, :type => String
+ attribute :address_4, :type => String
+ attribute :postcode, :type => String
+ attribute :phone_1, :type => String
+ attribute :phone_2, :type => String
+ attribute :custom, :type => Object, :default => DirtyHashy.new
+ attribute :custom_labels, :type => Object, :default => DirtyHashy.new
+
+ if ActiveModel::VERSION::MAJOR < 4
+ attr_accessible :first_name, :last_name, :address_1, :address_2, :address_3, :address_4,
+ :postcode, :phone_1, :phone_2, :custom, :custom_labels
+ end
+
+ # @!method initialize
+ # Initialize a new Contact
+ # @param [Hash] attributes The hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
+
+ # Get the full name
+ # @param [String] seperator What to split the scout's first name and last name with
+ # @return [String] this scout's full name seperated by the optional seperator
+ def name(seperator=' ')
+ return "#{first_name}#{seperator.to_s}#{last_name}"
+ end
+
+ # Get an array of all phone numbers for the contact
+ # @return [Array<String>]
+ def all_phones
+ [phone_1, phone_2].select{ |n| !n.blank? }.map{ |n| n.gsub(/[^\d\+]/, '') }
+ end
+ end
+
+
+ class MemberContact < Osm::Member::Contact
+ include EmailableContact
+ include PhoneableContact
+ # @!attribute [rw] email_1
+ # @return [String] the primary email address for the member
+ # @!attribute [rw] email_2
+ # @return [String] the secondary email address for the member
+ # @!attribute [rw] receive_email_1
+ # @return [Boolean] whether the member should receive emails from leaders on their primary email address
+ # @!attribute [rw] receive_email_2
+ # @return [Boolean] whether the member should receive emails from leaders on their secondary email address
+ # @!attribute [rw] receive_phone_1
+ # @return [Boolean] whether the member should receive SMSs from leaders on their primary phone number
+ # @!attribute [rw] receive_phone_2
+ # @return [Boolean] whether the member should receive SMSs from leaders on their secondary phone number
+
+ attribute :email_1, :type => String
+ attribute :receive_email_1, :type => Boolean, :default => false
+ attribute :email_2, :type => String
+ attribute :receive_email_2, :type => Boolean, :default => false
+ attribute :receive_phone_1, :type => Boolean, :default => false
+ attribute :receive_phone_2, :type => Boolean, :default => false
+
+ if ActiveModel::VERSION::MAJOR < 4
+ attr_accessible :email_1, :email_2, :receive_email_1, :receive_email_2,
+ :receive_phone_1, :receive_phone_2
+ end
+
+ validates_inclusion_of :receive_email_1, :in => [true, false]
+ validates_inclusion_of :receive_email_2, :in => [true, false]
+ validates_inclusion_of :receive_phone_1, :in => [true, false]
+ validates_inclusion_of :receive_phone_2, :in => [true, false]
+ end
+
+
+ class PrimaryContact < Osm::Member::Contact
+ include EmailableContact
+ include PhoneableContact
+ # @!attribute [rw] email_1
+ # @return [String] the primary email address for the contact
+ # @!attribute [rw] email_2
+ # @return [String] the secondary email address for the contact
+ # @!attribute [rw] receive_email_1
+ # @return [Boolean] whether the contact should receive emails from leaders on their primary email address
+ # @!attribute [rw] receive_email_2
+ # @return [Boolean] whether the contact should receive emails from leaders on their secondary email address
+ # @!attribute [rw] receive_phone_1
+ # @return [Boolean] whether the contact should receive SMSs from leaders on their primary phone number
+ # @!attribute [rw] receive_phone_2
+ # @return [Boolean] whether the contact should receive SMSs from leaders on their secondary phone number
+
+ attribute :email_1, :type => String
+ attribute :receive_email_1, :type => Boolean, :default => false
+ attribute :email_2, :type => String
+ attribute :receive_email_2, :type => Boolean, :default => false
+ attribute :receive_phone_1, :type => Boolean, :default => false
+ attribute :receive_phone_2, :type => Boolean, :default => false
+
+ if ActiveModel::VERSION::MAJOR < 4
+ attr_accessible :email_1, :email_2,
+ :receive_email_1, :receive_email_2, :receive_phone_1, :receive_phone_2
+ end
+
+ validates_inclusion_of :receive_email_1, :in => [true, false]
+ validates_inclusion_of :receive_email_2, :in => [true, false]
+ validates_inclusion_of :receive_phone_1, :in => [true, false]
+ validates_inclusion_of :receive_phone_2, :in => [true, false]
+ end # class PrimaryContact
+
+
+ class EmergencyContact < Osm::Member::Contact
+ # @!attribute [rw] email_1
+ # @return [String] the primary email address for the contact
+ # @!attribute [rw] email_2
+ # @return [String] the secondary email address for the contact
+
+ attribute :email_1, :type => String
+ attribute :email_2, :type => String
+
+ if ActiveModel::VERSION::MAJOR < 4
+ attr_accessible :email_1, :email_2
+ end
+
+ # Get the full name
+ # @param [String] seperator What to split the scout's first name and last name with
+ # @return [String] this scout's full name seperated by the optional seperator
+ def name(seperator=' ')
+ return "#{first_name}#{seperator.to_s}#{last_name}"
+ end
+ end # class EmergencyContact
+
+
+ class DoctorContact < Osm::Member::Contact
+ # @!attribute [rw] first_name
+ # @return [String] the contact's first name
+ # @!attribute [rw] last_name
+ # @return [String] the contact's last name
+ # @!attribute [rw] surgery
+ # @return [String] the surgery name
+
+ attribute :first_name, :type => String
+ attribute :last_name, :type => String
+ attribute :surgery, :type => String
+
+ if ActiveModel::VERSION::MAJOR < 4
+ attr_accessible :first_name, :last_name, :surgery
+ end
+
+ # Get the full name
+ # @param [String] seperator What to split the scout's first name and last name with
+ # @return [String] this scout's full name seperated by the optional seperator
+ def name(seperator=' ')
+ return "Dr. #{first_name}#{seperator.to_s}#{last_name}"
+ end
+ end # class DoctorContact
end # Class Member
end # Module