osm 0.6.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,12 @@
1
+ ## Version 1.0.0
2
+
3
+ * SMS text messages:
4
+ * Section gains sms\_sent\_test, sms\_messages\_sent and sms\_messages\_remaining attributes
5
+ * Add Sms class:
6
+ * With send\_sms(api, section\_id, member\_ids, all\_or\_one, source\_address, message) method
7
+ * With DeliveryReport Model subclass
8
+ * With get\_for\_section(api, section) class method
9
+
1
10
  ## Version 0.6.3
2
11
 
3
12
  * Fix started? and started methods for badges with a combination of custom and normal requirements
data/README.md CHANGED
@@ -32,7 +32,7 @@ Use the [Online Scout Manager](https://www.onlinescoutmanager.co.uk) API.
32
32
  Add to your Gemfile and run the `bundle` command to install it.
33
33
 
34
34
  ```ruby
35
- gem 'osm', '~> 0.6.0'
35
+ gem 'osm', '~> 1.0.0'
36
36
  ```
37
37
 
38
38
  Configure the gem during the initalization of the app (e.g. if using rails then config/initializers/osm.rb would look like):
@@ -108,6 +108,7 @@ however it should be noted that when the OSM API adds a feature it can be diffic
108
108
  * Roles
109
109
  * Section
110
110
  * Sections
111
+ * SMS Delivery Reports
111
112
  * Term
112
113
  * Terms
113
114
 
@@ -141,15 +142,13 @@ however it should be noted that when the OSM API adds a feature it can be diffic
141
142
  ### Actions
142
143
  * Authorise an app to use the API on a user's behalf
143
144
  * Add activity to programme
145
+ * Send an SMS to member(s)
144
146
 
145
147
 
146
148
  ## Parts of the OSM API currently NOT supported (may not be an exhaustive list):
147
149
 
148
150
  See the [Roadmap page in the wiki](https://github.com/robertgauld/osm/wiki/Roadmap) for more details.
149
151
 
150
- * SMS:
151
- * Retrieval of delivery reports [issue 54]
152
- * Sending a message [issue 54]
153
- * Gift aid (Everything) (Gold required)
154
- * Finances (Everything) (Gold required)
152
+ * Gift aid (Everything) (Gold required) [issue 75]
153
+ * Finances (Everything) (Gold required) [issues 76 & 77]]
155
154
  * MyScout (Everything) (Maybe)
data/lib/osm.rb CHANGED
@@ -91,7 +91,7 @@ module Osm
91
91
  end
92
92
  end
93
93
 
94
- def self.parse_date_time(date_time)
94
+ def self.parse_datetime(date_time)
95
95
  return nil if date_time.nil? || date_time.empty?
96
96
  begin
97
97
  return DateTime.strptime((date_time), OSM_DATETIME_FORMAT)
@@ -61,6 +61,12 @@ module Osm
61
61
  # @return [Fixnum] How many payment reminders to send to parents who haven't paid yet
62
62
  # @!attribute [rw] myscout_payment_reminder_frequency
63
63
  # @return [Fixnum] How many days to leave between payment reminder emails
64
+ # @!attribute [rw] sms_sent_test
65
+ # @return [Boolean] Whether the section has sent their test SMS message
66
+ # @!attribute [rw] sms_messages_sent
67
+ # @return [Fixnum] How many SMS messages have been sent by the section
68
+ # @!attribute [rw] sms_messages_remaining
69
+ # @return [Fixnum] How many SMS messages the section can send before needing to topup
64
70
 
65
71
  attribute :id, :type => Integer
66
72
  attribute :name, :type => String
@@ -92,6 +98,9 @@ module Osm
92
98
  attribute :myscout_event_reminder_frequency, :type => Integer
93
99
  attribute :myscout_payment_reminder_count, :type => Integer
94
100
  attribute :myscout_payment_reminder_frequency, :type => Integer
101
+ attribute :sms_sent_test, :type => Boolean, :default => false
102
+ attribute :sms_messages_sent, :type => Integer, :default => 0
103
+ attribute :sms_messages_remaining, :type => Integer, :default => 0
95
104
 
96
105
  attr_accessible :id, :name, :group_id, :group_name, :subscription_level, :subscription_expires,
97
106
  :type, :column_names, :fields, :intouch_fields, :mobile_fields, :flexi_records,
@@ -101,7 +110,8 @@ module Osm
101
110
  :myscout_email_address_from, :myscout_email_address_copy,
102
111
  :myscout_badges_partial, :myscout_programme_summary, :myscout_programme_times,
103
112
  :myscout_event_reminder_count, :myscout_event_reminder_frequency,
104
- :myscout_payment_reminder_count, :myscout_payment_reminder_frequency
113
+ :myscout_payment_reminder_count, :myscout_payment_reminder_frequency,
114
+ :sms_sent_test, :sms_messages_sent, :sms_messages_remaining
105
115
 
106
116
  validates_numericality_of :id, :only_integer=>true, :greater_than=>0, :allow_nil => true
107
117
  validates_numericality_of :group_id, :only_integer=>true, :greater_than=>0, :allow_nil => true
@@ -109,6 +119,8 @@ module Osm
109
119
  validates_numericality_of :myscout_event_reminder_frequency, :only_integer=>true, :greater_than_or_equal_to=>-1
110
120
  validates_numericality_of :myscout_payment_reminder_count, :only_integer=>true, :greater_than_or_equal_to=>-1
111
121
  validates_numericality_of :myscout_payment_reminder_frequency, :only_integer=>true, :greater_than_or_equal_to=>-1
122
+ validates_numericality_of :sms_messages_sent, :only_integer=>true, :greater_than_or_equal_to=>0
123
+ validates_numericality_of :sms_messages_remaining, :only_integer=>true, :greater_than_or_equal_to=>0
112
124
 
113
125
  validates_presence_of :name
114
126
  validates_presence_of :group_name
@@ -130,6 +142,7 @@ module Osm
130
142
  validates_inclusion_of :myscout_badges_partial, :in => [true, false]
131
143
  validates_inclusion_of :myscout_programme_summary, :in => [true, false]
132
144
  validates_inclusion_of :myscout_programme_times, :in => [true, false]
145
+ validates_inclusion_of :sms_sent_test, :in => [true, false]
133
146
 
134
147
  validates :column_names, :hash => {:key_type => Symbol, :value_type => String}
135
148
  validates :fields, :hash => {:key_type => Symbol, :value_in => [true, false]}
@@ -216,6 +229,9 @@ module Osm
216
229
  :myscout_event_reminder_frequency => myscout_data['eventRemindFrequency'].to_i,
217
230
  :myscout_payment_reminder_count => myscout_data['paymentRemindCount'].to_i,
218
231
  :myscout_payment_reminder_frequency => myscout_data['paymentRemindFrequency'].to_i,
232
+ :sms_sent_test => section_data['hasSentTestSMS'],
233
+ :sms_messages_sent => section_data['sms_sent'],
234
+ :sms_messages_remaining => section_data['sms_remaining'],
219
235
  )
