osm 0.1.17 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -30,11 +30,12 @@ module Osm
30
30
 
31
31
  # Get the groupings that a section has
32
32
  # @param [Osm::Api] api The api to use to make the request
33
- # @param [Fixnum] section the section (or its ID) of the section to get groupings for
33
+ # @param [Fixnum] section The section (or its ID) of the section to get groupings for
34
34
  # @!macro options_get
35
35
  # @return [Array<Osm::Grouping>, nil] An array of groupings or nil if the user can not access that section
36
36
  def self.get_for_section(api, section, options={})
37
37
  section_id = section.to_i
38
+ require_ability_to(api, :read, :member, section_id)
38
39
  cache_key = ['groupings', section_id]
39
40
 
40
41
  if !options[:no_cache] && cache_exist?(api, cache_key)
@@ -63,7 +64,45 @@ module Osm
63
64
 
64
65
  # @!method initialize
65
66
  # Initialize a new Term
66
- # @param [Hash] attributes the hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
67
+ # @param [Hash] attributes The hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
68
+
69
+
70
+ # Update the grouping in OSM
71
+ # @param [Osm::Api] api The api to use to make the request
72
+ # @return [Boolan] whether the member was successfully updated or not
73
+ # @raise [Osm::ObjectIsInvalid] If the Grouping is invalid
74
+ def update(api)
75
+ raise Osm::ObjectIsInvalid, 'grouping is invalid' unless valid?
76
+ require_ability_to(api, :read, :member, section_id)
77
+
78
+ to_update = changed_attributes
79
+ result = true
80
+
81
+ if to_update.include?('name') || to_update.include?('active')
82
+ data = api.perform_query("users.php?action=editPatrol&sectionid=#{section_id}", {
83
+ 'patrolid' => self.id,
84
+ 'name' => name,
85
+ 'active' => active,
86
+ })
87
+ result &= data.nil?
88
+ end
89
+
90
+ if to_update.include?('points')
91
+ data = api.perform_query("users.php?action=updatePatrolPoints&sectionid=#{section_id}", {
92
+ 'patrolid' => self.id,
93
+ 'points' => points,
94
+ })
95
+ result &= (data == {})
96
+ end
97
+
98
+ if result
99
+ reset_changed_attributes
100
+ # The cached groupings for the section will be out of date - remove them
101
+ Osm::Model.cache_delete(api, ['groupings', section_id])
102
+ end
103
+
104
+ return result
105
+ end
67
106
 
68
107
 
69
108
  end # Class Grouping
@@ -1,30 +1,28 @@
1
- # TODO with next version bump - rename to Meeting, also rename meeting_date to date
2
-
3
1
  module Osm
4
2
 
5
- class Evening < Osm::Model
3
+ class Meeting < Osm::Model
6
4
  class Activity; end # Ensure the constant exists for the validators
7
5
 
8
6
  # @!attribute [rw] id
9
- # @return [Fixnum] the id of the evening
7
+ # @return [Fixnum] the id of the meeting
10
8
  # @!attribute [rw] section_id
11
- # @return [Fixnum] the section the evening belongs to
9
+ # @return [Fixnum] the section the meeting belongs to
12
10
  # @!attribute [rw] title
13
- # @return [String] the title of the evening
11
+ # @return [String] the title of the meeting
14
12
  # @!attribute [rw] notes_for_parents
15
13
  # @return [String] notes to be shared with parents
16
14
  # @!attribute [rw] games
17
- # @return [String] games to be played during the evening
15
+ # @return [String] games to be played during the meeting
18
16
  # @!attribute [rw] pre_notes
19
- # @return [String] notes for the start of the evening
17
+ # @return [String] notes for the start of the meeting
20
18
  # @!attribute [rw] post_notes
21
- # @return [String] notes for the end of the evening
19
+ # @return [String] notes for the end of the meeting
22
20
  # @!attribute [rw] leaders
