osm 0.0.25 → 0.0.26

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ ## Version 0.0.26
2
+
3
+ * Register - Update attendance
4
+ * Add api.get\_badge\_requirements\_for\_evening
5
+ * Add api.update\_register
6
+ * Event:
7
+ * Add api.ceate\_event
8
+ * Add api.update\_event
9
+ * Add api.delete\_event
10
+ * Add api.add\_event\_field
11
+ * Event attendance:
12
+ * Add api.get\_event
13
+ * Add api.get\_event\_fields
14
+ * Add api.get\_event\_attendance
15
+ * Add api.update\_event\_attendance
16
+ * Fix "uninitialized constant Osm::Api::HTTParty"
17
+
1
18
  ## Version 0.0.25
2
19
 
3
20
  * FlexiRecordData, move these attributes to the fields hash:
data/README.md CHANGED
@@ -71,9 +71,13 @@ however it should be noted that when the OSM API adds a feature it can be diffic
71
71
  * Activity
72
72
  * API Access
73
73
  * API Access for our app
74
+ * Badge requirements for evening
74
75
  * Due Badges
75
76
  * Evening
77
+ * Event
76
78
  * Events
79
+ * Event Fields
80
+ * Event Attendance
77
81
  * Flexi Record Data
78
82
  * Flexi Record Structure
79
83
  * Groupings (e.g. Sixes, Patrols)
@@ -91,9 +95,16 @@ however it should be noted that when the OSM API adds a feature it can be diffic
91
95
 
92
96
  ### Update
93
97
  * Evening
98
+ * Event
99
+ * Event Attendance
100
+ * Register attendance
94
101
 
95
102
  ### Create
96
103
  * Evening
104
+ * Event
105
+
106
+ ### Delete
107
+ * Event
97
108
 
98
109
  ### Actions
99
110
  * Authorise an app to use the API on a user's behalf
@@ -103,26 +114,18 @@ however it should be noted that when the OSM API adds a feature it can be diffic
103
114
 
104
115
  * Badges:
105
116
  * Which requirements each member has met:
106
- * Retreive
107
- * Update
108
- * Retrieve details for each badge (stock, short column names etc.)
109
- * Retreival of leader access
110
- * Register - Update attendance
117
+ * Retreive [issue 21]
118
+ * Update [issue 22]
119
+ * Retrieve details for each badge (stock, short column names etc.) [issue 20]
111
120
  * Flexi Records:
112
- * Update data
113
- * Add Column
114
- * Events:
115
- * Attendance (everything)
116
- * Add column
117
- * Create
118
- * Update
121
+ * Update data [issue 23]
122
+ * Add Column [issue 24]
119
123
  * Member:
120
- * Update
121
- * Add
122
- * Delete
124
+ * Update [issue 33]
125
+ * Add [issue 34]
126
+ * Add activity to programme [issue 35]
127
+ * Delete Evening [issue 36]
123
128
  * Update Activity
124
- * Add activity to programme
125
- * Delete Evening
126
129
  * Gift aid (everything)
127
130
  * Finances (Everything)
128
131
  * SMS:
data/lib/osm/api.rb CHANGED
@@ -326,6 +326,25 @@ module Osm
326
326
  return result
327
327
  end
328
328
 
329
+ # Get the badge requirements met on a specific evening
330
+ # @param [Osm::Section] section the section to get the pbadge requirements for
331
+ # @param [Osm::Evening, DateTime, Date] evening the evening (or its date) to get the badge requirements for
332
+ # @!macro options_get
333
+ # @return [Array<Hash>] hashes ready to pass into the update_register method
334
+ def get_badge_requirements_for_evening(section, evening, options={})
335
+ evening = evening.meeting_date if evening.is_a?(Osm::Evening)
336
+ cache_key = "badge_requirements-#{section.id}-#{evening.strftime('%Y%m%d')}"
337
+
338
+ if !options[:no_cache] && cache_exist?(cache_key) && self.user_can_access?(:programme, section.id)
339
+ return cache_read(cache_key)
340
+ end
341
+
342
+ data = perform_query("users.php?action=getActivityRequirements&date=#{evening.strftime(Osm::OSM_DATE_FORMAT)}&sectionid=#{section.id}&section=#{section.type}")
343
+
344
+ cache_write(cache_key, data, :expires_in => @@default_cache_ttl)
345
+ return data
346
+ end
347
+
329
348
  # Get activity details
330
349
  # @param [Fixnum] activity_id the activity ID
331
350
  # @param [Fixnum] version the version of the activity to retreive, if nil the latest version will be assumed
@@ -448,21 +467,22 @@ module Osm
448
467
  cache_key = "events-#{section_id}"
449
468
  events = nil
450
469
 
451
- if !options[:no_cache] && cache_exist?(cache_key) && self.user_can_access?(:programme, section_id, api_data)
452
- events = cache_read(cache_key)
453
- else
470
+ if !options[:no_cache] && cache_exist?(cache_key) && self.user_can_access?(:events, section_id, api_data)
471
+ return cache_read(cache_key)
472
+ end
454
473
 
455
- data = perform_query("events.php?action=getEvents&sectionid=#{section_id}&showArchived=true", api_data)
474
+ data = perform_query("events.php?action=getEvents&sectionid=#{section_id}&showArchived=true", api_data)
456
475
 
457
- events = Array.new
458
- unless data['items'].nil?
459
- data['items'].each do |item|
460
- events.push Osm::Event.from_api(item)
461
- end
476
+ events = Array.new
477
+ unless data['items'].nil?
478
+ data['items'].each do |item|
479
+ event = Osm::Event.from_api(item)
480
+ events.push event
481
+ cache_write("event-#{section_id}-#{event.id}", event, :expires_in => @@default_cache_ttl)
462
482
  end
463
- self.user_can_access :programme, section_id, api_data
464
- cache_write(cache_key, events, :expires_in => @@default_cache_ttl)
465
483
  end
484
+ self.user_can_access :events, section_id, api_data
485
+ cache_write(cache_key, events, :expires_in => @@default_cache_ttl)
466
486
 