220
236
 
221
237
  result.push section
@@ -0,0 +1,180 @@
1
+ module Osm
2
+
3
+ class Sms
4
+
5
+ # Get delivery reports
6
+ # @param [Osm::Api] api The api to use to make the request
7
+ # @param [Osm::Section, Fixnum, #to_i] section The section (or its ID) to send the message to
8
+ # @param [Array<Osm::Member, Fixnum, #to_i>, Osm::Member, Fixnum, #to_i] members The members (or their IDs) to send the message to
9
+ # @param [Symbol] all_or_one Wheather to send the message to all numbers for a member (:all) or just the first mobile one (:one)
10
+ # @param [String, #to_s] source_address The number to claim the message is from
11
+ # @param [String, #to_s] message The text of the message to send
12
+ # @return [Hash] with keys :sent (Fixnum), :result (Boolean) and :message (String)
13
+ def self.send_sms(api, section, members, all_or_one, source_address, message)
14
+ raise ArgumentError, 'all_or_one must be either :all or :one' unless [:all, :one].include?(all_or_one)
15
+ Osm::Model.require_access_to_section(api, section)
16
+
17
+ data = api.perform_query("sms.php?action=sendText&sectionid=#{section.to_i}", {
18
+ 'msg' => message,
19
+ 'scouts' => [*members].join(','),
20
+ 'source' => source_address,
21
+ 'all' => all_or_one,
22
+ 'scheduled' => 'now',
23
+ })
24
+
25
+ data.select!{ |k,v| !['debug', 'config'].include?(k) }
26
+ data = data.map do |k,v|
27
+ k = 'message' if k.eql?('msg')
28
+ k = 'sent' if k.eql?('sent_to')
29
+ [k.to_sym, v]
30
+ end
31
+ return Hash[*data.flatten]
32
+ end
33
+
34
+
35
+
36
+ class DeliveryReport < Osm::Model
37
+ # @!attribute [rw] sms_id
38
+ # @return [Fixnum] the id of the SMS
39
+ # @!attribute [rw] user_id
40
+ # @return [Fixnum] the id of the OSM user who sent the SMS
41
+ # @!attribute [rw] member_id
42
+ # @return [Fixnum] the id of the member the SMS was sent to
43
+ # @!attribute [rw] section_id
44
+ # @return [Fixnum] the id of the section 'owning' the SMS
45
+ # @!attribute [rw] from_name
46
+ # @return [String] the name of the person who sent the SMS
47
+ # @!attribute [rw] from_number
48
+ # @return [String] the number the SMS was 'sent from'
49
+ # @!attribute [rw] to_name
50
+ # @return [String] the name of the person the message was sent to
51
+ # @!attribute [rw] to_number
52
+ # @return [String] the number the SMS was sent to
53
+ # @!attribute [rw] message
54
+ # @return [String] the text of the SMS
55
+ # @!attribute [rw] scheduled
56
+ # @return [DateTime] when the SMS was scheduled to be sent
57
+ # @!attribute [rw] last_updated
58
+ # @return [DateTime] when this report was last updated
59
+ # @!attribute [rw] credits
60
+ # @return [Fixnum] thow many credits the SMS cost
61
+ # @!attribute [rw] status
62
+ # @return [Symbol] the status of the SMS (usually :sent, :delivered, :not_delivered, :invalid_destination_address or :not_sent)
63
+
64
+ attribute :sms_id, :type => Integer
65
+ attribute :user_id, :type => Integer
66
+ attribute :member_id, :type => Integer
67
+ attribute :section_id, :type => Integer
68
+ attribute :from_name, :type => String
69
+ attribute :from_number, :type => String
70
+ attribute :to_name, :type => String
71
+ attribute :to_number, :type => String
72
+ attribute :message, :type => String
73
+ attribute :scheduled, :type => DateTime
74
+ attribute :last_updated, :type => DateTime
75
+ attribute :credits, :type => Integer
76
+ attribute :status, :type => Object
77
+
78
+ attr_accessible :sms_id, :user_id, :member_id, :section_id, :from_name, :from_number, :to_name, :to_number, :message, :scheduled, :last_updated, :credits, :status
79
+
80
+ validates_numericality_of :sms_id, :only_integer=>true, :greater_than_or_equal_to=>0
81
+ validates_numericality_of :user_id, :only_integer=>true, :greater_than_or_equal_to=>0
82
+ validates_numericality_of :member_id, :only_integer=>true, :greater_than_or_equal_to=>0
83
+ validates_numericality_of :section_id, :only_integer=>true, :greater_than_or_equal_to=>0
84
+ validates_numericality_of :credits, :only_integer=>true, :greater_than_or_equal_to=>0
85
+ validates_presence_of :from_name
86
+ validates_presence_of :from_number
87
+ validates_presence_of :to_name
88
+ validates_presence_of :to_number
89
+ validates_presence_of :message
90
+ validates_presence_of :scheduled
91
+ validates_presence_of :last_updated
92
+ VALID_STATUSES = [:sent, :not_sent, :delivered, :not_delivered, :invalid_destination_address, :invalid_source_address, :invalid_message_format, :route_not_available, :not_allowed]
93
+ validates_inclusion_of :status, :in => VALID_STATUSES
94
+
95
+
96
+ # @!method initialize
97
+ # Initialize a new Badge
98
+ # @param [Hash] attributes The hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
99
+
100
+
101
+ # Get delivery reports
102
+ # @param [Osm::Api] api The api to use to make the request
103
+ # @param [Osm::Section, Fixnum, #to_i] section The section (or its ID) to get the reports for
104
+ # @!macro options_get
105
+ # @return [Array<Osm::Sms::DeliveryReport>]
106
+ def self.get_for_section(api, section, options={})
107
+ require_access_to_section(api, section, options)
108
+ section_id = section.to_i
109
+ cache_key = ['sms_delivery_reports', section_id]
110
+
111
+ if !options[:no_cache] && Osm::Model.cache_exist?(api, cache_key)
112
+ return cache_read(api, cache_key)
113
+ end
114
+
115
+ reports = []
116
+ get_name_number_regex = /\A(?<name>.*\w)\W+(?<number>\d*)\Z/
117
+ data = api.perform_query("sms.php?action=deliveryReports&sectionid=#{section_id}&dateFormat=generic")
118
+ data['items'].each do |report|
119
+ from = report['from'].match(get_name_number_regex)
120
+ to = report['to'].match(get_name_number_regex)
121
+ reports.push new(
122
+ :sms_id => Osm.to_i_or_nil(report['smsid']),
123
+ :user_id => Osm.to_i_or_nil(report['userid']),
124
+ :member_id => Osm.to_i_or_nil(report['scoutid']),
125
+ :section_id => Osm.to_i_or_nil(report['sectionid']),
126
+ :from_name => from[:name],
127
+ :from_number => "+#{from[:number]}",
128
+ :to_name => to[:name],
129
+ :to_number => "+#{to[:number]}",
130
+ :message => report['message'],
131
+ :scheduled => Osm.parse_datetime(report['schedule']),
132
+ :last_updated => Osm.parse_datetime(report['lastupdated']),
133
+ :credits => Osm.to_i_or_nil(report['credits']),
134
+ :status => (report['status'] || 'error').downcase.to_sym,
135
+ )
136
+ end
137
+
138
+ cache_write(api, cache_key, reports)
139
+ return reports
140
+ end
141
+
142
+
143
+ # @!method status_sent?
144
+ # Check if the SMS was sent
145
+ # @return (Boolean)
146
+ # @!method status_not_sent?
147
+ # Check if the SMS was not sent
148
+ # @return (Boolean)
149
+ # @!method status_delivered?
150
+ # Check if the SMS was delivered
151
+ # @return (Boolean)
152
+ # @!method status_not_delivered?
153
+ # Check if the SMS was not delivered
154
+ # @return (Boolean)
155
+ # @!method status_invalid_destination_address?
156
+ # Check if the SMS had an invalid destination address
157
+ # @return (Boolean)
158
+ # @!method status_invalid_source_address?
159
+ # Check if the SMS had an invalid source address
160
+ # @return (Boolean)
161
+ # @!method status_invalid_message_format?
162
+ # Check if the SMS message was in an invalid format
163
+ # @return (Boolean)
164
+ # @!method route_not_available?
165
+ # Check if the SMS sending service could not route the message
166
+ # @return (Boolean)
167
+ # @!method status_not_allowed?
168
+ # Check if the SMS sending service refused to send the message
169
+ # @return (Boolean)
170
+ VALID_STATUSES.each do |attribute|
171
+ define_method "status_#{attribute}?" do
172
+ status == attribute
173
+ end
174
+ end
175
+
176
+ end
177
+
178
+ end
179
+
180
+ end
@@ -37,7 +37,10 @@ describe "Section" do
37
37
  :myscout_event_reminder_count => 4,