23
- # @return [String] the leaders present at the evening
24
- # @!attribute [rw] meeting_date
25
- # @return [Date] the date of the evening
21
+ # @return [String] the leaders present at the meeting
22
+ # @!attribute [rw] date
23
+ # @return [Date] the date of the meeting
26
24
  # @!attribute [rw] activities
27
- # @return [Array<Activity>] list of activities being done during the evening
25
+ # @return [Array<Activity>] list of activities being done during the meeting
28
26
  # @!attribute [rw] start_time
29
27
  # @return [String] the start time (hh:mm)
30
28
  # @!attribute [rw] finish_time
@@ -38,40 +36,40 @@ module Osm
38
36
  attribute :pre_notes, :type => String, :default => ''
39
37
  attribute :post_notes, :type => String, :default => ''
40
38
  attribute :leaders, :type => String, :default => ''
41
- attribute :meeting_date, :type => Date
39
+ attribute :date, :type => Date
42
40
  attribute :start_time, :type => String
43
41
  attribute :finish_time, :type => String
44
42
  attribute :activities, :default => []
45
43
 
46
- attr_accessible :id, :section_id, :title, :notes_for_parents, :games, :pre_notes, :post_notes, :leaders, :meeting_date, :activities, :start_time, :finish_time
44
+ attr_accessible :id, :section_id, :title, :notes_for_parents, :games, :pre_notes, :post_notes, :leaders, :date, :activities, :start_time, :finish_time
47
45
 
48
46
  validates_numericality_of :id, :only_integer=>true, :greater_than=>0
49
47
  validates_numericality_of :section_id, :only_integer=>true, :greater_than=>0
50
48
  validates_presence_of :title
51
- validates_presence_of :meeting_date
49
+ validates_presence_of :date
52
50
  validates_format_of :start_time, :with => Osm::OSM_TIME_REGEX, :message => 'is not in the correct format (HH:MM)', :allow_blank => true
53
51
  validates_format_of :finish_time, :with => Osm::OSM_TIME_REGEX, :message => 'is not in the correct format (HH:MM)', :allow_blank => true
54
52
 
55
- validates :activities, :array_of => {:item_type => Osm::Evening::Activity, :item_valid => true}
53
+ validates :activities, :array_of => {:item_type => Osm::Meeting::Activity, :item_valid => true}
56
54
 
57
55
  # @!method initialize
58
- # Initialize a new Evening
59
- # @param [Hash] attributes the hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
56
+ # Initialize a new Meeting
57
+ # @param [Hash] attributes The hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
60
58
 
61
59
 
62
60
  # Get the programme for a given term
63
61
  # @param [Osm::Api] api The api to use to make the request
64
- # @param [Osm::Section, Fixnum] section the section (or its ID) to get the programme for
65
- # @param [Osm::term, Fixnum, nil] term the term (or its ID) to get the programme for, passing nil causes the current term to be used
62
+ # @param [Osm::Section, Fixnum, #to_i] section The section (or its ID) to get the programme for
63
+ # @param [Osm::term, Fixnum, nil] term The term (or its ID) to get the programme for, passing nil causes the current term to be used
66
64
  # @!macro options_get
67
- # @return [Array<Osm::Evening>]
68
- # TODO Change to get_all in next version bump
69
- def self.get_programme(api, section, term=nil, options={})
65
+ # @return [Array<Osm::Meeting>]
66
+ def self.get_for_section(api, section, term=nil, options={})
67
+ require_ability_to(api, :read, :programme, section, options)
70
68
  section_id = section.to_i
71
69
  term_id = term.nil? ? Osm::Term.get_current_term_for_section(api, section).id : term.to_i
72
70
  cache_key = ['programme', section_id, term_id]
73
71
 
74
- if !options[:no_cache] && cache_exist?(api, cache_key) && get_user_permission(api, section_id, :programme).include?(:read)
72
+ if !options[:no_cache] && cache_exist?(api, cache_key)
75
73
  return cache_read(api, cache_key)