467
487
  return events if options[:include_archived]
468
488
  return events.reject do |event|
@@ -470,6 +490,82 @@ module Osm
470
490
  end
471
491
  end
472
492
 
493
+ # Get event
494
+ # @param [Osm::Section, Fixnum] section the section (or its ID) to get the events for
495
+ # @param [Fixnum] event_id the id of the event to get
496
+ # @!macro options_get
497
+ # @option options [Boolean] :include_archived (optional) if true then archived activities will also be returned
498
+ # @return [Osm::Event, nil] the event (or nil if it couldn't be found
499
+ def get_event(section, event_id, options={})
500
+ section_id = id_for_section(section)
501
+ cache_key = "event-#{section_id}-#{event_id}"
502
+
503
+ if !options[:no_cache] && cache_exist?(cache_key) && self.user_can_access?(:events, section_id)
504
+ return cache_read(cache_key)
505
+ end
506
+
507
+ events = get_events(section, options)
508
+ return nil unless events.is_a? Array
509
+
510
+ events.each do |event|
511
+ return event if event.id == event_id
512
+ end
513
+
514
+ return nil
515
+ end
516
+
517
+ # Get event fields
518
+ # @param [Osm::Event, Fixnum] event the event to get the fieldss for
519
+ # @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
520
+ # @!macro options_get
521
+ # @option options [Boolean] :include_archived (optional) if true then archived activities will also be returned
522
+ # @return [Hash] fields of data assigned to the event (keys is the id, value is the field names)
523
+ def get_event_fields(event, term=nil, options={})
524
+ term_id = id_for_term(term, event.section_id)
525
+ cache_key = "event-fields-#{event.section_id}-#{event.id}"
526
+
527
+ if !options[:no_cache] && cache_exist?(cache_key) && self.user_can_access?(:events, event.section_id)
528
+ return cache_read(cache_key)
529
+ end
530
+
531
+ data = perform_query("events.php?action=getEvent&sectionid=#{event.section_id}&eventid=#{event.id}")
532
+
533
+ fields = {}
534
+ ActiveSupport::JSON.decode(data['config']).each do |field|
535
+ fields[field['id']] = field['name']
536
+ end
537
+
538
+ self.user_can_access :events, event.section_id
539
+ cache_write(cache_key, fields, :expires_in => @@default_cache_ttl)
540
+ return fields
541
+ end
542
+
543
+ # Get event attendance
544
+ # @param [Osm::Event] event the event to get the fieldss for
545
+ # @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
546
+ # @!macro options_get
547
+ # @option options [Boolean] :include_archived (optional) if true then archived activities will also be returned
548
+ # @return [Hash] fields of data assigned to the event (keys is the id, value is the field names)
549
+ def get_event_attendance(event, term=nil, options={})
550
+ term_id = id_for_term(term, event.section_id)
551
+ cache_key = "event-attendance-#{event.section_id}-#{event.id}"
552
+
553
+ if !options[:no_cache] && cache_exist?(cache_key) && self.user_can_access?(:events, event.section_id)
554
+ return cache_read(cache_key)
555
+ end
556
+
557
+ data = perform_query("events.php?action=getEventAttendance&eventid=#{event.id}&sectionid=#{event.section_id}&termid=#{term_id}")
558
+ data = data['items']
559
+
560
+ to_return = []
561
+ data.each_with_index do |item, index|
562
+ to_return.push Osm::EventAttendance.from_api(item, index)
563
+ end
564
+ self.user_can_access :events, event.section_id
565
+ cache_write(cache_key, to_return, :expires_in => @@default_cache_ttl/2)
566
+ return to_return
567
+ end
568
+
473
569
  # Get due badges
474
570
  # @param [Osm::Section, Fixnum] section the section (or its ID) to get the due badges for
475
571
  # @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
@@ -661,6 +757,93 @@ module Osm
661
757
  return data.is_a?(Hash) && (data['result'] == 0)
662
758
  end
663
759
 
