osm 0.0.26 → 0.1.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.
- data/CHANGELOG.md +57 -0
- data/README.md +13 -7
- data/lib/osm.rb +47 -22
- data/lib/osm/activity.rb +52 -57
- data/lib/osm/api.rb +115 -1031
- data/lib/osm/api_access.rb +73 -36
- data/lib/osm/due_badges.rb +27 -12
- data/lib/osm/evening.rb +118 -55
- data/lib/osm/event.rb +275 -17
- data/lib/osm/flexi_record.rb +131 -0
- data/lib/osm/grouping.rb +37 -15
- data/lib/osm/member.rb +100 -41
- data/lib/osm/model.rb +95 -0
- data/lib/osm/register.rb +177 -0
- data/lib/osm/section.rb +163 -71
- data/lib/osm/term.rb +135 -21
- data/spec/osm/activity_spec.rb +7 -4
- data/spec/osm/api_access_spec.rb +44 -36
- data/spec/osm/api_spec.rb +32 -1147
- data/spec/osm/due_badges_spec.rb +8 -1
- data/spec/osm/evening_spec.rb +119 -54
- data/spec/osm/event_spec.rb +363 -13
- data/spec/osm/flexi_record_spec.rb +128 -0
- data/spec/osm/grouping_spec.rb +9 -5
- data/spec/osm/member_spec.rb +111 -36
- data/spec/osm/model_spec.rb +140 -0
- data/spec/osm/osm_spec.rb +7 -31
- data/spec/osm/register_spec.rb +103 -0
- data/spec/osm/section_spec.rb +208 -92
- data/spec/osm/term_spec.rb +164 -28
- data/spec/spec_helper.rb +22 -0
- data/version.rb +1 -1
- metadata +22 -29
- data/lib/osm/event_attendance.rb +0 -55
- data/lib/osm/flexi_record_data.rb +0 -51
- data/lib/osm/flexi_record_field.rb +0 -42
- data/lib/osm/register_data.rb +0 -64
- data/lib/osm/register_field.rb +0 -42
- data/lib/osm/role.rb +0 -133
- data/spec/osm/api_strangeness_spec.rb +0 -83
- data/spec/osm/event_attendance_spec.rb +0 -34
- data/spec/osm/flexi_record_data_spec.rb +0 -40
- data/spec/osm/flexi_record_field_spec.rb +0 -23
- data/spec/osm/register_data_spec.rb +0 -35
- data/spec/osm/register_field_spec.rb +0 -24
- data/spec/osm/role_spec.rb +0 -118
data/lib/osm/api_access.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
module Osm
|
2
2
|
|
3
|
-
class ApiAccess
|
4
|
-
include ::ActiveAttr::MassAssignmentSecurity
|
5
|
-
include ::ActiveAttr::Model
|
3
|
+
class ApiAccess < Osm::Model
|
6
4
|
|
7
5
|
# @!attribute [rw] id
|
8
6
|
# @return [Fixnum] the id for the API
|
@@ -20,52 +18,91 @@ module Osm
|
|
20
18
|
validates_numericality_of :id, :only_integer=>true, :greater_than=>0
|
21
19
|
validates_presence_of :name
|
22
20
|
|
23
|
-
validates :permissions, :hash => {:key_type => Symbol, :
|
21
|
+
validates :permissions, :hash => {:key_type => Symbol, :value_type => Array}
|
24
22
|
|
25
23
|
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
24
|
+
# Get API access details for a given section
|
25
|
+
# @param [Osm::Api] api The api to use to make the request
|
26
|
+
# @param [Osm::Section, Fixnum] section the section (or its ID) to get the details for
|
27
|
+
# @!macro options_get
|
28
|
+
# @return [Array<Osm::ApiAccess>]
|
29
|
+
def self.get_all(api, section, options={})
|
30
|
+
section_id = section.to_i
|
31
|
+
cache_key = ['api_access', api.user_id, section_id]
|
29
32
|
|
33
|
+
if !options[:no_cache] && cache_exist?(api, cache_key)
|
34
|
+
return cache_read(api, cache_key)
|
35
|
+
end
|
30
36
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
attributes[:
|
42
|
-
attributes[:permissions]
|
37
|
+
data = api.perform_query("users.php?action=getAPIAccess§ionid=#{section_id}")
|
38
|
+
|
39
|
+
permissions_map = {
|
40
|
+
10 => [:read],
|
41
|
+
20 => [:read, :write],
|
42
|
+
}
|
43
|
+
result = Array.new
|
44
|
+
data['apis'].each do |item|
|
45
|
+
attributes = {}
|
46
|
+
attributes[:id] = item['apiid'].to_i
|
47
|
+
attributes[:name] = item['name']
|
48
|
+
attributes[:permissions] = item['permissions'].is_a?(Hash) ? item['permissions'] : {}
|
49
|
+
|
50
|
+
# Rubyify permissions hash
|
51
|
+
attributes[:permissions].keys.each do |old_key|
|
52
|
+
new_key = (old_key.to_sym rescue old_key) # Get symbol of the key
|
53
|
+
attributes[:permissions][new_key] = attributes[:permissions].delete(old_key) # Change the key
|
54
|
+
attributes[:permissions][new_key] = permissions_map[attributes[:permissions][new_key].to_i] # Translate permissions value
|
55
|
+
end
|
56
|
+
attributes[:permissions].freeze
|
57
|
+
|
58
|
+
this_item = new(attributes)
|
59
|
+
result.push this_item
|
60
|
+
cache_write(api, [*cache_key, this_item.id], this_item)
|
43
61
|
end
|
44
|
-
|
62
|
+
cache_write(api, cache_key, result)
|
45
63
|
|
46
|
-
return
|
64
|
+
return result
|
47
65
|
end
|
48
66
|
|
49
|
-
# Determine if this API has read access for the provided permission
|
50
|
-
# @param [Symbol] key the permission being queried
|
51
|
-
# @return [Boolean] if this API can read the passed permission
|
52
|
-
def can_read?(key)
|
53
|
-
return [20, 10].include?(permissions[key])
|
54
|
-
end
|
55
67
|
|
56
|
-
#
|
57
|
-
# @param [
|
58
|
-
# @
|
59
|
-
|
60
|
-
|
68
|
+
# Get our API access details for a given section
|
69
|
+
# @param [Osm::Api] api The api to use to make the request
|
70
|
+
# @param [Osm::Section, Fixnum] section the section (or its ID) to get the details for
|
71
|
+
# @!macro options_get
|
72
|
+
# @return [Osm::ApiAccess]
|
73
|
+
def self.get_ours(api, section, options={})
|
74
|
+
get(api, section, api.api_id, options)
|
61
75
|
end
|
62
76
|
|
63
|
-
|
64
|
-
#
|
65
|
-
|
66
|
-
|
77
|
+
|
78
|
+
# Get API Access for a given API
|
79
|
+
# @param [Osm::Api] api The api to use to make the request
|
80
|
+
# @param [Osm::Section, Fixnum] section the section (or its ID) to get the details for
|
81
|
+
# @param [Osm::Api] for_api The api (or its ID) to get access for
|
82
|
+
# @!macro options_get
|
83
|
+
# @return [Osm::ApiAccess]
|
84
|
+
def self.get(api, section, for_api, options={})
|
85
|
+
section_id = section.to_i
|
86
|
+
for_api_id = for_api.to_i
|
87
|
+
cache_key = ['api_access', api.user_id, section_id, for_api]
|
88
|
+
|
89
|
+
if !options[:no_cache] && cache_exist?(api, cache_key)
|
90
|
+
return cache_read(api, cache_key)
|
91
|
+
end
|
92
|
+
|
93
|
+
data = get_all(api, section_id, options)
|
94
|
+
|
95
|
+
data.each do |item|
|
96
|
+
return item if item.id == for_api_id
|
97
|
+
end
|
98
|
+
return nil
|
67
99
|
end
|
68
100
|
|
101
|
+
|
102
|
+
# @!method initialize
|
103
|
+
# Initialize a new Term
|
104
|
+
# @param [Hash] attributes the hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
|
105
|
+
|
69
106
|
end # Class ApiAccess
|
70
107
|
|
71
108
|
end # Module
|
data/lib/osm/due_badges.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
module Osm
|
2
2
|
|
3
|
-
class DueBadges
|
4
|
-
include ::ActiveAttr::MassAssignmentSecurity
|
5
|
-
include ::ActiveAttr::Model
|
3
|
+
class DueBadges < Osm::Model
|
6
4
|
|
7
5
|
# @!attribute [rw] descriptions
|
8
6
|
# @return [Hash] descriptions for each of the badges
|
@@ -30,15 +28,25 @@ module Osm
|
|
30
28
|
end
|
31
29
|
|
32
30
|
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
31
|
+
# Get due badges
|
32
|
+
# @param [Osm::Api] api The api to use to make the request
|
33
|
+
# @param [Osm::Section, Fixnum] section the section (or its ID) to get the due badges for
|
34
|
+
# @param [Osm::Term, Fixnum, nil] term the term (or its ID) to get the due badges for, passing nil causes the current term to be used
|
35
|
+
# @!macro options_get
|
36
|
+
# @return [Osm::DueBadges]
|
37
|
+
def self.get(api, section, term=nil, options={})
|
38
|
+
section = Osm::Section.get(api, section, options) if section.is_a?(Fixnum)
|
39
|
+
term_id = term.nil? ? Osm::Term.get_current_term_for_section(api, section, options) : term.to_i
|
40
|
+
cache_key = ['due_badges', section.id, term_id]
|
36
41
|
|
42
|
+
if !options[:no_cache] && cache_exist?(api, cache_key) && get_user_permissions(api, section.id)[:badge].include?(:read)
|
43
|
+
return cache_read(api, cache_key)
|
44
|
+
end
|
37
45
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
data = {} unless data.is_a?(Hash) # OSM returns an empty array to represent no badges
|
46
|
+
data = api.perform_query("challenges.php?action=outstandingBadges§ion=#{section.type}§ionid=#{section.id}&termid=#{term_id}")
|
47
|
+
|
48
|
+
|
49
|
+
data = {} unless data.is_a?(Hash) # OSM/OGM returns an empty array to represent no badges
|
42
50
|
pending_raw = data['pending'] || {}
|
43
51
|
descriptions_raw = data['description'] || {}
|
44
52
|
|
@@ -52,16 +60,23 @@ module Osm
|
|
52
60
|
name = "#{member['firstname']} #{member['lastname']}"
|
53
61
|
description = descriptions_raw[key]['name'] + (descriptions_raw[key]['section'].eql?('staged') ? " (Level #{member['level']})" : '')
|
54
62
|
description_key = key + (descriptions_raw[key]['section'].eql?('staged') ? "_#{member['level']}" : '_1')
|
55
|
-
|
56
63
|
attributes[:descriptions][description_key] = description
|
57
64
|
attributes[:by_member][name] ||= []
|
58
65
|
attributes[:by_member][name].push(description_key)
|
59
66
|
end
|
60
67
|
end
|
61
68
|
|
62
|
-
new(attributes)
|
69
|
+
due_badges = Osm::DueBadges.new(attributes)
|
70
|
+
cache_write(api, cache_key, due_badges)
|
71
|
+
return due_badges
|
63
72
|
end
|
64
73
|
|
74
|
+
|
75
|
+
# @!method initialize
|
76
|
+
# Initialize a new Term
|
77
|
+
# @param [Hash] attributes the hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
|
78
|
+
|
79
|
+
|
65
80
|
# Check if there are no badges due
|
66
81
|
# @return [Boolean]
|
67
82
|
def empty?
|
data/lib/osm/evening.rb
CHANGED
@@ -1,11 +1,8 @@
|
|
1
1
|
module Osm
|
2
2
|
|
3
|
-
class Evening
|
3
|
+
class Evening < Osm::Model
|
4
4
|
class Activity; end # Ensure the constant exists for the validators
|
5
5
|
|
6
|
-
include ::ActiveAttr::MassAssignmentSecurity
|
7
|
-
include ::ActiveAttr::Model
|
8
|
-
|
9
6
|
# @!attribute [rw] id
|
10
7
|
# @return [Fixnum] the id of the evening
|
11
8
|
# @!attribute [rw] section_id
|
@@ -60,37 +57,103 @@ module Osm
|
|
60
57
|
# @param [Hash] attributes the hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
|
61
58
|
|
62
59
|
|
63
|
-
#
|
64
|
-
# @param [
|
65
|
-
# @param
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
60
|
+
# Get the programme for a given term
|
61
|
+
# @param [Osm::Api] api The api to use to make the request
|
62
|
+
# @param [Osm::Section, Fixnum] 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
|
64
|
+
# @!macro options_get
|
65
|
+
# @return [Array<Osm::Evening>]
|
66
|
+
def self.get_programme(api, section, term, options={})
|
67
|
+
section_id = section.to_i
|
68
|
+
term_id = term.nil? ? Osm::Term.get_current_term_for_section(api, section).id : term.to_i
|
69
|
+
cache_key = ['programme', section_id, term_id]
|
70
|
+
|
71
|
+
if !options[:no_cache] && cache_exist?(api, cache_key) && get_user_permissions(api, section_id)[:programme].include?(:read)
|
72
|
+
return cache_read(api, cache_key)
|
73
|
+
end
|
74
|
+
|
75
|
+
data = api.perform_query("programme.php?action=getProgramme§ionid=#{section_id}&termid=#{term_id}")
|
76
|
+
|
77
|
+
result = Array.new
|
78
|
+
data = {'items'=>[],'activities'=>{}} if data.is_a? Array
|
79
|
+
items = data['items'] || []
|
80
|
+
activities = data['activities'] || {}
|
81
|
+
|
82
|
+
items.each do |item|
|
83
|
+
attributes = {}
|
84
|
+
attributes[:id] = Osm::to_i_or_nil(item['eveningid'])
|
85
|
+
attributes[:section_id] = Osm::to_i_or_nil(item['sectionid'])
|
86
|
+
attributes[:title] = item['title'] || 'Unnamed meeting'
|
87
|
+
attributes[:notes_for_parents] = item['notesforparents'] || ''
|
88
|
+
attributes[:games] = item['games'] || ''
|
89
|
+
attributes[:pre_notes] = item['prenotes'] || ''
|
90
|
+
attributes[:post_notes] = item['postnotes'] || ''
|
91
|
+
attributes[:leaders] = item['leaders'] || ''
|
92
|
+
attributes[:start_time] = item['starttime'].nil? ? nil : item['starttime'][0..4]
|
93
|
+
attributes[:finish_time] = item['endtime'].nil? ? nil : item['endtime'][0..4]
|
94
|
+
attributes[:meeting_date] = Osm::parse_date(item['meetingdate'])
|
95
|
+
|
96
|
+
our_activities = activities[item['eveningid']]
|
97
|
+
attributes[:activities] = Array.new
|
98
|
+
unless our_activities.nil?
|
99
|
+
our_activities.each do |activity_data|
|
100
|
+
attributes[:activities].push Osm::Evening::Activity.new(
|
101
|
+
:activity_id => Osm::to_i_or_nil(activity_data['activityid']),
|
102
|
+
:title => activity_data['title'],
|
103
|
+
:notes => activity_data['notes'],
|
104
|
+
)
|
105
|
+
end
|
84
106
|
end
|
107
|
+
|
108
|
+
result.push new(attributes)
|
85
109
|
end
|
86
110
|
|
87
|
-
|
111
|
+
cache_write(api, cache_key, result)
|
112
|
+
return result
|
88
113
|
end
|
89
114
|
|
90
|
-
|
91
|
-
#
|
92
|
-
|
93
|
-
|
115
|
+
|
116
|
+
# Create an evening in OSM
|
117
|
+
# @param [Osm::Api] api The api to use to make the request
|
118
|
+
# @param [Osm::Section, Fixnum] section or section_id to add the evening to
|
119
|
+
# @param [Date] meeting_date the date of the meeting
|
120
|
+
# @return [Boolean] if the operation suceeded or not
|
121
|
+
def self.create(api, section, meeting_date)
|
122
|
+
section_id = section.to_i
|
123
|
+
api_data = {
|
124
|
+
'meetingdate' => meeting_date.strftime(Osm::OSM_DATE_FORMAT),
|
125
|
+
'sectionid' => section_id,
|
126
|
+
'activityid' => -1
|
127
|
+
}
|
128
|
+
|
129
|
+
data = api.perform_query("programme.php?action=addActivityToProgramme", api_data)
|
130
|
+
|
131
|
+
# The cached programmes for the section will be out of date - remove them
|
132
|
+
Osm::Term.get_for_section(api, section).each do |term|
|
133
|
+
cache_delete(api, ['programme', section_id, term.id])
|
134
|
+
end
|
135
|
+
|
136
|
+
return data.is_a?(Hash) && (data['result'] == 0)
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
# Update an evening in OSM
|
141
|
+
# @param [Osm::Api] api The api to use to make the request
|
142
|
+
# @return [Boolean] if the operation suceeded or not
|
143
|
+
def update(api)
|
144
|
+
raise ObjectIsInvalid, 'evening is invalid' unless valid?
|
145
|
+
|
146
|
+
activities_data = Array.new
|
147
|
+
activities.each do |activity|
|
148
|
+
this_activity = {
|
149
|
+
'activityid' => activity.activity_id,
|
150
|
+
'notes' => activity.notes,
|
151
|
+
}
|
152
|
+
activities_data.push this_activity
|
153
|
+
end
|
154
|
+
activities_data = ActiveSupport::JSON.encode(activities_data)
|
155
|
+
|
156
|
+
api_data = {
|
94
157
|
'eveningid' => id,
|
95
158
|
'sectionid' => section_id,
|
96
159
|
'meetingdate' => meeting_date.strftime(Osm::OSM_DATE_FORMAT),
|
@@ -102,27 +165,39 @@ module Osm
|
|
102
165
|
'postnotes' => post_notes,
|
103
166
|
'games' => games,
|
104
167
|
'leaders' => leaders,
|
105
|
-
'activity' =>
|
168
|
+
'activity' => activities_data,
|
106
169
|
}
|
170
|
+
response = api.perform_query("programme.php?action=editEvening", api_data)
|
171
|
+
|
172
|
+
# The cached programmes for the section will be out of date - remove them
|
173
|
+
Osm::Term.get_for_section(api, section_id).each do |term|
|
174
|
+
self.class.cache_delete(api, ['programme', section_id, term.id]) if term.contains_date?(meeting_date)
|
175
|
+
end
|
176
|
+
|
177
|
+
return response.is_a?(Hash) && (response['result'] == 0)
|
107
178
|
end
|
108
179
|
|
109
180
|
|
110
|
-
|
111
|
-
#
|
112
|
-
#
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
to_save.push this_activity
|
181
|
+
# Get the badge requirements met on a specific evening
|
182
|
+
# @param [Osm::Api] api The api to use to make the request
|
183
|
+
# @!macro options_get
|
184
|
+
# @return [Array<Hash>] hashes ready to pass into the update_register method
|
185
|
+
def get_badge_requirements(api, options={})
|
186
|
+
section = Osm::Section.get(api, section_id)
|
187
|
+
cache_key = ['badge_requirements', section.id, id]
|
188
|
+
|
189
|
+
if !options[:no_cache] && self.class.cache_exist?(api, cache_key) && get_user_permissions(api, section_id)[:programme].include?(:read)
|
190
|
+
return self.class.cache_read(api, cache_key)
|
121
191
|
end
|
122
|
-
|
192
|
+
|
193
|
+
data = api.perform_query("users.php?action=getActivityRequirements&date=#{meeting_date.strftime(Osm::OSM_DATE_FORMAT)}§ionid=#{section.id}§ion=#{section.type}")
|
194
|
+
|
195
|
+
self.class.cache_write(api, cache_key, data)
|
196
|
+
return data
|
123
197
|
end
|
124
198
|
|
125
199
|
|
200
|
+
private
|
126
201
|
class Activity
|
127
202
|
include ::ActiveAttr::MassAssignmentSecurity
|
128
203
|
include ::ActiveAttr::Model
|
@@ -143,22 +218,10 @@ module Osm
|
|
143
218
|
validates_numericality_of :activity_id, :only_integer=>true, :greater_than=>0
|
144
219
|
validates_presence_of :title
|
145
220
|
|
146
|
-
|
147
221
|
# @!method initialize
|
148
222
|
# Initialize a new Evening::Activity
|
149
223
|
# @param [Hash] attributes the hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
|
150
224
|
|
151
|
-
|
152
|
-
# Initialize a new Evening::Activity from api data
|
153
|
-
# @param [Hash] data the hash of data provided by the API
|
154
|
-
def self.from_api(data)
|
155
|
-
new({
|
156
|
-
:activity_id => Osm::to_i_or_nil(data['activityid']),
|
157
|
-
:title => data['title'],
|
158
|
-
:notes => data['notes'],
|
159
|
-
})
|
160
|
-
end
|
161
|
-
|
162
225
|
end # Class Evening::Activity
|
163
226
|
|
164
227
|
end # Class Evening
|
data/lib/osm/event.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
module Osm
|
2
2
|
|
3
|
-
class Event
|
4
|
-
include ::ActiveAttr::MassAssignmentSecurity
|
5
|
-
include ::ActiveAttr::Model
|
3
|
+
class Event < Osm::Model
|
6
4
|
|
7
5
|
# @!attribute [rw] id
|
8
6
|
# @return [Fixnum] the id for the event
|
@@ -22,6 +20,8 @@ module Osm
|
|
22
20
|
# @return [String] notes about the event
|
23
21
|
# @!attribute [rw] archived
|
24
22
|
# @return [Boolean] if the event has been archived
|
23
|
+
# @!attribute [rw] fields
|
24
|
+
# @return [Hash] Keys are the field's id, values are the field names
|
25
25
|
|
26
26
|
attribute :id, :type => Integer
|
27
27
|
attribute :section_id, :type => Integer
|
@@ -32,34 +32,292 @@ module Osm
|
|
32
32
|
attribute :location, :type => String, :default => ''
|
33
33
|
attribute :notes, :type => String, :default => ''
|
34
34
|
attribute :archived, :type => Boolean, :default => false
|
35
|
+
attribute :fields, :default => {}
|
35
36
|
|
36
|
-
attr_accessible :id, :section_id, :name, :start, :finish, :cost, :location, :notes, :archived
|
37
|
+
attr_accessible :id, :section_id, :name, :start, :finish, :cost, :location, :notes, :archived, :fields
|
37
38
|
|
38
39
|
validates_numericality_of :id, :only_integer=>true, :greater_than=>0, :allow_nil => true
|
39
40
|
validates_numericality_of :section_id, :only_integer=>true, :greater_than=>0
|
40
41
|
validates_presence_of :name
|
42
|
+
validates :fields, :hash => {:key_type => String, :value_type => String}
|
41
43
|
|
42
44
|
|
43
45
|
# @!method initialize
|
44
46
|
# Initialize a new Term
|
45
47
|
# @param [Hash] attributes the hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
|
46
48
|
|
47
|
-
|
48
|
-
#
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
49
|
+
|
50
|
+
# Get events for a section
|
51
|
+
# @param [Osm::Api] api The api to use to make the request
|
52
|
+
# @param [Osm::Section, Fixnum] section the section (or its ID) to get the events for
|
53
|
+
# @!macro options_get
|
54
|
+
# @option options [Boolean] :include_archived (optional) if true then archived activities will also be returned
|
55
|
+
# @return [Array<Osm::Event>]
|
56
|
+
def self.get_for_section(api, section, options={})
|
57
|
+
section_id = section.to_i
|
58
|
+
cache_key = ['events', section_id]
|
59
|
+
events = nil
|
60
|
+
|
61
|
+
if !options[:no_cache] && cache_exist?(api, cache_key) && get_user_permissions(api, section_id)[:events].include?(:read)
|
62
|
+
return cache_read(api, cache_key)
|
63
|
+
end
|
64
|
+
|
65
|
+
data = api.perform_query("events.php?action=getEvents§ionid=#{section_id}&showArchived=true")
|
66
|
+
|
67
|
+
events = Array.new
|
68
|
+
unless data['items'].nil?
|
69
|
+
data['items'].each do |item|
|
70
|
+
event_id = Osm::to_i_or_nil(item['eventid'])
|
71
|
+
fields_data = api.perform_query("events.php?action=getEvent§ionid=#{section_id}&eventid=#{event_id}")
|
72
|
+
fields = {}
|
73
|
+
ActiveSupport::JSON.decode(fields_data['config']).each do |field|
|
74
|
+
fields[field['id']] = field['name']
|
75
|
+
end
|
76
|
+
|
77
|
+
event = Osm::Event.new(
|
78
|
+
:id => event_id,
|
79
|
+
:section_id => Osm::to_i_or_nil(item['sectionid']),
|
80
|
+
:name => item['name'],
|
81
|
+
:start => Osm::make_datetime(item['startdate'], item['starttime']),
|
82
|
+
:finish => Osm::make_datetime(item['enddate'], item['endtime']),
|
83
|
+
:cost => item['cost'],
|
84
|
+
:location => item['location'],
|
85
|
+
:notes => item['notes'],
|
86
|
+
:archived => item['archived'].eql?('1'),
|
87
|
+
:fields => fields,
|
88
|
+
)
|
89
|
+
events.push event
|
90
|
+
cache_write(api, ['event', event.id], event)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
cache_write(api, cache_key, events)
|
94
|
+
|
95
|
+
return events if options[:include_archived]
|
96
|
+
return events.reject do |event|
|
97
|
+
event.archived?
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Get an event
|
102
|
+
# @param [Osm::Api] api The api to use to make the request
|
103
|
+
# @param [Osm::Section, Fixnum] section the section (or its ID) to get the events for
|
104
|
+
# @param [Fixnum] event_id the id of the event to get
|
105
|
+
# @!macro options_get
|
106
|
+
# @option options [Boolean] :include_archived (optional) if true then archived activities will also be returned
|
107
|
+
# @return [Osm::Event, nil] the event (or nil if it couldn't be found
|
108
|
+
def self.get(api, section, event_id, options={})
|
109
|
+
section_id = section.to_i
|
110
|
+
cache_key = ['event', event_id]
|
111
|
+
|
112
|
+
if !options[:no_cache] && cache_exist?(api, cache_key) && get_user_permissions(api, section_id)[:events].include?(:read)
|
113
|
+
return cache_read(api, cache_key)
|
114
|
+
end
|
115
|
+
|
116
|
+
events = get_for_section(api, section, options)
|
117
|
+
return nil unless events.is_a? Array
|
118
|
+
|
119
|
+
events.each do |event|
|
120
|
+
return event if event.id == event_id
|
121
|
+
end
|
122
|
+
|
123
|
+
return nil
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
# Create an event in OSM
|
128
|
+
# @param [Osm::Api] api The api to use to make the request
|
129
|
+
# @return [Osm::Event, nil] the created event, nil if failed
|
130
|
+
def self.create(api, parameters)
|
131
|
+
event = new(parameters)
|
132
|
+
raise ObjectIsInvalid, 'event is invalid' unless event.valid?
|
133
|
+
raise Forbidden, 'you do not have permission to write to events for this section' unless get_user_permissions(api, event.section_id)[:events].include?(:write)
|
134
|
+
|
135
|
+
data = api.perform_query("events.php?action=addEvent§ionid=#{event.section_id}", {
|
136
|
+
'name' => event.name,
|
137
|
+
'location' => event.location,
|
138
|
+
'startdate' => event.start.strftime(Osm::OSM_DATE_FORMAT),
|
139
|
+
'enddate' => event.finish.strftime(Osm::OSM_DATE_FORMAT),
|
140
|
+
'cost' => event.cost,
|
141
|
+
'notes' => event.notes,
|
142
|
+
'starttime' => event.start.strftime(Osm::OSM_TIME_FORMAT),
|
143
|
+
'endtime' => event.finish.strftime(Osm::OSM_TIME_FORMAT),
|
144
|
+
})
|
145
|
+
|
146
|
+
# The cached events for the section will be out of date - remove them
|
147
|
+
cache_delete(api, ['events', event.section_id])
|
148
|
+
cache_write(api, ['event', event.id], event)
|
149
|
+
|
150
|
+
if (data.is_a?(Hash) && data.has_key?('id'))
|
151
|
+
event.id = data['id'].to_i
|
152
|
+
return event
|
153
|
+
else
|
154
|
+
return nil
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# Update event in OSM
|
159
|
+
# @param [Osm::Api] api The api to use to make the request
|
160
|
+
# @return [Boolean] wether the update succedded
|
161
|
+
def update(api)
|
162
|
+
raise Forbidden, 'you do not have permission to write to events for this section' unless self.class.get_user_permissions(api, section_id)[:events].include?(:write)
|
163
|
+
|
164
|
+
data = api.perform_query("events.php?action=addEvent§ionid=#{section_id}", {
|
165
|
+
'eventid' => id,
|
166
|
+
'name' => name,
|
167
|
+
'location' => location,
|
168
|
+
'startdate' => start? ? start.strftime(Osm::OSM_DATE_FORMAT) : '',
|
169
|
+
'enddate' => finish? ? finish.strftime(Osm::OSM_DATE_FORMAT) : '',
|
170
|
+
'cost' => cost,
|
171
|
+
'notes' => notes,
|
172
|
+
'starttime' => start? ? start.strftime(Osm::OSM_TIME_FORMAT) : '',
|
173
|
+
'endtime' => finish? ? finish.strftime(Osm::OSM_TIME_FORMAT) : '',
|
174
|
+
})
|
175
|
+
|
176
|
+
# The cached events for the section will be out of date - remove them
|
177
|
+
self.class.cache_delete(api, ['event', id])
|
178
|
+
self.class.cache_delete(api, ['events', section_id])
|
179
|
+
|
180
|
+
return data.is_a?(Hash) && (data['id'].to_i == id)
|
181
|
+
end
|
182
|
+
|
183
|
+
# Delete event from OSM
|
184
|
+
# @param [Osm::Api] api The api to use to make the request
|
185
|
+
# @return [Boolean] wether the delete succedded
|
186
|
+
def delete(api)
|
187
|
+
raise Forbidden, 'you do not have permission to write to events for this section' unless self.class.get_user_permissions(api, section_id)[:events].include?(:write)
|
188
|
+
|
189
|
+
data = api.perform_query("events.php?action=deleteEvent§ionid=#{section_id}&eventid=#{id}")
|
190
|
+
|
191
|
+
# The cached events for the section will be out of date - remove them
|
192
|
+
self.class.cache_delete(api, ['events', section_id])
|
193
|
+
self.class.cache_delete(api, ['event', id])
|
194
|
+
|
195
|
+
return data.is_a?(Hash) ? data['ok'] : false
|
196
|
+
end
|
197
|
+
|
198
|
+
|
199
|
+
# Get event attendance
|
200
|
+
# @param [Osm::Api] api The api to use to make the request
|
201
|
+
# @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
|
202
|
+
# @!macro options_get
|
203
|
+
# @option options [Boolean] :include_archived (optional) if true then archived activities will also be returned
|
204
|
+
# @return [Array<Osm::Event::Attendance>]
|
205
|
+
def get_attendance(api, term=nil, options={})
|
206
|
+
term_id = term.nil? ? Osm::Term.get_current_term_for_section(api, section).id : term.to_i
|
207
|
+
cache_key = ['event_attendance', id]
|
208
|
+
|
209
|
+
if !options[:no_cache] && self.class.cache_exist?(api, cache_key) && self.class.get_user_permissions(api, section_id)[:events].include?(:read)
|
210
|
+
return self.class.cache_read(api, cache_key)
|
211
|
+
end
|
212
|
+
|
213
|
+
data = api.perform_query("events.php?action=getEventAttendance&eventid=#{id}§ionid=#{section_id}&termid=#{term_id}")
|
214
|
+
data = data['items']
|
215
|
+
|
216
|
+
attendance = []
|
217
|
+
data.each_with_index do |item, index|
|
218
|
+
item.merge!({
|
219
|
+
'dob' => item['dob'].nil? ? nil : Osm::parse_date(item['dob'], :ignore_epoch => true),
|
220
|
+
'attending' => item['attending'].eql?('Yes'),
|
221
|
+
})
|
222
|
+
|
223
|
+
attendance.push Osm::Event::Attendance.new(
|
224
|
+
:event => self,
|
225
|
+
:member_id => Osm::to_i_or_nil(item['scoutid']),
|
226
|
+
:grouping_id => Osm::to_i_or_nil(item['patrolid'].eql?('') ? nil : item['patrolid']),
|
227
|
+
:fields => item.select { |key, value|
|
228
|
+
['firstname', 'lastname', 'dob', 'attending'].include?(key) || key.to_s.match(/\Af_\d+\Z/)
|
229
|
+
},
|
230
|
+
:row => index,
|
231
|
+
)
|
232
|
+
end
|
233
|
+
|
234
|
+
self.class.cache_write(api, cache_key, attendance)
|
235
|
+
return attendance
|
236
|
+
end
|
237
|
+
|
238
|
+
|
239
|
+
# Add a field in OSM
|
240
|
+
# @param [Osm::Api] api The api to use to make the request
|
241
|
+
# @param [String] field_label the label for the field to add
|
242
|
+
# @return [Boolean] wether the update succedded
|
243
|
+
def add_field(api, label)
|
244
|
+
raise ArgumentIsInvalid, 'label is invalid' if label.blank?
|
245
|
+
raise Forbidden, 'you do not have permission to write to events for this section' unless self.class.get_user_permissions(api, section_id)[:events].include?(:write)
|
246
|
+
|
247
|
+
data = api.perform_query("events.php?action=addColumn§ionid=#{section_id}&eventid=#{id}", {
|
248
|
+
'columnName' => label
|
60
249
|
})
|
250
|
+
|
251
|
+
# The cached events for the section will be out of date - remove them
|
252
|
+
self.class.cache_delete(api, ['events', section_id])
|
253
|
+
self.class.cache_delete(api, ['event', id])
|
254
|
+
self.class.cache_delete(api, ['event_attendance', id])
|
255
|
+
|
256
|
+
return data.is_a?(Hash) && (data['eventid'].to_i == id)
|
61
257
|
end
|
62
258
|
|
259
|
+
|
260
|
+
|
261
|
+
class Attendance
|
262
|
+
include ::ActiveAttr::MassAssignmentSecurity
|
263
|
+
include ::ActiveAttr::Model
|
264
|
+
|
265
|
+
# @!attribute [rw] member_id
|
266
|
+
# @return [Fixnum] OSM id for the member
|
267
|
+
# @!attribute [rw] grouping__id
|
268
|
+
# @return [Fixnum] OSM id for the grouping the member is in
|
269
|
+
# @!attribute [rw] fields
|
270
|
+
# @return [Hash] Keys are the field's id, values are the field values
|
271
|
+
# @!attribute [rw] row
|
272
|
+
# @return [Fixnum] part of the OSM API
|
273
|
+
|
274
|
+
attribute :row, :type => Integer
|
275
|
+
attribute :member_id, :type => Integer
|
276
|
+
attribute :grouping_id, :type => Integer
|
277
|
+
attribute :fields, :default => {}
|
278
|
+
attribute :event
|
279
|
+
|
280
|
+
attr_accessible :member_id, :grouping_id, :fields, :row, :event
|
281
|
+
|
282
|
+
validates_numericality_of :row, :only_integer=>true, :greater_than_or_equal_to=>0
|
283
|
+
validates_numericality_of :member_id, :only_integer=>true, :greater_than=>0
|
284
|
+
validates_numericality_of :grouping_id, :only_integer=>true, :greater_than_or_equal_to=>-2
|
285
|
+
validates :fields, :hash => {:key_type => String}
|
286
|
+
validates_each :event do |record, attr, value|
|
287
|
+
record.event.valid?
|
288
|
+
end
|
289
|
+
|
290
|
+
|
291
|
+
# @!method initialize
|
292
|
+
# Initialize a new FlexiRecordData
|
293
|
+
# @param [Hash] attributes the hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
|
294
|
+
|
295
|
+
|
296
|
+
# Update event attendance
|
297
|
+
# @param [Osm::Api] api The api to use to make the request
|
298
|
+
# @param [String] field_id the id of the field to update (must be 'attending' or /\Af_\d+\Z/)
|
299
|
+
# @return [Boolean] if the operation suceeded or not
|
300
|
+
def update(api, field_id)
|
301
|
+
raise ArgumentIsInvalid, 'field_id is invalid' unless field_id.match(/\Af_\d+\Z/) || field_id.eql?('attending')
|
302
|
+
raise Forbidden, 'you do not have permission to write to events for this section' unless Osm::Model.get_user_permissions(api, event.section_id)[:events].include?(:write)
|
303
|
+
|
304
|
+
data = api.perform_query("events.php?action=updateScout", {
|
305
|
+
'scoutid' => member_id,
|
306
|
+
'column' => field_id,
|
307
|
+
'value' => !field_id.eql?('attending') ? fields[field_id] : (fields['attending'] ? 'Yes' : 'No'),
|
308
|
+
'sectionid' => event.section_id,
|
309
|
+
'row' => row,
|
310
|
+
'eventid' => event.id,
|
311
|
+
})
|
312
|
+
|
313
|
+
# The cached event attedance will be out of date
|
314
|
+
Osm::Model.cache_delete(api, ['event_attendance', event.id])
|
315
|
+
|
316
|
+
return data.is_a?(Hash)
|
317
|
+
end
|
318
|
+
|
319
|
+
end # Class Attendance
|
320
|
+
|
63
321
|
end # Class Event
|
64
322
|
|
65
323
|
end # Module
|