osm 0.0.25 → 0.0.26

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 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