760
+ # Create an event in OSM
761
+ # @param [Osm::Event] event the event to add to OSM
762
+ # @return [Fixnum, nil] the id of the created event, nil if failed
763
+ def create_event(event)
764
+ raise ArgumentIsInvalid, 'event is invalid' unless event.valid?
765
+
766
+ data = perform_query("events.php?action=addEvent&sectionid=#{event.section_id}", {
767
+ 'name' => event.name,
768
+ 'location' => event.location,
769
+ 'startdate' => event.start.strftime(Osm::OSM_DATE_FORMAT),
770
+ 'enddate' => event.finish.strftime(Osm::OSM_DATE_FORMAT),
771
+ 'cost' => event.cost,
772
+ 'notes' => event.notes,
773
+ 'starttime' => event.start.strftime(Osm::OSM_TIME_FORMAT),
774
+ 'endtime' => event.finish.strftime(Osm::OSM_TIME_FORMAT),
775
+ })
776
+
777
+ # The cached events for the section will be out of date - remove them
778
+ get_events(event.section_id).each do |item|
779
+ cache_delete("event-#{item.section_id}-#{item.id}")
780
+ end
781
+ cache_delete("events-#{event.section_id}")
782
+
783
+ return data.is_a?(Hash) ? data['id'] : nil
784
+ end
785
+
786
+ # Update an event in OSM
787
+ # @param [Osm::Event] event the event to update in OSM
788
+ # @return [Boolean] wether the update succedded
789
+ def update_event(event)
790
+ raise ArgumentIsInvalid, 'event is invalid' unless event.valid?
791
+
792
+ data = perform_query("events.php?action=addEvent&sectionid=#{event.section_id}", {
793
+ 'eventid' => event.id,
794
+ 'name' => event.name,
795
+ 'location' => event.location,
796
+ 'startdate' => event.start? ? event.start.strftime(Osm::OSM_DATE_FORMAT) : '',
797
+ 'enddate' => event.finish? ? event.finish.strftime(Osm::OSM_DATE_FORMAT) : '',
798
+ 'cost' => event.cost,
799
+ 'notes' => event.notes,
800
+ 'starttime' => event.start? ? event.start.strftime(Osm::OSM_TIME_FORMAT) : '',
801
+ 'endtime' => event.finish? ? event.finish.strftime(Osm::OSM_TIME_FORMAT) : '',
802
+ })
803
+
804
+ # The cached events for the section will be out of date - remove them
805
+ get_events(event.section_id).each do |item|
806
+ cache_delete("event-#{item.section_id}-#{item.id}")
807
+ end
808
+ cache_delete("events-#{event.section_id}")
809
+
810
+ return data.is_a?(Hash) && (data['id'].to_i == event.id)
811
+ end
812
+
813
+ # Delete an event from OSM
814
+ # @param [Osm::Event] event the event to delete from OSM
815
+ # @return [Boolean] wether the delete succedded
816
+ def delete_event(event)
817
+ raise ArgumentIsInvalid, 'event is invalid' unless event.valid?
818
+
819
+ data = perform_query("events.php?action=deleteEvent&sectionid=#{event.section_id}&eventid=#{event.id}", {})
820
+
821
+ # The cached events for the section will be out of date - remove them
822
+ cache_delete("event-#{event.section_id}-#{event.id}")
823
+ cache_delete("events-#{event.section_id}")
824
+
825
+ return data.is_a?(Hash) ? data['ok'] : false
826
+ end
827
+
828
+ # Add a field to an Event in OSM
829
+ # @param [Osm::Event] event the event to update in OSM
830
+ # @param [String] field_label the label for the field to add
831
+ # @return [Boolean] wether the update succedded
832
+ def add_event_field(event, field_label)
833
+ raise ArgumentIsInvalid, 'event is invalid' unless event.valid?
834
+ raise ArgumentIsInvalid, 'field_label is invalid' if field_label.blank?
835
+
836
+ data = perform_query("events.php?action=addColumn&sectionid=#{event.section_id}&eventid=#{event.id}", {
837
+ 'columnName' => field_label
838
+ })
839
+
840
+ # The cached events for the section will be out of date - remove them
841
+ cache_delete("event-fields-#{event.section_id}-#{event.id}")
842
+ cache_delete("event-attendance-#{event.section_id}-#{event.id}")
843
+
844
+ return data.is_a?(Hash) && (data['eventid'].to_i == event.id)
845
+ end
846
+
664
847
  # Create a term in OSM
665
848
  # @param [Hash] options - the configuration of the new term
666
849
  # @option options [Osm::Section, Fixnum] :section (required) section or section_id to add the term to
@@ -711,6 +894,42 @@ module Osm
711
894
  return response.is_a?(Hash) && (response['result'] == 0)
712
895
  end
713
896
 
897
+
898
+ # Update register for an evening in OSM
899
+ # @param [Hash] data
900
+ # @option data [Osm::Section] :section the section to update the register for
901
+ # @option data [Osm::Term, Fixnum, nil] :term the term (or its ID) to get the register for, passing nil causes the current term to be used
902
+ # @option data [Osm::Evening, DateTime, Date] :evening the evening to update the register on
903
+ # @option data [String] :attendance what to mark the attendance as, one of "Yes", "No" or "Absent"
904
+ # @option data [Fixnum, Array<Fixnum>, Osm::Member, Array<Osm::Member>] :members the members (or their ids) to update
905
+ # @option data [Array<Hash>] :completed_badge_requirements (optional) the badge requirements to mark as completed, selected from the Hash returned by the get_badge_requirements_for_evening method
906
+ # @return [Boolean] wether the update succedded
907
+ def update_register(data={})
908
+ raise ArgumentIsInvalid, ':attendance is invalid' unless ['Yes', 'No', 'Absent'].include?(data[:attendance])
909
+ raise ArgumentIsInvalid, ':section is missing' if data[:section].nil?
910
+ raise ArgumentIsInvalid, ':evening is missing' if data[:evening].nil?
911
+ raise ArgumentIsInvalid, ':members is missing' if data[:members].nil?
912
+
913
+ term_id = id_for_term(data[:term], data[:section])
914
+
915
+ data[:members] = [data[:members]] unless data[:members].is_a?(Array) # Make sure it's an Array
916
+ data[:members] = data[:members].map{ |member| (member.is_a?(Fixnum) ? member : member.id).to_s } # Make sure it's an Array of Strings
917
+
918
+ response = perform_query("users.php?action=registerUpdate&sectionid=#{data[:section].id}&termid=#{term_id}", {
919
+ 'scouts' => data[:members].inspect,
920
+ 'selectedDate' => data[:evening].strftime(Osm::OSM_DATE_FORMAT),
921
+ 'present' => data[:attendance],
922
+ 'section' => data[:section].type,
923
+ 'sectionid' => data[:section].id,
924
+ 'completedBadges' => (data[:completed_badge_requirements] || []).to_json
925
+ })
926
+
927
+ # The cached attendance will be out of date - remove them
928
+ cache_delete("register-#{data[:section].id}-#{term_id}")
929
+
930
+ return response.is_a?(Array)
931
+ end
932
+
714
933
  # Update a term in OSM
715
934
  # @param [Osm::Term] term the term to update
716
935
  # @return [Boolean] if the operation suceeded or not
@@ -725,6 +944,31 @@ module Osm
725
944
 
726
945
  return data.is_a?(Hash) && data['terms'].is_a?(Hash)
727
946
  end