38
38
  :myscout_event_reminder_frequency => 5,
39
39
  :myscout_payment_reminder_count => 6,
40
- :myscout_payment_reminder_frequency => 7
40
+ :myscout_payment_reminder_frequency => 7,
41
+ :sms_sent_test => true,
42
+ :sms_messages_sent => 8,
43
+ :sms_messages_remaining => 9,
41
44
  }
42
45
  end
43
46
 
@@ -75,6 +78,9 @@ describe "Section" do
75
78
  section.myscout_event_reminder_frequency.should == 5
76
79
  section.myscout_payment_reminder_count.should == 6
77
80
  section.myscout_payment_reminder_frequency.should == 7
81
+ section.sms_sent_test.should == true
82
+ section.sms_messages_sent.should == 8
83
+ section.sms_messages_remaining.should == 9
78
84
  section.valid?.should be_true
79
85
  end
80
86
 
@@ -92,6 +98,9 @@ describe "Section" do
92
98
  section.flexi_records.should == []
93
99
  section.myscout_email_address_from.should == ''
94
100
  section.myscout_email_address_copy.should == ''
101
+ section.sms_sent_test.should == false
102
+ section.sms_messages_sent.should == 0
103
+ section.sms_messages_remaining.should == 0
95
104
  end
96
105
 
