osm 0.6.3 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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