947
+
948
+ # Update event attendance
949
+ # @param [Osm::Event] event the event to update the attendance of
950
+ # @param [Osm::EventAttendance] event_attendance the attendance record to update
951
+ # @param [String] field_id the id of the field to update (must be 'attending' or /\Af_\d+\Z/)
952
+ # @return [Boolean] if the operation suceeded or not
953
+ def update_event_attendance(event, event_attendance, field_id)
954
+ raise ArgumentIsInvalid, 'event is invalid' unless event.valid?
955
+ raise ArgumentIsInvalid, 'event_attendance is invalid' unless event_attendance.valid?
956
+ raise ArgumentIsInvalid, 'field_id is invalid' unless field_id.match(/\Af_\d+\Z/) || field_id.eql?('attending')
957
+
958
+ data = perform_query("events.php?action=updateScout", {
959
+ 'scoutid' => event_attendance.member_id,
960
+ 'column' => field_id,
961
+ 'value' => !field_id.eql?('attending') ? event_attendance.fields[field_id] : (event_attendance.fields['attending'] ? 'Yes' : 'No'),
962
+ 'sectionid' => event.section_id,
963
+ 'row' => event_attendance.row,
964
+ 'eventid' => event.id,
965
+ })
966
+
967
+ # The cached event attedance will be out of date
968
+ cache_delete("event-attendance-#{event.section_id}-#{event.id}")
969
+
970
+ return data.is_a?(Hash)
971
+ end
728
972
 
729
973
 
730
974
 
data/lib/osm/event.rb CHANGED
@@ -21,6 +21,7 @@ module Osm
21
21
  # @!attribute [rw] notes
22
22
  # @return [String] notes about the event
23
23
  # @!attribute [rw] archived
24
+ # @return [Boolean] if the event has been archived
24
25
 
25
26
  attribute :id, :type => Integer
26
27
  attribute :section_id, :type => Integer
@@ -34,7 +35,7 @@ module Osm
34
35
 
35
36
  attr_accessible :id, :section_id, :name, :start, :finish, :cost, :location, :notes, :archived
36
37
 
37
- validates_numericality_of :id, :only_integer=>true, :greater_than=>0
38
+ validates_numericality_of :id, :only_integer=>true, :greater_than=>0, :allow_nil => true
38
39
  validates_numericality_of :section_id, :only_integer=>true, :greater_than=>0
39
40
  validates_presence_of :name
40
41
 
@@ -55,7 +56,7 @@ module Osm
55
56
  :cost => data['cost'],
56
57
  :location => data['location'],
57
58
  :notes => data['notes'],
58
- :archived => data['archived'].eql?('1')
59
+ :archived => data['archived'].eql?('1'),
59
60
  })
60
61
  end
61
62
 
@@ -0,0 +1,55 @@
1
+ module Osm
2
+
3
+ class EventAttendance
4
+ include ::ActiveAttr::MassAssignmentSecurity
5
+ include ::ActiveAttr::Model
6
+
7
+ # @!attribute [rw] member_id
8
+ # @return [Fixnum] OSM id for the member
9
+ # @!attribute [rw] grouping__id
10
+ # @return [Fixnum] OSM id for the grouping the member is in
11
+ # @!attribute [rw] fields
12
+ # @return [Hash] Keys are the field's id, values are the field values
13
+ # @!attribute [rw] row
14
+ # @return [Fixnum] part of the OSM API
15
+
16
+ attribute :row, :type => Integer
17
+ attribute :member_id, :type => Integer
18
+ attribute :grouping_id, :type => Integer
19
+ attribute :fields, :default => {}
20
+
21
+ attr_accessible :member_id, :grouping_id, :fields, :row
22
+
23
+ validates_numericality_of :row, :only_integer=>true, :greater_than_or_equal_to=>0
24
+ validates_numericality_of :member_id, :only_integer=>true, :greater_than=>0
25
+ validates_numericality_of :grouping_id, :only_integer=>true, :greater_than_or_equal_to=>-2
26
+ validates :fields, :hash => {:key_type => String}
27
+
28
+
29
+ # @!method initialize
30
+ # Initialize a new FlexiRecordData
31
+ # @param [Hash] attributes the hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
32
+
33
+
34
+ # Initialize a new FlexiRecordData from api data
35
+ # @param [Hash] data the hash of data provided by the API
36
+ # @param [Fixnum] row part of the OSM API
37
+ def self.from_api(data, row)
38
+ data.merge!({
39
+ 'dob' => data['dob'].nil? ? nil : Osm::parse_date(data['dob'], :ignore_epoch => true),
40
+ 'attending' => data['attending'].eql?('Yes'),
41
+ })
42
+
43
+ new({
44
+ :member_id => Osm::to_i_or_nil(data['scoutid']),
45
+ :grouping_id => Osm::to_i_or_nil(data['patrolid'].eql?('') ? nil : data['patrolid']),
46
+ :fields => data.select { |key, value|
47
+ ['firstname', 'lastname', 'dob', 'attending'].include?(key) || key.to_s.match(/\Af_\d+\Z/)
48
+ },
49
+ :row => row,
50
+ })
51
+ end
52
+
53
+ end # Class EventAttendance
54
+
55
+ end # Module
@@ -9,7 +9,7 @@ module Osm
9
9
  # @!attribute [rw] grouping__id
10
10
  # @return [Fixnum] OSM id for the grouping the member is in
11
11
  # @!attribute [rw] fields
12
- # @return [Hash] Keys are the field'd id, values are the field values
12
+ # @return [Hash] Keys are the field's id, values are the field values
13
13
 
14
14
  attribute :member_id, :type => Integer
15
15
  attribute :grouping_id, :type => Integer
@@ -41,7 +41,7 @@ module Osm
41
41
  :member_id => Osm::to_i_or_nil(data['scoutid']),
42
42
  :grouping_id => Osm::to_i_or_nil(data['patrolid'].eql?('') ? nil : data['patrolid']),
43
43
  :fields => data.select { |key, value|
44
- ['firstname', 'lastname', 'dob', 'total', 'completed', 'age'].include?(key) || key.to_s.match(/^f_\d+/)
44
+ ['firstname', 'lastname', 'dob', 'total', 'completed', 'age'].include?(key) || key.to_s.match(/\Af_\d+\Z/)
45
45
  }
46
46
  })
47
47
  end
data/lib/osm.rb CHANGED
@@ -1,9 +1,14 @@
1
1
  require 'active_attr'
2
+ require 'active_support'
3
+ require 'active_model'
2
4
  require 'date'
5
+ require 'httparty'
6
+
3
7
 
4
8
  module Osm