97
106
 
@@ -99,8 +108,8 @@ describe "Section" do
99
108
 
100
109
  before :each do
101
110
  body = [
102
- {"sectionConfig"=>"{\"subscription_level\":1,\"subscription_expires\":\"2013-01-05\",\"sectionType\":\"beavers\",\"columnNames\":{\"column_names\":\"names\"},\"numscouts\":10,\"hasUsedBadgeRecords\":true,\"hasProgramme\":true,\"extraRecords\":[{\"name\":\"Flexi Record 1\",\"extraid\":\"111\"}],\"wizard\":\"false\",\"fields\":{\"fields\":true},\"intouch\":{\"intouch_fields\":true},\"mobFields\":{\"mobile_fields\":true},\"gocardless\":\"true\",\"portal\":{\"paymentRemindFrequency\":\"7\",\"paymentRemindCount\":\"6\",\"eventRemindFrequency\":\"5\",\"eventRemindCount\":\"4\",\"badgesPartial\":1,\"programmeTimes\":1,\"programmeSummary\":1,\"emailAddress\":\"send_from@example.com\",\"emailAddressCopy\":null,\"payments\":1,\"badges\":1,\"emails\":{\"email1\":\"true\",\"email2\":\"false\"},\"events\":1,\"programme\":1},\"portalExpires\":{\"events\":\"2013-01-06\",\"eventsA\":1,\"badges\":\"2013-01-07\",\"badgesA\":1,\"programme\":\"2013-01-08\",\"programmeA\":1}}", "groupname"=>"3rd Somewhere", "groupid"=>"3", "groupNormalised"=>"1", "sectionid"=>"1", "sectionname"=>"Section 1", "section"=>"beavers", "isDefault"=>"1", "permissions"=>{"badge"=>10, "member"=>20, "user"=>100, "register"=>100, "contact"=>100, "programme"=>100, "originator"=>1, "events"=>100, "finance"=>100, "flexi"=>100}},
103
- {"sectionConfig"=>"{\"subscription_level\":3,\"subscription_expires\":\"2013-01-05\",\"sectionType\":\"cubs\",\"columnNames\":{\"phone1\":\"Home Phone\",\"phone2\":\"Parent 1 Phone\",\"address\":\"Member's Address\",\"phone3\":\"Parent 2 Phone\",\"address2\":\"Address 2\",\"phone4\":\"Alternate Contact Phone\",\"subs\":\"Gender\",\"email1\":\"Parent 1 Email\",\"medical\":\"Medical / Dietary\",\"email2\":\"Parent 2 Email\",\"ethnicity\":\"Gift Aid\",\"email3\":\"Member's Email\",\"religion\":\"Religion\",\"email4\":\"Email 4\",\"school\":\"School\"},\"numscouts\":10,\"hasUsedBadgeRecords\":true,\"hasProgramme\":true,\"extraRecords\":[],\"wizard\":\"false\",\"fields\":{\"email1\":true,\"email2\":true,\"email3\":true,\"email4\":false,\"address\":true,\"address2\":false,\"phone1\":true,\"phone2\":true,\"phone3\":true,\"phone4\":true,\"school\":false,\"religion\":true,\"ethnicity\":true,\"medical\":true,\"patrol\":true,\"subs\":true,\"saved\":true},\"intouch\":{\"address\":true,\"address2\":false,\"email1\":false,\"email2\":false,\"email3\":false,\"email4\":false,\"phone1\":true,\"phone2\":true,\"phone3\":true,\"phone4\":true,\"medical\":false},\"mobFields\":{\"email1\":false,\"email2\":false,\"email3\":false,\"email4\":false,\"address\":true,\"address2\":false,\"phone1\":true,\"phone2\":true,\"phone3\":true,\"phone4\":true,\"school\":false,\"religion\":false,\"ethnicity\":true,\"medical\":true,\"patrol\":true,\"subs\":false}}", "groupname"=>"1st Somewhere", "groupid"=>"1", "groupNormalised"=>"1", "sectionid"=>"2", "sectionname"=>"Section 2", "section"=>"cubs", "isDefault"=>"0", "permissions"=>{"badge"=>100, "member"=>100, "user"=>100, "register"=>100, "contact"=>100, "programme"=>100, "originator"=>1, "events"=>100, "finance"=>100, "flexi"=>100}}
111
+ {"sectionConfig"=>"{\"subscription_level\":1,\"subscription_expires\":\"2013-01-05\",\"sectionType\":\"beavers\",\"columnNames\":{\"column_names\":\"names\"},\"numscouts\":10,\"hasUsedBadgeRecords\":true,\"hasProgramme\":true,\"extraRecords\":[{\"name\":\"Flexi Record 1\",\"extraid\":\"111\"}],\"wizard\":\"false\",\"fields\":{\"fields\":true},\"intouch\":{\"intouch_fields\":true},\"mobFields\":{\"mobile_fields\":true},\"gocardless\":\"true\",\"portal\":{\"paymentRemindFrequency\":\"7\",\"paymentRemindCount\":\"6\",\"eventRemindFrequency\":\"5\",\"eventRemindCount\":\"4\",\"badgesPartial\":1,\"programmeTimes\":1,\"programmeSummary\":1,\"emailAddress\":\"send_from@example.com\",\"emailAddressCopy\":null,\"payments\":1,\"badges\":1,\"emails\":{\"email1\":\"true\",\"email2\":\"false\"},\"events\":1,\"programme\":1},\"portalExpires\":{\"events\":\"2013-01-06\",\"eventsA\":1,\"badges\":\"2013-01-07\",\"badgesA\":1,\"programme\":\"2013-01-08\",\"programmeA\":1},\"hasSentTestSMS\":true,\"sms_remaining\":8,\"sms_sent\":9}", "groupname"=>"3rd Somewhere", "groupid"=>"3", "groupNormalised"=>"1", "sectionid"=>"1", "sectionname"=>"Section 1", "section"=>"beavers", "isDefault"=>"1", "permissions"=>{"badge"=>10, "member"=>20, "user"=>100, "register"=>100, "contact"=>100, "programme"=>100, "originator"=>1, "events"=>100, "finance"=>100, "flexi"=>100}},
112
+ {"sectionConfig"=>"{\"subscription_level\":3,\"subscription_expires\":\"2013-01-05\",\"sectionType\":\"cubs\",\"columnNames\":{\"phone1\":\"Home Phone\",\"phone2\":\"Parent 1 Phone\",\"address\":\"Member's Address\",\"phone3\":\"Parent 2 Phone\",\"address2\":\"Address 2\",\"phone4\":\"Alternate Contact Phone\",\"subs\":\"Gender\",\"email1\":\"Parent 1 Email\",\"medical\":\"Medical / Dietary\",\"email2\":\"Parent 2 Email\",\"ethnicity\":\"Gift Aid\",\"email3\":\"Member's Email\",\"religion\":\"Religion\",\"email4\":\"Email 4\",\"school\":\"School\"},\"numscouts\":10,\"hasUsedBadgeRecords\":true,\"hasProgramme\":true,\"extraRecords\":[],\"wizard\":\"false\",\"fields\":{\"email1\":true,\"email2\":true,\"email3\":true,\"email4\":false,\"address\":true,\"address2\":false,\"phone1\":true,\"phone2\":true,\"phone3\":true,\"phone4\":true,\"school\":false,\"religion\":true,\"ethnicity\":true,\"medical\":true,\"patrol\":true,\"subs\":true,\"saved\":true},\"intouch\":{\"address\":true,\"address2\":false,\"email1\":false,\"email2\":false,\"email3\":false,\"email4\":false,\"phone1\":true,\"phone2\":true,\"phone3\":true,\"phone4\":true,\"medical\":false},\"mobFields\":{\"email1\":false,\"email2\":false,\"email3\":false,\"email4\":false,\"address\":true,\"address2\":false,\"phone1\":true,\"phone2\":true,\"phone3\":true,\"phone4\":true,\"school\":false,\"religion\":false,\"ethnicity\":true,\"medical\":true,\"patrol\":true,\"subs\":false},\"hasSentTestSMS\":true,\"sms_remaining\":8,\"sms_sent\":9}", "groupname"=>"1st Somewhere", "groupid"=>"1", "groupNormalised"=>"1", "sectionid"=>"2", "sectionname"=>"Section 2", "section"=>"cubs", "isDefault"=>"0", "permissions"=>{"badge"=>100, "member"=>100, "user"=>100, "register"=>100, "contact"=>100, "programme"=>100, "originator"=>1, "events"=>100, "finance"=>100, "flexi"=>100}}
104
113
  ]