76
74
  end
77
75
 
@@ -94,13 +92,13 @@ module Osm
94
92
  attributes[:leaders] = item['leaders'] || ''
95
93
  attributes[:start_time] = item['starttime'].nil? ? nil : item['starttime'][0..4]
96
94
  attributes[:finish_time] = item['endtime'].nil? ? nil : item['endtime'][0..4]
97
- attributes[:meeting_date] = Osm::parse_date(item['meetingdate'])
95
+ attributes[:date] = Osm::parse_date(item['meetingdate'])
98
96
 
99
97
  our_activities = activities[item['eveningid']]
100
98
  attributes[:activities] = Array.new
101
99
  unless our_activities.nil?
102
100
  our_activities.each do |activity_data|
103
- attributes[:activities].push Osm::Evening::Activity.new(
101
+ attributes[:activities].push Osm::Meeting::Activity.new(
104
102
  :activity_id => Osm::to_i_or_nil(activity_data['activityid']),
105
103
  :title => activity_data['title'],
106
104
  :notes => activity_data['notes'],
@@ -116,36 +114,39 @@ module Osm
116
114
  end
117
115
 
118
116
 
119
- # Create an evening in OSM
117
+ # Create a meeting in OSM
120
118
  # @param [Osm::Api] api The api to use to make the request
121
- # @return [Osm::Evening, nil] the created evening, nil if failed
119
+ # @return [Osm::Meeting, nil] the created meeting, nil if failed
122
120
  def self.create(api, parameters)
123
- evening = new(parameters)
121
+ require_ability_to(api, :write, :programme, parameters[:section_id])
122
+ meeting = new(parameters)
124
123
 
125
124
  data = api.perform_query("programme.php?action=addActivityToProgramme", {
126
- 'meetingdate' => evening.meeting_date.strftime(Osm::OSM_DATE_FORMAT),
127
- 'sectionid' => evening.section_id,
125
+ 'meetingdate' => meeting.date.strftime(Osm::OSM_DATE_FORMAT),
126
+ 'sectionid' => meeting.section_id,
128
127
  'activityid' => -1,
129
- 'start' => evening.meeting_date.strftime(Osm::OSM_DATE_FORMAT),
130
- 'starttime' => evening.start_time,
131
- 'endtime' => evening.finish_time,
132
- 'title' => evening.title,
128
+ 'start' => meeting.date.strftime(Osm::OSM_DATE_FORMAT),
129
+ 'starttime' => meeting.start_time,
130
+ 'endtime' => meeting.finish_time,
131
+ 'title' => meeting.title,
133
132
  })
134
133
 
135
134
  # The cached programmes for the section will be out of date - remove them
136
- Osm::Term.get_for_section(api, evening.section_id).each do |term|
137
- cache_delete(api, ['programme', evening.section_id, term.id])
135
+ Osm::Term.get_for_section(api, meeting.section_id).each do |term|
136
+ cache_delete(api, ['programme', meeting.section_id, term.id])
138
137
  end
139
138
 
140
- return data.is_a?(Hash) ? evening : nil
139
+ return data.is_a?(Hash) ? meeting : nil
141
140
  end
142
141
 
143
142
 
144
- # Update an evening in OSM
143
+ # Update an meeting in OSM
145
144
  # @param [Osm::Api] api The api to use to make the request
146
145
  # @return [Boolean] if the operation suceeded or not
146
+ # @raise [Osm::ObjectIsInvalid] If the Meeting is invalid
147
147
  def update(api)
148
- raise ObjectIsInvalid, 'evening is invalid' unless valid?
148
+ raise Osm::ObjectIsInvalid, 'meeting is invalid' unless valid?
149
+ require_ability_to(api, :write, :programme, section_id)
149
150
 
150
151
  activities_data = Array.new
151
152
  activities.each do |activity|
@@ -160,7 +161,7 @@ module Osm
160
161
  api_data = {
161
162
  'eveningid' => id,
162
163
  'sectionid' => section_id,
163
- 'meetingdate' => meeting_date.strftime(Osm::OSM_DATE_FORMAT),
164
+ 'meetingdate' => date.strftime(Osm::OSM_DATE_FORMAT),
164
165
  'starttime' => start_time,
165
166
  'endtime' => finish_time,
166
167
  'title' => title,
@@ -173,26 +174,30 @@ module Osm
173
174
  }
174
175
  response = api.perform_query("programme.php?action=editEvening", api_data)
175
176
 
176
- # The cached programmes for the section will be out of date - remove them
177
- Osm::Term.get_for_section(api, section_id).each do |term|
178
- cache_delete(api, ['programme', section_id, term.id]) if term.contains_date?(meeting_date)
177
+ if response.is_a?(Hash) && (response['result'] == 0)
178
+ reset_changed_attributes
179
+ # The cached programmes for the section will be out of date - remove them
180
+ Osm::Term.get_for_section(api, section_id).each do |term|
181
+ cache_delete(api, ['programme', section_id, term.id]) if term.contains_date?(date)
182
+ end
183
+ return true
184
+ else
185
+ return false
179
186
  end
180
-
181
- return response.is_a?(Hash) && (response['result'] == 0)
182
187
  end
183
188
 
184
- # Add an activity to this evening in OSM
189
+ # Add an activity to this meeting in OSM
185
190
  # @param [Osm::Api] api The api to use to make the request
186
- # @param [Osm::Activity] activity The Activity to add to the Evening
187
- # @param [String] notes The notes which should appear for this Activity on this Evening
191
+ # @param [Osm::Activity] activity The Activity to add to the Meeting
192
+ # @param [String] notes The notes which should appear for this Activity on this Meeting
188
193
  # @return [Boolean] Whether the activity ws successfully added
189
194
  def add_activity(api, activity, notes='')
190
- if activity.add_to_programme(api, section_id, meeting_date, notes)
191
- activities.push Osm::Evening::Activity.new(:activity_id => activity.id, :notes => notes, :title => activity.title)
195
+ if activity.add_to_programme(api, section_id, date, notes)
196
+ activities.push Osm::Meeting::Activity.new(:activity_id => activity.id, :notes => notes, :title => activity.title)
192
197
 
193
198
  # The cached programmes for the section will be out of date - remove them
194
199
  Osm::Term.get_for_section(api, section_id).each do |term|
195
- cache_delete(api, ['programme', section_id, term.id]) if term.contains_date?(meeting_date)
200
+ cache_delete(api, ['programme', section_id, term.id]) if term.contains_date?(date)
196
201
  end
197
202
 
198
203
  return true
@@ -201,34 +206,36 @@ module Osm
201
206
  return false
202
207
  end
203
208
 
204
- # Delete evening from OSM
209
+ # Delete meeting from OSM
205
210
  # @param [Osm::Api] api The api to use to make the request
206
211
  # @return [Boolean] true
207
212
  def delete(api)
213
+ require_ability_to(api, :write, :programme, section_id)
208
214
  data = api.perform_query("programme.php?action=deleteEvening&eveningid=#{id}&sectionid=#{section_id}")
209
215
 
210
216
  # The cached programmes for the section will be out of date - remove them
211
217
  Osm::Term.get_for_section(api, section_id).each do |term|
212
- cache_delete(api, ['programme', section_id, term.id]) if term.contains_date?(meeting_date)
218
+ cache_delete(api, ['programme', section_id, term.id]) if term.contains_date?(date)
213
219
  end
214
220
 
215
221
  return true
216
222
  end
217
223
 
218
224
 
219
- # Get the badge requirements met on a specific evening
225
+ # Get the badge requirements met on a specific meeting
220
226
  # @param [Osm::Api] api The api to use to make the request
221
227
  # @!macro options_get
222
228
  # @return [Array<Hash>] hashes ready to pass into the update_register method
223
229
  def get_badge_requirements(api, options={})
230
+ require_ability_to(api, :read, :programme, section_id, options)
224
231
  section = Osm::Section.get(api, section_id)
225
232
  cache_key = ['badge_requirements', section.id, id]
226
233
 
227
- if !options[:no_cache] && cache_exist?(api, cache_key) && get_user_permission(api, section_id, :programme).include?(:read)
234
+ if !options[:no_cache] && cache_exist?(api, cache_key)
228
235
  return cache_read(api, cache_key)
229
236
  end
230
237
 
231
- data = api.perform_query("users.php?action=getActivityRequirements&date=#{meeting_date.strftime(Osm::OSM_DATE_FORMAT)}&sectionid=#{section.id}&section=#{section.type}")
238
+ data = api.perform_query("users.php?action=getActivityRequirements&date=#{date.strftime(Osm::OSM_DATE_FORMAT)}&sectionid=#{section.id}&section=#{section.type}")
232
239
 
233
240
  cache_write(api, cache_key, data)
234
241
  return data
@@ -240,7 +247,7 @@ module Osm
240
247
  compare = self.section_id <=> another.section_id
241
248
  return compare unless compare == 0
242
249
 
243
- compare = self.meeting_date <=> another.meeting_date
250
+ compare = self.date <=> another.date
244
251
  return compare unless compare == 0
245
252
 
246
253
  my_start_time = self.start_time.split(':').map{ |i| i.to_i }
@@ -267,7 +274,7 @@ module Osm
267
274
  # @!attribute [rw] title
268
275
  # @return [String] the activity's title
269
276
  # @!attribute [rw] notes
270
- # @return [String] notes relevant to doing this activity on this evening
277
+ # @return [String] notes relevant to doing this activity on this meeting
271
278
 
272
279
  attribute :activity_id, :type => Integer
273
280
  attribute :title, :type => String
@@ -279,11 +286,11 @@ module Osm
279
286
  validates_presence_of :title
280
287
 
281
288
  # @!method initialize
282
- # Initialize a new Evening::Activity
283
- # @param [Hash] attributes the hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
289
+ # Initialize a new Meeting::Activity
290
+ # @param [Hash] attributes The hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
284
291
 
285
- end # Class Evening::Activity
292
+ end # Class Meeting::Activity
286
293
 
287
- end # Class Evening
294
+ end # Class Meeting
288
295
 
289
296
  end # Module
@@ -74,8 +74,6 @@ module Osm
74
74
  # @return [Fixnum] the grouping within the section that the member belongs to
75
75
  # @!attribute [rw] grouping_leader
76
76
  # @return [Fixnum] whether the member is the grouping leader (0=no, 1=seconder/APL, 2=sixer/PL)
77
- # @!attribute [rw] grouping_label
78
- # @return [Fixnum] the grouping within the section that the member belongs to (as displayed in OSM, if member was retrieved from OSM)
79
77
  # @!attribute [rw] joined
80
78
  # @return [Date] when the member joined the section
81
79
  # @!attribute [rw] age
@@ -118,7 +116,6 @@ module Osm
118
116
  attribute :custom8, :type => String, :default => ''
119
117
  attribute :custom9, :type => String, :default => ''
120
118
  attribute :grouping_id, :type => Integer
121
- attribute :grouping_label, :type => String, :default => ''
122
119
  attribute :grouping_leader, :type => Integer
123
120
  attribute :joined, :type => Date
124
121
  attribute :age, :type => String
@@ -128,7 +125,7 @@ module Osm
128
125
  :phone1, :phone2, :phone3, :phone4, :address, :address2, :date_of_birth, :started,
129
126
  :joining_in_years, :parents, :notes, :medical, :religion, :school, :ethnicity, :subs,
130
127
  :custom1, :custom2, :custom3, :custom4, :custom5, :custom6, :custom7, :custom8, :custom9,
131
- :grouping_id, :grouping_label, :grouping_leader, :joined, :age, :joined_years
128
+ :grouping_id, :grouping_leader, :joined, :age, :joined_years
132
129
 
133
130
  validates_numericality_of :id, :only_integer=>true, :greater_than=>0, :unless => Proc.new { |r| r.id.nil? }
134
131
  validates_numericality_of :section_id, :only_integer=>true, :greater_than=>0
@@ -146,17 +143,18 @@ module Osm
146
143
 
147
144
  # Get members for a section
148
145
  # @param [Osm::Api] api The api to use to make the request
149
- # @param [Osm::Section, Fixnum] section the section (or its ID) to get the members for
150
- # @param [Osm::Term, Fixnum, nil] term the term (or its ID) to get the members for, passing nil causes the current term to be used
146
+ # @param [Osm::Section, Fixnum, #to_i] section The section (or its ID) to get the members for
147
+ # @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
151
148
  # @!macro options_get
152
149
  # @return [Array<Osm::Member>]
153
150
  def self.get_for_section(api, section, term=nil, options={})
151
+ require_ability_to(api, :read, :member, section, options)
154
152
  section = Osm::Section.get(api, section) if section.is_a?(Fixnum)
155
153
  term = -1 if section.waiting?
156
154
  term_id = term.nil? ? Osm::Term.get_current_term_for_section(api, section).id : term.to_i
157
155
  cache_key = ['members', section.id, term_id]
158
156
 
159
- if !options[:no_cache] && cache_exist?(api, cache_key) && get_user_permission(api, section.id, :member).include?(:read)
157
+ if !options[:no_cache] && cache_exist?(api, cache_key)
160
158
  return cache_read(api, cache_key)
161
159
  end
162
160
 
@@ -200,7 +198,6 @@ module Osm
200
198
  :custom8 => item['custom8'],
201
199
  :custom9 => item['custom9'],
202
200
  :grouping_id => Osm::to_i_or_nil(item['patrolid']),
203
- :grouping_label => item['patrol'],
204
201
  :grouping_leader => Osm::to_i_or_nil(item['patrolleader']),
205
202
  :joined => Osm::parse_date(item['joined']),
206
203
  :age => item['age'].gsub(' ', ''),
@@ -213,31 +210,20 @@ module Osm
213
210
  end
214
211
 
215
212
 
216
- # @deprecated use grouping_label instead
217
- # @return [String] the grouping as displayed in OSM
218
- # TODO - Use a Grouping object not String when upping the version
219
- def grouping
220
- return self.grouping_label
221
- end
222
- # @deprecated use grouping_label instead
223
- # TODO - Use a Grouping object not String when upping the version
224
- def grouping=(new_grouping)
225
- return self.grouping_label = new_grouping
226
- end
227
-
228
-
229
-
230
213
  # @!method initialize
231
214
  # Initialize a new Member
232
- # @param [Hash] attributes the hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
215
+ # @param [Hash] attributes The hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
233
216
 
234
217
 
235
218
  # Create the user in OSM
236
219
  # @param [Osm::Api] api The api to use to make the request
237
220
  # @return [Boolan] whether the member was successfully added or not
221
+ # @raise [Osm::ObjectIsInvalid] If the Member is invalid
222
+ # @raise [Osm::Error] If the member already exists in OSM
238
223
  def create(api)
239
- raise ObjectIsInvalid, 'member is invalid' unless valid?
240
- raise Error, 'the member already exists in OSM' unless id.nil?
224
+ raise Osm::ObjectIsInvalid, 'member is invalid' unless valid?
225
+ require_ability_to(api, :write, :member, section_id)
226
+ raise Osm::Error, 'the member already exists in OSM' unless id.nil?
241
227
 
242
228
  data = api.perform_query("users.php?action=newMember", {
243
229
  'firstname' => first_name,
@@ -288,45 +274,47 @@ module Osm
288
274
  end
289
275
  end
290
276
 
291
- # Update the user in OSM
277
+ # Update the member in OSM
292
278
  # @param [Osm::Api] api The api to use to make the request
293
279
  # @return [Boolan] whether the member was successfully updated or not
280
+ # @raise [Osm::ObjectIsInvalid] If the Member is invalid
294
281
  def update(api)
295
- raise ObjectIsInvalid, 'member is invalid' unless valid?
282
+ raise Osm::ObjectIsInvalid, 'member is invalid' unless valid?
283
+ require_ability_to(api, :write, :member, section_id)
296
284
 
297
- values = {
298
- 'firstname' => first_name,
299
- 'lastname' => last_name,
300
- 'dob' => date_of_birth.strftime(Osm::OSM_DATE_FORMAT),
301
- 'started' => started.strftime(Osm::OSM_DATE_FORMAT),
302
- 'startedsection' => joined.strftime(Osm::OSM_DATE_FORMAT),
303
- 'email1' => email1,
304
- 'email2' => email2,
305
- 'email3' => email3,
306
- 'email4' => email4,
307
- 'phone1' => phone1,
308
- 'phone2' => phone2,
309
- 'phone3' => phone3,
310
- 'phone4' => phone4,
311
- 'address' => address,
312
- 'address2' => address2,
313
- 'parents' => parents,
314
- 'notes' => notes,
315
- 'medical' => medical,
316
- 'religion' => religion,
317
- 'school' => school,
318
- 'ethnicity' => ethnicity,
319
- 'subs' => subs,
320
- 'custom1' => custom1,
321
- 'custom2' => custom2,
322
- 'custom3' => custom3,
323
- 'custom4' => custom4,
324
- 'custom5' => custom5,
325
- 'custom6' => custom6,
326
- 'custom7' => custom7,
327
- 'custom8' => custom8,
328
- 'custom9' => custom9,
329
- }
285
+ to_update = changed_attributes
286
+ values = {}
287
+ values['firstname'] = first_name if to_update.include?('first_name')
288
+ values['lastname'] = last_name if to_update.include?('last_name')
289
+ values['dob'] = date_of_birth.strftime(Osm::OSM_DATE_FORMAT) if to_update.include?('date_of_birth')
290
+ values['started'] = started.strftime(Osm::OSM_DATE_FORMAT) if to_update.include?('started')
291
+ values['startedsection'] = joined.strftime(Osm::OSM_DATE_FORMAT) if to_update.include?('joined')
292
+ values['email1'] = email1 if to_update.include?('email1')
293
+ values['email2'] = email2 if to_update.include?('email2')
294
+ values['email3'] = email3 if to_update.include?('email3')
295
+ values['email4'] = email4 if to_update.include?('email4')
296
+ values['phone1'] = phone1 if to_update.include?('phone1')
297
+ values['phone2'] = phone2 if to_update.include?('phone2')
298
+ values['phone3'] = phone3 if to_update.include?('phone3')
299
+ values['phone4'] = phone4 if to_update.include?('phone3')
300
+ values['address'] = address if to_update.include?('address')
301
+ values['address2'] = address2 if to_update.include?('address2')
302
+ values['parents'] = parents if to_update.include?('parents')
303
+ values['notes'] = notes if to_update.include?('notes')
304
+ values['medical'] = medical if to_update.include?('medical')
305
+ values['religion'] = religion if to_update.include?('religion')
306
+ values['school'] = school if to_update.include?('school')
307
+ values['ethnicity'] = ethnicity if to_update.include?('ethnicity')
308
+ values['subs'] = subs if to_update.include?('subs')
309
+ values['custom1'] = custom1 if to_update.include?('custom1')
310
+ values['custom2'] = custom2 if to_update.include?('custom2')
311
+ values['custom3'] = custom3 if to_update.include?('custom3')
312
+ values['custom4'] = custom4 if to_update.include?('custom4')
313
+ values['custom5'] = custom5 if to_update.include?('custom5')
314
+ values['custom6'] = custom6 if to_update.include?('custom6')
315
+ values['custom7'] = custom7 if to_update.include?('custom7')
316
+ values['custom8'] = custom8 if to_update.include?('custom8')
317
+ values['custom9'] = custom9 if to_update.include?('custom9')
330
318
 
331
319
  result = true
332
320
  values.each do |column, value|
@@ -339,13 +327,23 @@ module Osm
339
327
  result &= (data[column] == value.to_s)
340
328
  end
341
329
 
342
- data = api.perform_query("users.php?action=updateMemberPatrol", {
343
- 'scoutid' => self.id,
344
- 'patrolid' => grouping_id,
345
- 'pl' => grouping_leader,
346
- 'sectionid' => section_id,
347
- })
348
- result &= ((data['patrolid'].to_i == grouping_id) && (data['patrolleader'].to_i == grouping_leader))
330
+ if to_update.include?('grouping_id') || to_update.include?('grouping_leader')
331
+ data = api.perform_query("users.php?action=updateMemberPatrol", {
332
+ 'scoutid' => self.id,
333
+ 'patrolid' => grouping_id,
334
+ 'pl' => grouping_leader,
335
+ 'sectionid' => section_id,
336
+ })
337
+ result &= ((data['patrolid'].to_i == grouping_id) && (data['patrolleader'].to_i == grouping_leader))
338
+ end
339
+
340
+ if result
341
+ reset_changed_attributes
342
+ # The cached columns for the flexi record will be out of date - remove them
343
+ Osm::Term.get_for_section(api, section_id).each do |term|
344
+ Osm::Model.cache_delete(api, ['members', section_id, term.id])
345
+ end
346
+ end
349
347
 
350
348
  return result
351
349
  end
@@ -363,12 +361,34 @@ module Osm
363
361
  end
364
362
 
365
363
  # Get the full name
366
- # @param [String] seperator what to split the scout's first name and last name with
364
+ # @param [String] seperator What to split the scout's first name and last name with
367
365
  # @return [String] this scout's full name seperated by the optional seperator
368
366
  def name(seperator=' ')
369
367
  return "#{first_name}#{seperator.to_s}#{last_name}"
370
368
  end
371
369
 
370
+ # Get the My.SCOUT link for this member
371
+ # @param [Osm::Api] api The api to use to make the request
372
+ # @param [Symbol] link_to The page in My.SCOUT to link to (:payments, :events, :programme or :badges)
373
+ # @return [String] the link for this member's My.SCOUT
374
+ # @raise [Osm::ObjectIsInvalid] If the Member is invalid
375
+ # @raise [Osm::ArgumentIsInvalid] If link_to is not an allowed Symbol
376
+ # @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
377
+ def myscout_link(api, link_to=:badges)
378
+ raise Osm::ObjectIsInvalid, 'member is invalid' unless valid?
379
+ require_ability_to(api, :read, :member, section_id)
380
+ raise Osm::Error, 'the member does not already exist in OSM' if id.nil?
381
+ raise Osm::ArgumentIsInvalid, 'link_to is invalid' unless [:payments, :events, :programme, :badges].include?(link_to)
382
+
383
+ if @myscout_link_key.nil?
384
+ data = api.perform_query("api.php?action=getMyScoutKey&sectionid=#{section_id}&scoutid=#{self.id}")
385
+ raise Osm::Error, 'Could not retrieve the key for the link from OSM' unless data['ok']
386
+ @myscout_link_key = data['key']
387
+ end
388
+
389
+ return "https://www.onlinescoutmanager.co.uk/parents/#{link_to}.php?sc=#{self.id}&se=#{section_id}&c=#{@myscout_link_key}"
390
+ end
391
+
372
392
  end # Class Member
373
393
 
374
394
  end # Module