5
9
  OSM_EPOCH_S = '1970-01-01'
6
10
  OSM_DATE_FORMAT = '%Y-%m-%d'
11
+ OSM_TIME_FORMAT = '%H:%M:%S'
7
12
  OSM_DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S'
8
13
  OSM_TIME_REGEX = /\A(?:[0-1][0-9]|2[0-3]):[0-5][0-9]\Z/
9
14
  OSM_DATE_REGEX = /\A\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])\Z/
@@ -59,6 +64,16 @@ module Osm
59
64
  end
60
65
  end
61
66
 
67
+ def self.parse_date_time(date_time)
68
+ return nil if date_time.nil? || date_time.empty?
69
+ begin
70
+ return DateTime.strptime((date_time), OSM_DATETIME_FORMAT)
71
+ rescue ArgumentError
72
+ return nil
73
+ end
74
+ end
75
+
76
+
62
77
  def self.parse_date(date, options={})
63
78
  return nil if date.nil? || date.empty? || (date.eql?(OSM_EPOCH_S) && !options[:ignore_epoch])
64
79
  begin
data/spec/osm/api_spec.rb CHANGED
@@ -346,6 +346,165 @@ describe "API" do
346
346
  events[0].id.should == 1
347
347
  end
348
348
 
349
+ it "Fetch an event" do
350
+ body = {
351
+ 'identifier' => 'eventid',
352
+ 'label' => 'name',
353
+ 'items' => [{
354
+ 'eventid' => '2',
355
+ 'name' => 'An Event',
356
+ 'startdate' => '2001-02-03',
357
+ 'enddate' => nil,
358
+ 'starttime' => '00:00:00',
359
+ 'endtime' => '00:00:00',
360
+ 'cost' => '0.00',
361
+ 'location' => '',
362
+ 'notes' => '',
363
+ 'sectionid' => 1,
364
+ 'googlecalendar' => nil,
365
+ 'archived' => '0'
366
+ }]
367
+ }
368
+ FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/events.php?action=getEvents&sectionid=1&showArchived=true", :body => body.to_json)
369
+ event = Osm::Api.new('1', '2').get_event(1, 2)
370
+ event.id.should == 2
371
+ end
372
+
373
+ it "Fetch an event's fields" do
374
+ events_body = {
375
+ 'identifier' => 'eventid',
376
+ 'label' => 'name',
377
+ 'items' => [{
378
+ 'eventid' => '2',
379
+ 'name' => 'An Event',
380
+ 'startdate' => '2001-02-03',
381
+ 'enddate' => nil,
382
+ 'starttime' => '00:00:00',
383
+ 'endtime' => '00:00:00',
384
+ 'cost' => '0.00',
385
+ 'location' => '',
386
+ 'notes' => '',
387
+ 'sectionid' => 1,
388
+ 'googlecalendar' => nil,
389
+ 'archived' => '0'
390
+ }]
391
+ }
392
+ fields_body = {
393
+ 'config' => '[{"id":"f_1","name":"Field 1"}]'
394
+ }
395
+
396
+ FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/events.php?action=getEvents&sectionid=1&showArchived=true", :body => events_body.to_json)
397
+ FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/events.php?action=getEvent&sectionid=1&eventid=2", :body => fields_body.to_json)
398
+ api = Osm::Api.new('1', '2')
399
+
400
+ fields = api.get_event_fields(api.get_event(1, 2), 3)
401
+ fields.should == {'f_1' => 'Field 1'}
402
+ end
403
+
404
+ it "Fetch an event's attendance" do
405
+ events_body = {
406
+ 'identifier' => 'eventid',
407
+ 'label' => 'name',
408
+ 'items' => [{
409
+ 'eventid' => '2',
410
+ 'name' => 'An Event',
411
+ 'startdate' => '2001-02-03',
412
+ 'enddate' => nil,
413
+ 'starttime' => '00:00:00',
414
+ 'endtime' => '00:00:00',
415
+ 'cost' => '0.00',
416
+ 'location' => '',
417
+ 'notes' => '',
418
+ 'sectionid' => 1,
419
+ 'googlecalendar' => nil,
420
+ 'archived' => '0'
421
+ }]
422
+ }
423
+ attendance_body = {
424
+ 'identifier' => 'scoutid',
425
+ 'eventid' => '2',
426
+ 'items' => [
427
+ {
428
+ 'scoutid' => '1',
429
+ 'attending' => 'Yes',
430
+ 'firstname' => 'First',
431
+ 'lastname' => 'Last',
432
+ 'dob' => '1980-01-02',
433
+ 'patrolid' => '2',
434
+ 'f_1' => '',
435
+ }
436
+ ]
437
+ }
438
+
439
+ FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/events.php?action=getEvents&sectionid=1&showArchived=true", :body => events_body.to_json)
440
+ FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/events.php?action=getEventAttendance&eventid=2&sectionid=1&termid=3", :body => attendance_body.to_json)
441
+ api = Osm::Api.new('1', '2')
442
+
443
+ attendance = api.get_event_attendance(api.get_event(1, 2), 3)
444
+ attendance.is_a?(Array).should be_true
445
+ end
446
+
447
+ it "Update an event's attendance" do
448
+ events_body = {
449
+ 'identifier' => 'eventid',
450
+ 'label' => 'name',
451
+ 'items' => [{
452
+ 'eventid' => '2',
453
+ 'name' => 'An Event',
454
+ 'startdate' => '2001-02-03',
455
+ 'enddate' => nil,
456
+ 'starttime' => '00:00:00',
457
+ 'endtime' => '00:00:00',
458
+ 'cost' => '0.00',
459
+ 'location' => '',
460
+ 'notes' => '',
461
+ 'sectionid' => 1,
462
+ 'googlecalendar' => nil,
463
+ 'archived' => '0'
464
+ }]
465
+ }
466
+ attendance_body = {
467
+ 'identifier' => 'scoutid',
468
+ 'eventid' => '2',
469
+ 'items' => [
470
+ {
471
+ 'scoutid' => '1',
472
+ 'attending' => 'Yes',
473
+ 'firstname' => 'First',
474
+ 'lastname' => 'Last',
475
+ 'dob' => '1980-01-02',
476
+ 'patrolid' => '2',
477
+ 'f_1' => '',
478
+ }
479
+ ]
480
+ }
481
+
482
+ FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/events.php?action=getEvents&sectionid=1&showArchived=true", :body => events_body.to_json)
483
+ FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/events.php?action=getEventAttendance&eventid=2&sectionid=1&termid=3", :body => attendance_body.to_json)
484
+
485
+ api = Osm::Api.new('1', '2')
486
+ e = api.get_event(1, 2)
487
+ ea = api.get_event_attendance(e, 3)[0]
488
+ ea.fields['f_1'] = 'TEST'
489
+
490
+ HTTParty.should_receive(:post).with(
491
+ "https://www.onlinescoutmanager.co.uk/events.php?action=updateScout",
492
+ {:body => {
493
+ 'scoutid' => 1,
494
+ 'column' => 'f_1',
495
+ 'value' => 'TEST',
496
+ 'sectionid' => 1,
497
+ 'row' => 0,
498
+ 'eventid' => 2,
499
+ 'apiid' => '1',
500
+ 'token' => 'API TOKEN',
501
+ 'userid' => '1',
502
+ 'secret' => '2',
503
+ }}
504
+ ) { DummyHttpResult.new(:response=>{:code=>'200', :body=>'{}'}) }
505
+ api.update_event_attendance(e, ea, 'f_1').should be_true
506
+ end
507
+
349
508
  it "Fetch events for a section honoring archived option" do