105
114
  FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/api.php?action=getUserRoles", :body => body.to_json)
106
115
  end
@@ -143,6 +152,9 @@ describe "Section" do
143
152
  section.myscout_event_reminder_frequency.should == 5
144
153
  section.myscout_payment_reminder_count.should == 6
145
154
  section.myscout_payment_reminder_frequency.should == 7
155
+ section.sms_sent_test.should == true
156
+ section.sms_messages_remaining.should == 8
157
+ section.sms_messages_sent.should == 9
146
158
  end
147
159
 
148
160
  it "From cache" do
@@ -0,0 +1,129 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe "SMS" do
5
+
6
+ describe "Send an SMS" do
7
+
8
+ it "Success" do
9
+ HTTParty.should_receive(:post).with('https://www.onlinescoutmanager.co.uk/sms.php?action=sendText&sectionid=1', {:body => {
10
+ 'apiid' => @CONFIGURATION[:api][:osm][:id],
11
+ 'token' => @CONFIGURATION[:api][:osm][:token],
12
+ 'userid' => 'user_id',
13
+ 'secret' => 'secret',
14
+ 'msg' => 'Test message.',
15
+ 'scouts' => '2,3',
16
+ 'source' => '441234567890',
17
+ 'all' => :one,
18
+ 'scheduled' => 'now',
19
+ }}) { OsmTest::DummyHttpResult.new(:response=>{:code=>'200', :body=>{'result'=>true,'sent'=>2,'message'=>'Success','debug'=>nil,'config'=>{}}.to_json}) }
20
+
21
+ result = Osm::Sms.send_sms(
22
+ @api,
23
+ 1, # Section
24
+ [2, 3], # Members
25
+ :one,
26
+ '441234567890', # Source address
27
+ 'Test message.' # Message text
28
+ )
29
+
30
+ result.should == {
31
+ :result => true,
32
+ :sent => 2,
33
+ :message => 'Success'
34
+ }
35
+ end
36
+
37
+ end
38
+
39
+
40
+ describe "Delivery Report" do
41
+
42
+ it "Create" do
43
+ report = Osm::Sms::DeliveryReport.new(
44
+ :sms_id => 1,
45
+ :user_id => 2,
46
+ :member_id => 3,
47
+ :section_id => 4,
48
+ :from_name => 'a',
49
+ :from_number => '5',
50
+ :to_name => 'b',
51
+ :to_number => '6',
52
+ :message => 'c',
53
+ :scheduled => DateTime.new(2000, 1, 2, 3, 4, 5),
54
+ :last_updated => DateTime.new(2000, 1, 2, 3, 5, 6),
55
+ :credits => 7,
56
+ :status => :delivered,
57
+ )
58
+
59
+ report.sms_id.should == 1
60
+ report.user_id.should == 2
61
+ report.member_id.should == 3
62
+ report.section_id.should == 4
63
+ report.from_name.should == 'a'
64
+ report.from_number.should == '5'
65
+ report.to_name.should == 'b'
66
+ report.to_number.should == '6'
67
+ report.message.should == 'c'
68
+ report.scheduled.should == DateTime.new(2000, 1, 2, 3, 4, 5)
69
+ report.last_updated.should == DateTime.new(2000, 1, 2, 3, 5, 6)
70
+ report.credits.should == 7
71
+ report.status.should == :delivered
72
+ report.valid?.should be_true
73
+ end
74
+
75
+ describe "Status helpers" do
76
+ statuses = Osm::Sms::DeliveryReport::VALID_STATUSES
77
+ statuses.each do |status|
78
+ it "For #{status}" do
79
+ statuses.each do |test_status|
80
+ Osm::Sms::DeliveryReport.new(:status => status).send("status_#{test_status}?").should == (status == test_status)
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ it "Get from OSM" do
87
+ data = {
88
+ "identifier" => "smsid",
89
+ "items" => [{
90
+ "smsid" => "2",
91
+ "userid" => "3",
92
+ "scoutid" => "4",
93
+ "sectionid" => "1",
94
+ "phone" => "442345678901",
95
+ "from" => "From Name 443456789012",
96
+ "message" => "Test message.",
97
+ "schedule" => "2000-01-02 03:04:05",
98
+ "status" => "DELIVERED",
99
+ "lastupdated" => "2000-01-02 03:04:06",
100
+ "credits" => "1",
101
+ "fromuser" => "From Name ",
102
+ "firstname" => "To",
103
+ "lastname" => "Name",
104
+ "to" => "To Name 441234567890"
105
+ }]
106
+ }
107
+ FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/sms.php?action=deliveryReports&sectionid=1&dateFormat=generic", :body => data.to_json)
108
+
109
+ reports = Osm::Sms::DeliveryReport.get_for_section(@api, 1)
110
+ reports.size.should == 1
111
+ report = reports[0]
112
+ report.sms_id.should == 2
113
+ report.user_id.should == 3
114
+ report.member_id.should == 4
115
+ report.section_id.should == 1
116
+ report.from_name.should == 'From Name'
117
+ report.from_number.should == '+443456789012'
118
+ report.to_name.should == 'To Name'
119
+ report.to_number.should == '+441234567890'
120
+ report.message.should == 'Test message.'
121
+ report.scheduled.should == DateTime.new(2000, 1, 2, 3, 4, 5)
122
+ report.last_updated.should == DateTime.new(2000, 1, 2, 3, 4, 6)
123
+ report.credits.should == 1
124
+ report.status.should == :delivered
125
+ end
126
+
127
+ end
128
+
129
+ end
data/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Osm
2
- VERSION = "0.6.3"
2
+ VERSION = "1.0.0"
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.6.3
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -204,6 +204,7 @@ files:
204
204
  - lib/osm/model.rb
205
205
  - lib/osm/register.rb
206
206
  - lib/osm/section.rb
207
+ - lib/osm/sms.rb
207
208
  - lib/osm/term.rb
208
209
  - osm.gemspec
209
210
  - spec/osm/activity_spec.rb
@@ -220,6 +221,7 @@ files:
220
221
  - spec/osm/osm_spec.rb
221
222
  - spec/osm/register_spec.rb
222
223
  - spec/osm/section_spec.rb
224
+ - spec/osm/sms_spec.rb
223
225
  - spec/osm/term_spec.rb
224
226
  - spec/spec_helper.rb
225
227
  - version.rb