350
509
  body = {
351
510
  'identifier' => 'eventid',
@@ -401,6 +560,17 @@ describe "API" do
401
560
  end
402
561
 
403
562
 
563
+ it "Fetch badge requirements for an evening" do
564
+ badges_body = [{'a'=>'a'},{'a'=>'A'}]
565
+ FakeWeb.register_uri(:post, 'https://www.onlinescoutmanager.co.uk/users.php?action=getActivityRequirements&date=2000-01-02&sectionid=3&section=cubs', :body => badges_body.to_json)
566
+
567
+ section = Osm::Section.new(:id => 3, :type => :cubs)
568
+ evening = Date.new(2000, 1, 2)
569
+
570
+ Osm::Api.new('1', '2').get_badge_requirements_for_evening(section, evening).should == badges_body
571
+ end
572
+
573
+
404
574
  it "Fetch badge stock levels for a section" do
405
575
  badges_body = {
406
576
  'stock' => {
@@ -587,6 +757,217 @@ describe "API" do
587
757
  end
588
758
 
589
759
 
760
+ it "Create an event (succeded)" do
761
+ url = 'https://www.onlinescoutmanager.co.uk/events.php?action=addEvent&sectionid=1'
762
+ post_data = {
763
+ 'apiid' => @api_config[:api_id],
764
+ 'token' => @api_config[:api_token],
765
+ 'userid' => 'user',
766
+ 'secret' => 'secret',
767
+ 'name' => 'Test event',
768
+ 'startdate' => '2000-01-02',
769
+ 'enddate' => '2001-02-03',
770
+ 'starttime' => '03:04:05',
771
+ 'endtime' => '04:05:06',
772
+ 'cost' => '1.23',
773
+ 'location' => 'Somewhere',
774
+ 'notes' => 'none'
775
+ }
776
+
777
+ api = Osm::Api.new('user', 'secret')
778
+ api.stub(:get_events) { [] }
779
+ HTTParty.should_receive(:post).with(url, {:body => post_data}) { DummyHttpResult.new(:response=>{:code=>'200', :body=>'{"id":2}'}) }
780
+
781
+ api.create_event(Osm::Event.new({
782
+ :section_id => 1,
783
+ :name => 'Test event',
784
+ :start => DateTime.new(2000, 01, 02, 03, 04, 05),
785
+ :finish => DateTime.new(2001, 02, 03, 04, 05, 06),
786
+ :cost => '1.23',
787
+ :location => 'Somewhere',
788
+ :notes => 'none'
789
+ })).should == 2
790
+ end
791
+
792
+ it "Create an event (failed)" do
793
+ url = 'https://www.onlinescoutmanager.co.uk/events.php?action=addEvent&sectionid=1'
794
+ post_data = {
795
+ 'apiid' => @api_config[:api_id],
796
+ 'token' => @api_config[:api_token],
797
+ 'userid' => 'user',
798
+ 'secret' => 'secret',
799
+ 'name' => 'Test event',
800
+ 'startdate' => '2000-01-02',
801
+ 'enddate' => '2001-02-03',
802
+ 'starttime' => '03:04:05',
803
+ 'endtime' => '04:05:06',
804
+ 'cost' => '1.23',
805
+ 'location' => 'Somewhere',
806
+ 'notes' => 'none'
807
+ }
808
+
809
+ api = Osm::Api.new('user', 'secret')
810
+ api.stub(:get_events) { [] }
811
+ HTTParty.should_receive(:post).with(url, {:body => post_data}) { DummyHttpResult.new(:response=>{:code=>'200', :body=>'{}'}) }
812
+
813
+ api.create_event(Osm::Event.new({
814
+ :section_id => 1,
815
+ :name => 'Test event',
816
+ :start => DateTime.new(2000, 01, 02, 03, 04, 05),
817
+ :finish => DateTime.new(2001, 02, 03, 04, 05, 06),
818
+ :cost => '1.23',
819
+ :location => 'Somewhere',
820
+ :notes => 'none'
821
+ })).should be_nil
822
+ end
823
+
824
+ it "Update an event (succeded)" do
825
+ url = 'https://www.onlinescoutmanager.co.uk/events.php?action=addEvent&sectionid=1'
826
+ post_data = {
827
+ 'apiid' => @api_config[:api_id],
828
+ 'token' => @api_config[:api_token],
829
+ 'userid' => 'user',
830
+ 'secret' => 'secret',
831
+ 'name' => 'Test event',
832
+ 'startdate' => '2000-01-02',
833
+ 'enddate' => '2001-02-03',
834
+ 'starttime' => '03:04:05',
835
+ 'endtime' => '04:05:06',
836
+ 'cost' => '1.23',
837
+ 'location' => 'Somewhere',
838
+ 'notes' => 'none',
839
+ 'eventid' => 2
840
+ }
841
+
842
+ api = Osm::Api.new('user', 'secret')
843
+ api.stub(:get_events) { [] }
844
+ HTTParty.should_receive(:post).with(url, {:body => post_data}) { DummyHttpResult.new(:response=>{:code=>'200', :body=>'{"id":2}'}) }
845
+
846
+ api.update_event(Osm::Event.new({
847
+ :section_id => 1,
848
+ :name => 'Test event',
849
+ :start => DateTime.new(2000, 01, 02, 03, 04, 05),
850
+ :finish => DateTime.new(2001, 02, 03, 04, 05, 06),
851
+ :cost => '1.23',
852
+ :location => 'Somewhere',
853
+ :notes => 'none',
854
+ :id => 2
855
+ })).should be_true
856
+ end
857
+
858
+ it "Update an event (failed)" do
859
+ url = 'https://www.onlinescoutmanager.co.uk/events.php?action=addEvent&sectionid=1'
860
+ post_data = {
861
+ 'apiid' => @api_config[:api_id],
862
+ 'token' => @api_config[:api_token],
863
+ 'userid' => 'user',
864
+ 'secret' => 'secret',
865
+ 'name' => 'Test event',
866
+ 'startdate' => '2000-01-02',
867
+ 'enddate' => '2001-02-03',
868
+ 'starttime' => '03:04:05',
869
+ 'endtime' => '04:05:06',
870
+ 'cost' => '1.23',
871
+ 'location' => 'Somewhere',
872
+ 'notes' => 'none',
873
+ 'eventid' => 2
874
+ }
875
+
876
+ api = Osm::Api.new('user', 'secret')
877
+ api.stub(:get_events) { [] }
878
+ HTTParty.should_receive(:post).with(url, {:body => post_data}) { DummyHttpResult.new(:response=>{:code=>'200', :body=>'{}'}) }
879
+
880
+ api.update_event(Osm::Event.new({
881
+ :section_id => 1,
882
+ :name => 'Test event',
883
+ :start => DateTime.new(2000, 01, 02, 03, 04, 05),
884
+ :finish => DateTime.new(2001, 02, 03, 04, 05, 06),
885
+ :cost => '1.23',
886
+ :location => 'Somewhere',
887
+ :notes => 'none',
888
+ :id => 2
889
+ })).should be_false
890
+ end
891
+
892
+ it "Delete an event (succeded)" do
893
+ url = 'https://www.onlinescoutmanager.co.uk/events.php?action=deleteEvent&sectionid=1&eventid=2'
894
+ post_data = {
895
+ 'apiid' => @api_config[:api_id],
896
+ 'token' => @api_config[:api_token],
897
+ 'userid' => 'user',
898
+ 'secret' => 'secret',
899
+ }
900
+
901
+ api = Osm::Api.new('user', 'secret')
902
+ HTTParty.should_receive(:post).with(url, {:body => post_data}) { DummyHttpResult.new(:response=>{:code=>'200', :body=>'{"ok":true}'}) }
903
+
904
+ api.delete_event(Osm::Event.new({
905
+ :section_id => 1,
906
+ :name => 'Test event',
907
+ :id => 2
908
+ })).should be_true
909
+ end
910
+
911
+ it "Delete an event (failed)" do
912
+ url = 'https://www.onlinescoutmanager.co.uk/events.php?action=deleteEvent&sectionid=1&eventid=2'
913
+ post_data = {
914
+ 'apiid' => @api_config[:api_id],
915
+ 'token' => @api_config[:api_token],
916
+ 'userid' => 'user',
917
+ 'secret' => 'secret',
918
+ }
919
+
920
+ api = Osm::Api.new('user', 'secret')
921
+ HTTParty.should_receive(:post).with(url, {:body => post_data}) { DummyHttpResult.new(:response=>{:code=>'200', :body=>'{"ok":false}'}) }
922
+
923
+ api.delete_event(Osm::Event.new({
924
+ :section_id => 1,
925
+ :name => 'Test event',
926
+ :id => 2
927
+ })).should be_false
928
+ end
929
+
930
+ it "Add field to an event (succeded)" do
931
+ url = 'https://www.onlinescoutmanager.co.uk/events.php?action=addColumn&sectionid=1&eventid=2'
932
+ post_data = {
933
+ 'apiid' => @api_config[:api_id],
934
+ 'token' => @api_config[:api_token],
935
+ 'userid' => 'user',
936
+ 'secret' => 'secret',
937
+ 'columnName' => 'Test field',
938
+ }
939
+
940
+ api = Osm::Api.new('user', 'secret')
941
+ HTTParty.should_receive(:post).with(url, {:body => post_data}) { DummyHttpResult.new(:response=>{:code=>'200', :body=>'{"eventid":"2"}'}) }
942
+
943
+ api.add_event_field(Osm::Event.new({
944
+ :section_id => 1,
945
+ :name => 'Test event',
946
+ :id => 2
947
+ }), 'Test field').should be_true
948
+ end
949
+
950
+ it "Add field to an event (failed)" do
951
+ url = 'https://www.onlinescoutmanager.co.uk/events.php?action=addColumn&sectionid=1&eventid=2'
952
+ post_data = {
953
+ 'apiid' => @api_config[:api_id],
954
+ 'token' => @api_config[:api_token],
955
+ 'userid' => 'user',
956
+ 'secret' => 'secret',
957
+ 'columnName' => 'Test field',
958
+ }
959
+
960
+ api = Osm::Api.new('user', 'secret')
961
+ HTTParty.should_receive(:post).with(url, {:body => post_data}) { DummyHttpResult.new(:response=>{:code=>'200', :body=>'{}'}) }
962
+
963
+ api.add_event_field(Osm::Event.new({
964
+ :section_id => 1,
965
+ :name => 'Test event',
966
+ :id => 2
967
+ }), 'Test field').should be_false
968
+ end
969
+
970
+
590
971
  it "Create a term (succeded)" do
591
972
  url = 'https://www.onlinescoutmanager.co.uk/users.php?action=addTerm&sectionid=1'
592
973
  post_data = {
@@ -637,6 +1018,32 @@ describe "API" do
637
1018
  }).should be_false
638
1019
  end
639
1020
 
1021
+ it "Update register attendance" do
1022
+ url = 'https://www.onlinescoutmanager.co.uk/users.php?action=registerUpdate&sectionid=1&termid=2'
1023
+ post_data = {
1024
+ 'apiid' => @api_config[:api_id],
1025
+ 'token' => @api_config[:api_token],
1026
+ 'userid' => 'user',
1027
+ 'secret' => 'secret',
1028
+ 'scouts' => '["3"]',
1029
+ 'selectedDate' => '2000-01-02',
1030
+ 'present' => 'Yes',
1031
+ 'section' => :cubs,
1032
+ 'sectionid' => 1,
1033
+ 'completedBadges' => '[{"a":"A"},{"b":"B"}]'
1034
+ }
1035
+
1036
+ HTTParty.should_receive(:post).with(url, {:body => post_data}) { DummyHttpResult.new(:response=>{:code=>'200', :body=>'[]'}) }
1037
+ Osm::Api.new('user', 'secret').update_register({
1038
+ :section => Osm::Section.new(:id=>1, :type=>:cubs),
1039
+ :term => 2,
1040
+ :evening => Date.new(2000, 1, 2),
1041
+ :attendance => 'Yes',
1042
+ :members => 3,
1043
+ :completed_badge_requirements => [{'a'=>'A'}, {'b'=>'B'}]
1044
+ }).should be_true
1045
+ end
1046
+
640
1047
 
641
1048
  it "Update a term (succeded)" do
642
1049
  url = 'https://www.onlinescoutmanager.co.uk/users.php?action=addTerm&sectionid=1'
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+ require 'date'
4
+
5
+
6
+ describe "Event Attendance" do
7
+
8
+ it "Create from API data" do
9
+ data = {
10
+ "scoutid" => "1",
11
+ "firstname" => "First",
12
+ "lastname" => "Last",
13
+ "dob" => "1899-11-30",
14
+ "patrolid" => "2",
15
+ "f_1" => "a",
16
+ "attending" => "Yes",
17
+ }
18
+
19
+ ea = Osm::EventAttendance.from_api(data, 3)
20
+
21
+ ea.member_id.should == 1
22
+ ea.grouping_id.should == 2
23
+ ea.fields.should == {
24
+ 'firstname' => 'First',
25
+ 'lastname' => 'Last',
26
+ 'dob' => Date.new(1899, 11, 30),
27
+ 'attending' => true,
28
+ 'f_1' => 'a',
29
+ }
30
+ ea.row.should == 3
31
+ ea.valid?.should be_true
32
+ end
33
+
34
+ end
@@ -16,7 +16,7 @@ describe "Event" do
16
16
  'cost' => 'Free',
17
17
  'location' => 'Somewhere',
18
18
  'notes' => 'None',
19
- 'archived' => '0'
19
+ 'archived' => '0',
20
20
  }
21
21
  event = Osm::Event.from_api(data)
22
22
 
data/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Osm
2
- VERSION = "0.0.25"
2
+ VERSION = "0.0.26"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: osm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.25
4
+ version: 0.0.26
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-26 00:00:00.000000000Z
12
+ date: 2012-10-02 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
16
- requirement: &83764340 !ruby/object:Gem::Requirement
16
+ requirement: &84281650 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '3.2'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *83764340
24
+ version_requirements: *84281650
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: httparty
27
- requirement: &83763040 !ruby/object:Gem::Requirement
27
+ requirement: &84280940 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0.9'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *83763040
35
+ version_requirements: *84280940
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: active_attr
38
- requirement: &83762650 !ruby/object:Gem::Requirement
38
+ requirement: &84277910 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0.6'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *83762650
46
+ version_requirements: *84277910
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: activemodel
49
- requirement: &83761810 !ruby/object:Gem::Requirement
49
+ requirement: &84277570 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '3.2'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *83761810
57
+ version_requirements: *84277570
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rake
60
- requirement: &83759370 !ruby/object:Gem::Requirement
60
+ requirement: &84277120 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0.9'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *83759370
68
+ version_requirements: *84277120
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
- requirement: &83745000 !ruby/object:Gem::Requirement
71
+ requirement: &84276710 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ~>
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '2.11'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *83745000
79
+ version_requirements: *84276710
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: fakeweb
82
- requirement: &83744610 !ruby/object:Gem::Requirement
82
+ requirement: &84276320 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ~>
@@ -87,7 +87,7 @@ dependencies:
87
87
  version: '1.3'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *83744610
90
+ version_requirements: *84276320
91
91
  description: Use the Online Scout Manager API (https://www.onlinescoutmanager.co.uk)
92
92
  to retrieve and save data.
93
93
  email:
@@ -113,6 +113,7 @@ files:
113
113
  - lib/osm/due_badges.rb
114
114
  - lib/osm/evening.rb
115
115
  - lib/osm/event.rb
116
+ - lib/osm/event_attendance.rb
116
117
  - lib/osm/flexi_record_data.rb
117
118
  - lib/osm/flexi_record_field.rb
118
119
  - lib/osm/grouping.rb
@@ -129,6 +130,7 @@ files:
129
130
  - spec/osm/api_strangeness_spec.rb
130
131
  - spec/osm/due_badges_spec.rb
131
132
  - spec/osm/evening_spec.rb
133
+ - spec/osm/event_attendance_spec.rb
132
134
  - spec/osm/event_spec.rb
133
135
  - spec/osm/flexi_record_data_spec.rb
134
136
  - spec/osm/flexi_record_field_spec.rb