osm 1.2.24 → 1.2.25
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +3 -1
- data/lib/osm.rb +2 -7
- data/lib/osm/activity.rb +1 -1
- data/lib/osm/api.rb +8 -4
- data/lib/osm/email.rb +392 -0
- data/lib/osm/myscout.rb +330 -0
- data/spec/osm/api_spec.rb +5 -0
- data/spec/osm/email_spec.rb +539 -0
- data/spec/osm/myscout_spec.rb +108 -0
- data/spec/osm/osm_spec.rb +0 -8
- data/version.rb +1 -1
- metadata +6 -2
data/lib/osm/myscout.rb
ADDED
@@ -0,0 +1,330 @@
|
|
1
|
+
module Osm
|
2
|
+
|
3
|
+
class Myscout
|
4
|
+
|
5
|
+
class ParentLoginHistory < Osm::Model
|
6
|
+
SORT_BY= [:last_name, :first_name, :member_id]
|
7
|
+
|
8
|
+
# @!attribute [rw] member_id
|
9
|
+
# @return [Fixnum] the id for the member
|
10
|
+
# @!attribute [rw] first_name
|
11
|
+
# @return [String] the member's first name
|
12
|
+
# @!attribute [rw] last_name
|
13
|
+
# @return [String] the member's last name
|
14
|
+
# @!attribute [rw] logins
|
15
|
+
# @return [Fixnum] the total number of logins
|
16
|
+
# @!attribute [rw] last_login
|
17
|
+
# @return [DateTime] the time and date of the last login
|
18
|
+
|
19
|
+
attribute :member_id, type: Integer
|
20
|
+
attribute :first_name, type: String
|
21
|
+
attribute :last_name, type: String
|
22
|
+
attribute :logins, type: Integer
|
23
|
+
attribute :last_login, type: DateTime
|
24
|
+
|
25
|
+
if ActiveModel::VERSION::MAJOR < 4
|
26
|
+
attr_accessible :member_id, :first_name, :last_name, :logins, :last_login
|
27
|
+
end
|
28
|
+
|
29
|
+
validates_presence_of :first_name
|
30
|
+
validates_presence_of :last_name
|
31
|
+
validates_numericality_of :member_id, only_integer: true, greater_than: 0
|
32
|
+
validates_numericality_of :logins, only_integer: true, greater_than_or_equal_to: 0
|
33
|
+
|
34
|
+
|
35
|
+
# @!method initialize
|
36
|
+
# Initialize a new Member
|
37
|
+
# @param [Hash] attributes The hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
|
38
|
+
|
39
|
+
|
40
|
+
# Get parent login history
|
41
|
+
# @param [Osm::Api] api The api to use to make the request
|
42
|
+
# @param [Osm::Section, Fixnum, #to_i] section The section (or its ID) to get login history for
|
43
|
+
# @!macro options_get
|
44
|
+
# @return [Array<Osm::Myscout::ParentLoginHistory>]
|
45
|
+
def self.get_for_section(api, section, options={})
|
46
|
+
section_id = section.to_i
|
47
|
+
require_ability_to(api, :read, :member, section, options)
|
48
|
+
cache_key = ['myscout', 'parent_login_history', section_id]
|
49
|
+
|
50
|
+
if !options[:no_cache] && cache_exist?(api, cache_key)
|
51
|
+
return cache_read(api, cache_key)
|
52
|
+
end
|
53
|
+
|
54
|
+
data = api.perform_query("ext/settings/parents/loginhistory/?action=getLoginHistory§ionid=#{section_id}")
|
55
|
+
return [] unless data.is_a?(Hash)
|
56
|
+
data = data['items']
|
57
|
+
return [] unless data.is_a?(Array)
|
58
|
+
|
59
|
+
data.map! do |item|
|
60
|
+
new(
|
61
|
+
member_id: Osm::to_i_or_nil(item['scoutid']),
|
62
|
+
first_name: item['firstname'],
|
63
|
+
last_name: item['lastname'],
|
64
|
+
logins: Osm::to_i_or_nil(item['numlogins']),
|
65
|
+
last_login: get_last_login_date(item['lastlogin'],)
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
cache_write(api, cache_key, data)
|
70
|
+
return data
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
def self.get_last_login_date(date_str)
|
75
|
+
return nil if date_str.nil?
|
76
|
+
return nil if date_str.eql?('Invitation not sent')
|
77
|
+
Time.strptime(date_str, '%d/%m/%Y %H:%M')
|
78
|
+
end
|
79
|
+
|
80
|
+
end # class Myscout::ParentLoginHistory
|
81
|
+
|
82
|
+
|
83
|
+
class Template < Osm::Model
|
84
|
+
SORT_BY = [:key]
|
85
|
+
|
86
|
+
TEMPLATES = [
|
87
|
+
{title: "First payment email", id: "email-first", description: "This email is sent to the parents the first time that you request a payment from them. The message should introduce the system to them, explain the benefits that the parents and you get, and provide account details (by using the tags).", tags:[
|
88
|
+
{id: "DIRECT_LINK", required: true, description: "A direct link to the payments page that avoids the need for the parents to login."},
|
89
|
+
{id: "SCHEDULE_NAME", required: true, description: "The name of the first payment schedule that you have asked the parents to pay."},
|
90
|
+
{id: "SCHEDULE_DESCRIPTION", required: false, description: "The description of the first payment schedule that you have asked the parents to pay."},
|
91
|
+
{id: "SCHEDULE_PREAUTH", required: false, description: "The amount you are asking parents to pre-authorise."},
|
92
|
+
{id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
|
93
|
+
{id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
|
94
|
+
]},
|
95
|
+
{title: "New schedule", id: "email-subsequent", description: "This email is sent every time you request the parents sign up to a payment schedule.", tags:[
|
96
|
+
{id: "DIRECT_LINK", required: true, description: "A direct link to the payments page that avoids the need for the parents to login."},
|
97
|
+
{id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
|
98
|
+
{id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
|
99
|
+
{id: "SCHEDULE_NAME", required: true, description: "The name of the payment schedule that you have asked the parents to pay."},
|
100
|
+
{id: "SCHEDULE_DESCRIPTION", required: false, description: "The description of the payment schedule that you have asked the parents to pay."},
|
101
|
+
{id: "SCHEDULE_PREAUTH", required: false, description: "The amount you are asking parents to pre-authorise."},
|
102
|
+
]},
|
103
|
+
{title: "New payment (direct debit already setup)", id: "email-specificpayment-dd", description: "This email is sent to parents (who have already set up a direct debit) when their child has been set to pay a payment on a schedule that contains optional payments (i.e. events). It should simply notify them of the upcoming payment and give a link to the system.", tags:[
|
104
|
+
{id: "DIRECT_LINK", required: true, description: "A direct link to the payments page that avoids the need for the parents to login."},
|
105
|
+
{id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
|
106
|
+
{id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
|
107
|
+
{id: "PAYMENT_NAME", required: true, description: "The name of the specific payment (this is different to the schedule name)."},
|
108
|
+
{id: "PAYMENT_DATE", required: true, description: "The date the payment process will be initiated."},
|
109
|
+
{id: "PAYMENT_AMOUNT", required: true, description: "The amount that will be taken (a pound sign is automatically inserted)."},
|
110
|
+
{id: "SCHEDULE_NAME", required: false, description: "The name of the payment schedule that you have asked the parents to pay."},
|
111
|
+
{id: "SCHEDULE_DESCRIPTION", required: false, description: "The description of the payment schedule that you have asked the parents to pay."},
|
112
|
+
{id: "SCHEDULE_PREAUTH", required: false, description: "The amount you are asking parents to pre-authorise."},
|
113
|
+
]},
|
114
|
+
{title: "Payment notification for overdue payment", id: "email-immediatepayment-dd", description: "This email is sent to parents who have an active direct debit when their child has been marked as requiring a payment in the past to let them know that they are being charged immediately.", tags:[
|
115
|
+
{id: "DIRECT_LINK", required: true, description: "A direct link to the payments page that avoids the need for the parents to login."},
|
116
|
+
{id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
|
117
|
+
{id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
|
118
|
+
{id: "PAYMENT_NAME", required: true, description: "The name of the specific payment (this is different to the schedule name)."},
|
119
|
+
{id: "PAYMENT_DATE", required: false, description: "The date the payment process will be initiated."},
|
120
|
+
{id: "PAYMENT_AMOUNT", required: true, description: "The amount that will be taken (a pound sign is automatically inserted)."},
|
121
|
+
{id: "SCHEDULE_NAME", required: false, description: "The name of the payment schedule that you have asked the parents to pay."},
|
122
|
+
{id: "SCHEDULE_DESCRIPTION", required: false, description: "The description of the payment schedule that you have asked the parents to pay."},
|
123
|
+
{id: "SCHEDULE_PREAUTH", required: false, description: "The amount you are asking parents to pre-authorise."},
|
124
|
+
]},
|
125
|
+
{title: "Immediate payment request for overdue payment", id: "email-immediatepayment-nodd", description: "This email is sent to parents who have not got an active direct debit when their child has been marked as requiring a payment in the past to let them know that they need to pay immediately.", tags:[
|
126
|
+
{id: "DIRECT_LINK", required: true, description: "A direct link to the payments page that avoids the need for the parents to login."},
|
127
|
+
{id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
|
128
|
+
{id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
|
129
|
+
{id: "PAYMENT_NAME", required: true, description: "The name of the specific payment (this is different to the schedule name)."},
|
130
|
+
{id: "PAYMENT_DATE", required: false, description: "The date the payment process will be initiated."},
|
131
|
+
{id: "PAYMENT_AMOUNT", required: true, description: "The amount that will be taken (a pound sign is automatically inserted)."},
|
132
|
+
{id: "SCHEDULE_NAME", required: false, description: "The name of the payment schedule that you have asked the parents to pay."},
|
133
|
+
{id: "SCHEDULE_DESCRIPTION", required: false, description: "The description of the payment schedule that you have asked the parents to pay."},
|
134
|
+
{id: "SCHEDULE_PREAUTH", required: false, description: "The amount you are asking parents to pre-authorise."},
|
135
|
+
]},
|
136
|
+
{title: "New payment (direct debit not setup)", id: "email-specificpayment-nodd", description: "This email is sent to parents (who have *not* set up a direct debit) when their child has been asked to pay for an individual entry on a schedule. The message should ask the parents to sign up to a direct debit, or optionally, remind them to pay you via cash/cheque etc.", tags:[
|
137
|
+
{id: "DIRECT_LINK", required: true, description: "A direct link to the payments page that avoids the need for the parents to login."},
|
138
|
+
{id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
|
139
|
+
{id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
|
140
|
+
{id: "PAYMENT_NAME", required: true, description: "The name of the specific payment (this is different to the schedule name)."},
|
141
|
+
{id: "PAYMENT_DATE", required: true, description: "The date the payment is due."},
|
142
|
+
{id: "PAYMENT_AMOUNT", required: true, description: "The amount that will be taken (a pound sign is automatically inserted)."},
|
143
|
+
{id: "SCHEDULE_NAME", required: false, description: "The name of the payment schedule that you have asked the parents to pay."},
|
144
|
+
{id: "SCHEDULE_DESCRIPTION", required: false, description: "The description of the payment schedule that you have asked the parents to pay."},
|
145
|
+
{id: "SCHEDULE_PREAUTH", required: false, description: "The amount you are asking parents to pre-authorise."},
|
146
|
+
]},
|
147
|
+
{title: "Payment initiated", id: "email-initiated", description: "This email is sent to parents when a payment is initiated by the system.", tags:[
|
148
|
+
{id: "DIRECT_LINK", required: true, description: "A direct link to the payments page that avoids the need for the parents to login."},
|
149
|
+
{id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
|
150
|
+
{id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
|
151
|
+
{id: "PAYMENT_NAME", required: false, description: "The name of the specific payment (this is different to the schedule name)."},
|
152
|
+
{id: "PAYMENT_DATE", required: false, description: "The date the payment is due."},
|
153
|
+
{id: "PAYMENT_AMOUNT", required: false, description: "The amount that will be taken (a pound sign is automatically inserted)."},
|
154
|
+
{id: "SCHEDULE_NAME", required: false, description: "The name of the payment schedule that you have asked the parents to pay."},
|
155
|
+
{id: "SCHEDULE_DESCRIPTION", required: false, description: "The description of the payment schedule that you have asked the parents to pay."},
|
156
|
+
{id: "SCHEDULE_PREAUTH", required: false, description: "The amount you are asking parents to pre-authorise."},
|
157
|
+
]},
|
158
|
+
{title: "Payment reminder", id: "email-paymentreminder", description: "This is send periodically after the due date when the payment has not been made. The frequency of the emails is configurable in the My.SCOUT section of the site.", tags:[
|
159
|
+
{id: "DIRECT_LINK", required: true, description: "A direct link to the payments page that avoids the need for the parents to login."},
|
160
|
+
{id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
|
161
|
+
{id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
|
162
|
+
{id: "PAYMENT_NAME", required: false, description: "The name of the specific payment (this is different to the schedule name)."},
|
163
|
+
{id: "PAYMENT_DATE", required: false, description: "The date the payment is due."},
|
164
|
+
{id: "PAYMENT_AMOUNT", required: false, description: "The amount that will be taken (a pound sign is automatically inserted)."},
|
165
|
+
{id: "SCHEDULE_NAME", required: false, description: "The name of the payment schedule that you have asked the parents to pay."},
|
166
|
+
{id: "SCHEDULE_DESCRIPTION", required: false, description: "The description of the payment schedule that you have asked the parents to pay."},
|
167
|
+
{id: "SCHEDULE_PREAUTH", required: false, description: "The amount you are asking parents to pre-authorise."},
|
168
|
+
]},
|
169
|
+
{title: "Introduction to payment system", id: "website-payments-index", description: "This text is shown on the parent website under the words \"What is this?\". It should be used to explain about this system and the benefits that the parents and leaders will get, and reassure the parents that it is a safe and secure system.", tags:[]},
|
170
|
+
{title: "Instructions to click Pay Now/Subscribe", id: "website-payments-schedule", description: "This text is shown on the parent website on a payment schedules pages, above the subscribe button. It should direct the parents to click the Subscribe button to set up a direct debit, or Pay falsew buttons to pay for things individually.", tags:[]},
|
171
|
+
{title: "Event invitation", id: "email-event", description: "This email is sent to the parents when you invite children to events in the Your Events area.", tags:[
|
172
|
+
{id: "DIRECT_LINK", required: true, description: "A direct link to the payments page that avoids the need for the parents to login."},
|
173
|
+
{id: "EVENT_NAME", required: false, description: "The name of the event"},
|
174
|
+
{id: "EVENT_LOCATION", required: false, description: "The location of the event"},
|
175
|
+
{id: "EVENT_COST", required: false, description: "The cost of the event"},
|
176
|
+
{id: "EVENT_DATES", required: false, description: "The event dates - this will be formatted properly into \"DATE\", \"DATE at TIME\", \"From DATE to DATE\", \"From DATE at TIME to DATE at TIME\" etc."},
|
177
|
+
{id: "EVENT_DETAILS", required: false, description: "This is the \"Details for My.SCOUT\" section of the event"},
|
178
|
+
{id: "CONFIRMATION_DEADLINE", required: false, description: "The confirmation deadline - beyond which, parents will not be able to sign up through My.SCOUT"},
|
179
|
+
{id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
|
180
|
+
{id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
|
181
|
+
]},
|
182
|
+
{title: "Event invitation reminder", id: "email-event-reminder", description: "This is a reminder email to ask the parents to let you know if their child is attending - the frequency and number of reminders is customisable in the My.SCOUT settings page.", tags:[
|
183
|
+
{id: "DIRECT_LINK", required: true, description: "A direct link to the events page that avoids the need for the parents to login."},
|
184
|
+
{id: "EVENT_NAME", required: false, description: "The name of the event"},
|
185
|
+
{id: "EVENT_LOCATION", required: false, description: "The location of the event"},
|
186
|
+
{id: "EVENT_COST", required: false, description: "The cost of the event"},
|
187
|
+
{id: "EVENT_DATES", required: false, description: "The event dates - this will be formatted properly into \"on DATE\", \"on DATE at TIME\", \"from DATE to DATE\", \"from DATE at TIME to DATE at TIME\" etc."},
|
188
|
+
{id: "EVENT_DETAILS", required: false, description: "This is the \"Details for My.SCOUT\" section of the event"},
|
189
|
+
{id: "CONFIRMATION_DEADLINE", required: false, description: "The confirmation deadline - beyond which, parents will not be able to sign up through My.SCOUT"},
|
190
|
+
{id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
|
191
|
+
{id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
|
192
|
+
]},
|
193
|
+
{title: "Event attendance reminder", id: "email-event-attendancereminder", description: "This is a reminder email to tell parents that their child is attending the event - the number of days before the event that this email is sent is customisable on a per-event basis on each event page.", tags:[
|
194
|
+
{id: "DIRECT_LINK", required: false, description: "A direct link to the events page that avoids the need for the parents to login."},
|
195
|
+
{id: "EVENT_NAME", required: false, description: "The name of the event"},
|
196
|
+
{id: "EVENT_LOCATION", required: false, description: "The location of the event"},
|
197
|
+
{id: "EVENT_DATES", required: false, description: "The event dates - this will be formatted properly into \"on DATE\", \"on DATE at TIME\", \"from DATE to DATE\", \"from DATE at TIME to DATE at TIME\" etc."},
|
198
|
+
{id: "EVENT_DETAILS", required: false, description: "This is the \"Details for My.SCOUT\" section of the event"},
|
199
|
+
{id: "CONFIRMATION_DEADLINE", required: false, description: "The confirmation deadline - beyond which, parents will not be able to sign up through My.SCOUT"},
|
200
|
+
{id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
|
201
|
+
{id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
|
202
|
+
]},
|
203
|
+
{title: "Invitation to system", id: "email-invitation", description: "This email is sent to invite parents into the system - they will receive a private link that avoids the need to login.", tags:[
|
204
|
+
{id: "DIRECT_LINK", required: true, description: "A direct link into the parent system that avoids the need for the parents to login."},
|
205
|
+
{id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
|
206
|
+
{id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
|
207
|
+
]},
|
208
|
+
{title: "Parent rota reminder email", id: "email-rota-reminder", description: "This email informs parents that they are signed up to the rota and is sent the day before the meeting", tags:[
|
209
|
+
{id: "PROGRAMME_TITLE", required: false, description: "The title of programme"},
|
210
|
+
{id: "PROGRAMME_falseTES", required: false, description: "falsetes for parents"},
|
211
|
+
{id: "PROGRAMME_WHEN", required: false, description: "Dates and if specified time of the programme meeting."},
|
212
|
+
{id: "DIRECT_LINK", required: false, description: "A direct link to the programme page that avoids the need for the parents to login."},
|
213
|
+
{id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
|
214
|
+
{id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
|
215
|
+
]},
|
216
|
+
{title: "Badge awarded email", id: "email-badge-awarded", description: "This email is sent to parents whenever badges have been awarded.", tags:[
|
217
|
+
{id: "BADGE_LIST", required: true, description: "The list of badges that have been awarded."},
|
218
|
+
{id: "DIRECT_LINK", required: false, description: "A direct link to the badges page on My.SCOUT that avoids the need for the parents to login."},
|
219
|
+
{id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
|
220
|
+
{id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
|
221
|
+
]},
|
222
|
+
{title: "Request for census information", id: "email-census", description: "This is only sent when a leader clicks the 'Send My.SCOUT email' button in the census aggregator pages.", tags:[
|
223
|
+
{id: "DIRECT_LINK", required: true, description: "A direct link to the census."},
|
224
|
+
{id: "MEMBER_FIRSTNAME", required: true, description: "The member's first name."},
|
225
|
+
{id: "MEMBER_LASTNAME", required: false, description:"The member's last name."},
|
226
|
+
]},
|
227
|
+
{title: "Gift Aid Declaration", id: "email-giftaid", description: "This email asks parents to update their Gift Aid declaration details on My.SCOUT (this is a free feature for Gold users)", tags:[
|
228
|
+
{id: "DIRECT_LINK", required: false, description: "A direct link to the programme page that avoids the need for the parents to login."},
|
229
|
+
{id: "MEMBER_FIRSTNAME", required: false, description: "The member's first name."},
|
230
|
+
{id: "MEMBER_LASTNAME", required: false, description: "The member's last name."},
|
231
|
+
]},
|
232
|
+
]
|
233
|
+
|
234
|
+
VALID_TEMPLATE_IDS = TEMPLATES.map{ |t| t[:id] }
|
235
|
+
|
236
|
+
|
237
|
+
# Get a template
|
238
|
+
# @param [Osm::Api] api The api to use to make the request
|
239
|
+
# @param [Osm::Section, Fixnum, #to_i] section The section (or its ID) to get login history for
|
240
|
+
# @param [String] id The ID of the template to get
|
241
|
+
# @!macro options_get
|
242
|
+
# @return [String, nil]
|
243
|
+
def self.get_template(api, section, id, options={})
|
244
|
+
fail ArgumentError, "Invalid template ID: #{id.inspect}" unless VALID_TEMPLATE_IDS.include?(id)
|
245
|
+
|
246
|
+
section_id = section.to_i
|
247
|
+
require_ability_to(api, :read, :user, section, options)
|
248
|
+
cache_key = ['myscout', 'template', section_id, id]
|
249
|
+
|
250
|
+
if !options[:no_cache] && cache_exist?(api, cache_key)
|
251
|
+
return cache_read(api, cache_key)
|
252
|
+
end
|
253
|
+
|
254
|
+
data = api.perform_query("ext/settings/parents/?action=getTemplate&key=#{id}§ion_id=#{section_id}")
|
255
|
+
content = data.is_a?(Hash) ? data['data'] : ''
|
256
|
+
return nil if content.empty?
|
257
|
+
|
258
|
+
cache_write(api, cache_key, content)
|
259
|
+
return content
|
260
|
+
end
|
261
|
+
|
262
|
+
# Update a template in OSM
|
263
|
+
# @param [Osm::Api] api The api to use to make the request
|
264
|
+
# @param [Osm::Section, Fixnum, #to_i] section The section (or its ID) to get login history for
|
265
|
+
# @param [String] id The ID of the template to get
|
266
|
+
# @param [String] content The new content of the template
|
267
|
+
# @return [Boolean] Wheter OSM reported the template as updated
|
268
|
+
def self.update_template(api, section, id, content)
|
269
|
+
fail ArgumentError, "Invalid template ID: #{id.inspect}" unless VALID_TEMPLATE_IDS.include?(id)
|
270
|
+
|
271
|
+
section_id = section.to_i
|
272
|
+
require_ability_to(api, :write, :user, section)
|
273
|
+
|
274
|
+
# Make sure required tags are present
|
275
|
+
tags = Osm::Myscout::Template::TEMPLATES.find{ |t| t[:id].eql?(id) }[:tags]
|
276
|
+
fail Osm::Error, "Couldn't find tags for template" if tags.nil?
|
277
|
+
tags.select{ |tag| tag[:required] }.each do |tag|
|
278
|
+
unless content.include?("[#{tag[:id]}]")
|
279
|
+
message = "Required tag [#{tag[:id]}] not found in template content."
|
280
|
+
fail ArgumentError, message
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
data = api.perform_query('ext/settings/parents/?action=updateTemplate', {
|
285
|
+
'section_id' => section_id,
|
286
|
+
'key' => id,
|
287
|
+
'value' => content
|
288
|
+
})
|
289
|
+
|
290
|
+
if data.is_a?(Hash) && data['status'] && data['data']
|
291
|
+
cache_key = ['myscout', 'template', section_id, id]
|
292
|
+
cache_write(api, cache_key, content)
|
293
|
+
return true
|
294
|
+
end
|
295
|
+
|
296
|
+
return false
|
297
|
+
end
|
298
|
+
|
299
|
+
# Restore a template to OSM's default for it
|
300
|
+
# @param [Osm::Api] api The api to use to make the request
|
301
|
+
# @param [Osm::Section, Fixnum, #to_i] section The section (or its ID) to get login history for
|
302
|
+
# @param [String] id The ID of the template to get
|
303
|
+
# @param [String] content The new content of the template
|
304
|
+
# @return [String, nil] The content of the template (nil if not restored)
|
305
|
+
def self.restore_template(api, section, id)
|
306
|
+
fail ArgumentError, "Invalid template ID: #{id.inspect}" unless VALID_TEMPLATE_IDS.include?(id)
|
307
|
+
|
308
|
+
section_id = section.to_i
|
309
|
+
require_ability_to(api, :write, :user, section)
|
310
|
+
|
311
|
+
data = api.perform_query('ext/settings/parents/?action=restoreTemplate', {
|
312
|
+
'section_id' => section_id,
|
313
|
+
'key' => id,
|
314
|
+
})
|
315
|
+
|
316
|
+
if data.is_a?(Hash) && data['status']
|
317
|
+
content = data['data']
|
318
|
+
cache_key = ['myscout', 'template', section_id, id]
|
319
|
+
cache_write(api, cache_key, content)
|
320
|
+
return content
|
321
|
+
end
|
322
|
+
|
323
|
+
return nil
|
324
|
+
end
|
325
|
+
|
326
|
+
end # class Myscout::Template
|
327
|
+
|
328
|
+
end
|
329
|
+
|
330
|
+
end
|
data/spec/osm/api_spec.rb
CHANGED
@@ -179,6 +179,11 @@ describe "API" do
|
|
179
179
|
expect{ Osm::Api.authorize('email@example.com', 'password') }.to raise_error(Osm::Error, 'Error message')
|
180
180
|
end
|
181
181
|
|
182
|
+
it "Raises an error if OSM returns an error (as a hash in a hash)" do
|
183
|
+
HTTParty.stub(:post) { OsmTest::DummyHttpResult.new(:response=>{:code=>'200', :body=>'{"error":{"message":"Error message"}}'}) }
|
184
|
+
expect{ Osm::Api.authorize('email@example.com', 'password') }.to raise_error(Osm::Error, 'Error message')
|
185
|
+
end
|
186
|
+
|
182
187
|
it "Raises an error if OSM returns an error (as a plain string)" do
|
183
188
|
HTTParty.stub(:post) { OsmTest::DummyHttpResult.new(:response=>{:code=>'200', :body=>'Error message'}) }
|
184
189
|
expect{ Osm::Api.authorize('email@example.com', 'password') }.to raise_error(Osm::Error, 'Error message')
|
@@ -0,0 +1,539 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe "Email" do
|
5
|
+
|
6
|
+
describe "Get emails for contacts" do
|
7
|
+
|
8
|
+
it "Single member" do
|
9
|
+
@api.should_receive(:perform_query).with("/ext/members/email/?action=getSelectedEmailsFromContacts§ionid=1&scouts=2", {"contactGroups" => '["contact_primary_member"]'}){
|
10
|
+
{
|
11
|
+
"emails"=>{
|
12
|
+
"2"=>{
|
13
|
+
"emails"=>["john@example.com"],
|
14
|
+
"firstname"=>"John",
|
15
|
+
"lastname"=>"Smith"
|
16
|
+
}
|
17
|
+
},
|
18
|
+
"count"=>1
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
result = Osm::Email.get_emails_for_contacts(@api, 1, :member, 2)
|
23
|
+
result.should == {
|
24
|
+
'2' => {
|
25
|
+
'emails' => ['john@example.com'],
|
26
|
+
'firstname' => 'John',
|
27
|
+
'lastname' => 'Smith'
|
28
|
+
}
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
it "Several members" do
|
33
|
+
@api.should_receive(:perform_query).with("/ext/members/email/?action=getSelectedEmailsFromContacts§ionid=1&scouts=2,3", {"contactGroups" => '["contact_primary_member"]'}){
|
34
|
+
{
|
35
|
+
"emails"=>{
|
36
|
+
"2"=>{
|
37
|
+
"emails"=>["john@example.com"],
|
38
|
+
"firstname"=>"John",
|
39
|
+
"lastname"=>"Smith"
|
40
|
+
},
|
41
|
+
"3"=>{
|
42
|
+
"emails"=>["jane@example.com","jane2@example.com"],
|
43
|
+
"firstname"=>"Jane",
|
44
|
+
"lastname"=>"Smith"
|
45
|
+
}
|
46
|
+
},
|
47
|
+
"count"=>3
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
result = Osm::Email.get_emails_for_contacts(@api, 1, :member, [2,3])
|
52
|
+
result.should == {
|
53
|
+
'2' => {
|
54
|
+
'emails' => ['john@example.com'],
|
55
|
+
'firstname' => 'John',
|
56
|
+
'lastname' => 'Smith'
|
57
|
+
},
|
58
|
+
'3' => {
|
59
|
+
'emails' => ['jane@example.com', 'jane2@example.com'],
|
60
|
+
'firstname' => 'Jane',
|
61
|
+
'lastname' => 'Smith'
|
62
|
+
}
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
it "Requires at least one contact" do
|
67
|
+
@api.should_not_receive(:perform_query)
|
68
|
+
expect{ Osm::Email.get_emails_for_contacts(@api, 1, [], [2]) }.to raise_error ArgumentError, "You must pass at least one contact"
|
69
|
+
end
|
70
|
+
|
71
|
+
it "Checks for invalid contacts" do
|
72
|
+
@api.should_not_receive(:perform_query)
|
73
|
+
expect{ Osm::Email.get_emails_for_contacts(@api, 1, [:invalid_contact], [2]) }.to raise_error ArgumentError, "Invalid contact - :invalid_contact"
|
74
|
+
end
|
75
|
+
|
76
|
+
it "Requires at least one member" do
|
77
|
+
@api.should_not_receive(:perform_query)
|
78
|
+
expect{ Osm::Email.get_emails_for_contacts(@api, 1, [:primary], []) }.to raise_error ArgumentError, "You must pass at least one member"
|
79
|
+
end
|
80
|
+
|
81
|
+
end # describe Get emails for conatcts
|
82
|
+
|
83
|
+
describe "Send email" do
|
84
|
+
|
85
|
+
it "With cc" do
|
86
|
+
@api.should_receive(:perform_query).with("ext/members/email/?action=send", {
|
87
|
+
'sectionid' => 1,
|
88
|
+
'emails' => '{"2":{"firstname":"John","lastname":"Smith","emails":["john@example.com"]}}',
|
89
|
+
'scouts' => '2',
|
90
|
+
'cc' => 'cc@example.com',
|
91
|
+
'from' => 'Sender <from@example.com>',
|
92
|
+
'subject' => 'Subject of email',
|
93
|
+
'body' => 'Body of email',
|
94
|
+
}){ {'ok'=>true} }
|
95
|
+
|
96
|
+
Osm::Email.send_email(
|
97
|
+
@api,
|
98
|
+
1,
|
99
|
+
{'2'=>{'firstname'=>'John', 'lastname'=>'Smith', 'emails'=>['john@example.com']}},
|
100
|
+
'cc@example.com',
|
101
|
+
'Sender <from@example.com>',
|
102
|
+
'Subject of email',
|
103
|
+
'Body of email',
|
104
|
+
).should == true
|
105
|
+
end
|
106
|
+
|
107
|
+
it "Without cc" do
|
108
|
+
@api.should_receive(:perform_query).with("ext/members/email/?action=send", {
|
109
|
+
'sectionid' => 1,
|
110
|
+
'emails' => '{"2":{"firstname":"John","lastname":"Smith","emails":["john@example.com"]}}',
|
111
|
+
'scouts' => '2',
|
112
|
+
'cc' => '',
|
113
|
+
'from' => 'Sender <from@example.com>',
|
114
|
+
'subject' => 'Subject of email',
|
115
|
+
'body' => 'Body of email',
|
116
|
+
}){ {'ok'=>true} }
|
117
|
+
|
118
|
+
Osm::Email.send_email(
|
119
|
+
@api,
|
120
|
+
1,
|
121
|
+
{'2'=>{'firstname'=>'John', 'lastname'=>'Smith', 'emails'=>['john@example.com']}},
|
122
|
+
'Sender <from@example.com>',
|
123
|
+
'Subject of email',
|
124
|
+
'Body of email',
|
125
|
+
).should == true
|
126
|
+
end
|
127
|
+
|
128
|
+
it "To several members" do
|
129
|
+
@api.should_receive(:perform_query).with("ext/members/email/?action=send", {
|
130
|
+
'sectionid' => 1,
|
131
|
+
'emails' => '{"2":{"firstname":"John","lastname":"Smith","emails":["john@example.com"]},"3":{"firstname":"Jane","lastname":"Smith","emails":["jane@example.com"]}}',
|
132
|
+
'scouts' => '2,3',
|
133
|
+
'cc' => '',
|
134
|
+
'from' => 'Sender <from@example.com>',
|
135
|
+
'subject' => 'Subject of email',
|
136
|
+
'body' => 'Body of email',
|
137
|
+
}){ {'ok'=>true} }
|
138
|
+
|
139
|
+
Osm::Email.send_email(
|
140
|
+
@api,
|
141
|
+
1,
|
142
|
+
{'2'=>{'firstname'=>'John', 'lastname'=>'Smith', 'emails'=>['john@example.com']},'3'=>{'firstname'=>'Jane', 'lastname'=>'Smith', 'emails'=>['jane@example.com']}},
|
143
|
+
'Sender <from@example.com>',
|
144
|
+
'Subject of email',
|
145
|
+
'Body of email',
|
146
|
+
).should == true
|
147
|
+
end
|
148
|
+
|
149
|
+
end # describe Send email
|
150
|
+
|
151
|
+
|
152
|
+
describe "DeliveryReport" do
|
153
|
+
|
154
|
+
describe "Attribute validity -" do
|
155
|
+
|
156
|
+
before :each do
|
157
|
+
@report = Osm::Email::DeliveryReport.new(
|
158
|
+
id: 1,
|
159
|
+
section_id: 1,
|
160
|
+
sent_at: Time.new(2016, 10, 27, 13, 0),
|
161
|
+
subject: 'Subject line of email',
|
162
|
+
recipients: [],
|
163
|
+
)
|
164
|
+
end
|
165
|
+
|
166
|
+
%w{id section_id}.each do |attribute|
|
167
|
+
it attribute do
|
168
|
+
@report.send("#{attribute}=", 0)
|
169
|
+
@report.valid?.should == false
|
170
|
+
@report.errors.messages[attribute.to_sym].should == ["must be greater than 0"]
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
%w{sent_at subject}.each do |attribute|
|
175
|
+
it attribute do
|
176
|
+
@report.send("#{attribute}=", nil)
|
177
|
+
@report.valid?.should == false
|
178
|
+
@report.errors.messages[attribute.to_sym].should == ["can't be blank"]
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
describe "recipients" do
|
183
|
+
|
184
|
+
it "Empty array allowed" do
|
185
|
+
@report.recipients = []
|
186
|
+
@report.valid?.should == true
|
187
|
+
@report.errors.messages[:recipients].should == nil
|
188
|
+
end
|
189
|
+
|
190
|
+
it "Invalid item in array not allowed" do
|
191
|
+
@report.recipients = [Osm::Email::DeliveryReport::Recipient.new()]
|
192
|
+
@report.valid?.should == false
|
193
|
+
@report.errors.messages[:recipients].should == ["contains an invalid item"]
|
194
|
+
end
|
195
|
+
|
196
|
+
it "Something other than a recipient not allowed" do
|
197
|
+
@report.recipients = [Time.now]
|
198
|
+
@report.valid?.should == false
|
199
|
+
@report.errors.messages[:recipients].should == ["items in the Array must be a Osm::Email::DeliveryReport::Recipient"]
|
200
|
+
end
|
201
|
+
|
202
|
+
end # describe Email -> DeliveryReport : Invalid without : Recipients
|
203
|
+
|
204
|
+
end # describe Email -> DeliveryReport : Invalid without
|
205
|
+
|
206
|
+
|
207
|
+
it "Fetch delivery reports from OSM" do
|
208
|
+
response = [
|
209
|
+
{'id'=>"0", 'name'=>"ALL", 'type'=>"all", 'count'=>47},
|
210
|
+
{'id'=>123, 'name'=>'01/02/2003 04:05 - Subject of email - 1', 'type'=>'email', 'parent'=>'0', 'hascontent'=>true, 'errors'=>0, 'opens'=>0, 'warnings'=>0},
|
211
|
+
{'id'=>'123-1', 'name'=>'a@example.com - delivered', 'type'=>'oneEmail', 'status'=>'delivered', 'email'=>'a@example.com', 'email_key'=>'aexamplecom', 'hascontent'=>true, 'member_id'=>'12', 'parent'=>123, 'status_raw'=>'delivered'},
|
212
|
+
{'id'=>'123-2', 'name'=>'b@example.com - processed', 'type'=>'oneEmail', 'status'=>'processed', 'email'=>'b@example.com', 'email_key'=>'bexamplecom', 'hascontent'=>true, 'member_id'=>'23', 'parent'=>123, 'status_raw'=>'processed'},
|
213
|
+
{'id'=>'123-3', 'name'=>'c@example.com - bounced', 'type'=>'oneEmail', 'status'=>'bounced', 'email'=>'c@example.com', 'email_key'=>'cexamplecom', 'hascontent'=>true, 'member_id'=>'34', 'parent'=>123, 'status_raw'=>'bounced'},
|
214
|
+
]
|
215
|
+
|
216
|
+
HTTParty.should_receive(:post).with('https://www.onlinescoutmanager.co.uk/ext/settings/emails/?action=getDeliveryReport§ionid=1234', {:body => {
|
217
|
+
'apiid' => @CONFIGURATION[:api][:osm][:id],
|
218
|
+
'token' => @CONFIGURATION[:api][:osm][:token],
|
219
|
+
'userid' => 'user_id',
|
220
|
+
'secret' => 'secret',
|
221
|
+
}}).once { OsmTest::DummyHttpResult.new(:response=>{:code=>'200', :body=>response.to_json}) }
|
222
|
+
|
223
|
+
reports = Osm::Email::DeliveryReport.get_for_section(@api, 1234)
|
224
|
+
reports.count.should == 1
|
225
|
+
report = reports[0]
|
226
|
+
report.id.should == 123
|
227
|
+
report.sent_at.should == Time.new(2003, 2, 1, 4, 5)
|
228
|
+
report.subject.should == 'Subject of email - 1'
|
229
|
+
report.section_id.should == 1234
|
230
|
+
|
231
|
+
report.recipients.count.should == 3
|
232
|
+
recipients = report.recipients.sort{ |a,b| a.id <=> b.id }
|
233
|
+
recipients[0].delivery_report.should == report
|
234
|
+
recipients[0].id.should == 1
|
235
|
+
recipients[0].member_id.should == 12
|
236
|
+
recipients[0].address.should == 'a@example.com'
|
237
|
+
recipients[0].status.should == :delivered
|
238
|
+
recipients[1].delivery_report.should == report
|
239
|
+
recipients[1].id.should == 2
|
240
|
+
recipients[1].member_id.should == 23
|
241
|
+
recipients[1].address.should == 'b@example.com'
|
242
|
+
recipients[1].status.should == :processed
|
243
|
+
recipients[2].delivery_report.should == report
|
244
|
+
recipients[2].id.should == 3
|
245
|
+
recipients[2].member_id.should == 34
|
246
|
+
recipients[2].address.should == 'c@example.com'
|
247
|
+
recipients[2].status.should == :bounced
|
248
|
+
end
|
249
|
+
|
250
|
+
it "Fetch email from OSM" do
|
251
|
+
email = Osm::Email::DeliveryReport::Email.new
|
252
|
+
report = Osm::Email::DeliveryReport.new(id: 3, section_id: 4)
|
253
|
+
|
254
|
+
Osm::Email::DeliveryReport::Email.should_receive(:fetch_from_osm).with(@api, 4, 3).once{ email }
|
255
|
+
report.get_email(@api).should == email
|
256
|
+
end
|
257
|
+
|
258
|
+
describe "Get recipients of a certain status -" do
|
259
|
+
|
260
|
+
before :each do
|
261
|
+
@processed_recipient = Osm::Email::DeliveryReport::Recipient.new(status: :processed)
|
262
|
+
@delivered_recipient = Osm::Email::DeliveryReport::Recipient.new(status: :delivered)
|
263
|
+
@bounced_recipient = Osm::Email::DeliveryReport::Recipient.new(status: :bounced)
|
264
|
+
|
265
|
+
@reports = Osm::Email::DeliveryReport.new(recipients: [@processed_recipient, @delivered_recipient, @bounced_recipient])
|
266
|
+
end
|
267
|
+
|
268
|
+
%w{processed delivered bounced}.each do |status|
|
269
|
+
it status do
|
270
|
+
returned = @reports.send("#{status}_recipients")
|
271
|
+
returned.should == [instance_variable_get("@#{status}_recipient")]
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
end
|
276
|
+
|
277
|
+
describe "Check for recipients of a certain status -" do
|
278
|
+
|
279
|
+
before :each do
|
280
|
+
@processed_recipient = Osm::Email::DeliveryReport::Recipient.new(status: :processed)
|
281
|
+
@delivered_recipient = Osm::Email::DeliveryReport::Recipient.new(status: :delivered)
|
282
|
+
@bounced_recipient = Osm::Email::DeliveryReport::Recipient.new(status: :bounced)
|
283
|
+
end
|
284
|
+
|
285
|
+
%w{processed delivered bounced}.each do |status|
|
286
|
+
it status do
|
287
|
+
reports = Osm::Email::DeliveryReport.new(recipients: [instance_variable_get("@#{status}_recipient")])
|
288
|
+
reports.send("#{status}_recipients?").should == true
|
289
|
+
|
290
|
+
reports.recipients = []
|
291
|
+
reports.send("#{status}_recipients?").should == false
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
end
|
296
|
+
|
297
|
+
it "Converts to a string" do
|
298
|
+
report = Osm::Email::DeliveryReport.new(sent_at: Time.new(2016, 4, 17, 11, 50, 45), subject: 'Subject line of email')
|
299
|
+
report.to_s.should == '17/04/2016 11:50 - Subject line of email'
|
300
|
+
end
|
301
|
+
|
302
|
+
it "Sorts by sent_at then id" do
|
303
|
+
report1 = Osm::Email::DeliveryReport.new(sent_at: Time.new(2016), id: 1)
|
304
|
+
report2 = Osm::Email::DeliveryReport.new(sent_at: Time.new(2017), id: 1)
|
305
|
+
report3 = Osm::Email::DeliveryReport.new(sent_at: Time.new(2017), id: 2)
|
306
|
+
reports = [report2, report3, report1]
|
307
|
+
reports.sort.should == [report1, report2, report3]
|
308
|
+
end
|
309
|
+
|
310
|
+
|
311
|
+
describe "Recipient" do
|
312
|
+
|
313
|
+
describe "Attribute validity -" do
|
314
|
+
|
315
|
+
before :each do
|
316
|
+
@recipient = Osm::Email::DeliveryReport::Recipient.new(
|
317
|
+
id: 1,
|
318
|
+
member_id: 1,
|
319
|
+
address: 'someone@example.com',
|
320
|
+
delivery_report: Osm::Email::DeliveryReport.new,
|
321
|
+
status: :processed
|
322
|
+
)
|
323
|
+
end
|
324
|
+
|
325
|
+
%w{id member_id}.each do |attribute|
|
326
|
+
it attribute do
|
327
|
+
@recipient.send("#{attribute}=", 0)
|
328
|
+
@recipient.valid?.should == false
|
329
|
+
@recipient.errors.messages[attribute.to_sym].should == ["must be greater than 0"]
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
it "address" do
|
334
|
+
@recipient.address = nil
|
335
|
+
@recipient.valid?.should == false
|
336
|
+
@recipient.errors.messages[:address].should == ["can't be blank"]
|
337
|
+
end
|
338
|
+
|
339
|
+
describe "status" do
|
340
|
+
[nil, :invalid].each do |status|
|
341
|
+
it "is #{status.inspect}" do
|
342
|
+
@recipient.status = status
|
343
|
+
@recipient.valid?.should == false
|
344
|
+
@recipient.errors.messages[:status].should == ["is not included in the list"]
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
end # describe Email -> DeliveryReport -> Recipient : invalid without
|
350
|
+
|
351
|
+
it "Fetch email from OSM" do
|
352
|
+
email = Osm::Email::DeliveryReport::Email.new
|
353
|
+
report = Osm::Email::DeliveryReport.new(id: 3, section_id: 4)
|
354
|
+
recipient = Osm::Email::DeliveryReport::Recipient.new(member_id: 456, address: 'd@example.com', delivery_report: report)
|
355
|
+
|
356
|
+
Osm::Email::DeliveryReport::Email.should_receive(:fetch_from_osm).with(@api, 4, 3, 456, 'd@example.com').once{ email }
|
357
|
+
recipient.get_email(@api).should == email
|
358
|
+
end
|
359
|
+
|
360
|
+
|
361
|
+
describe "Unblock address in OSM" do
|
362
|
+
it "Success" do
|
363
|
+
recipient = Osm::Email::DeliveryReport::Recipient.new(address: 'a@example.com', status: :bounced, delivery_report: Osm::Email::DeliveryReport.new(id: 2, section_id: 1))
|
364
|
+
@api.should_receive(:perform_query).once.with('ext/settings/emails/?action=unBlockEmail', {"section_id"=>1, "email"=>"a@example.com", "email_id"=>2}){ {'status'=>true} }
|
365
|
+
recipient.unblock_address(@api).should == true
|
366
|
+
end
|
367
|
+
|
368
|
+
it "Fails with error message" do
|
369
|
+
recipient = Osm::Email::DeliveryReport::Recipient.new(address: 'a@example.com', status: :bounced, delivery_report: Osm::Email::DeliveryReport.new(id: 2, section_id: 1))
|
370
|
+
@api.should_receive(:perform_query).once.with('ext/settings/emails/?action=unBlockEmail', {"section_id"=>1, "email"=>"a@example.com", "email_id"=>2}){ {'status'=>false, 'error'=>'Error message'} }
|
371
|
+
expect{ recipient.unblock_address(@api) }.to raise_error(Osm::Error, 'Error message')
|
372
|
+
end
|
373
|
+
|
374
|
+
it "Fails without error message" do
|
375
|
+
recipient = Osm::Email::DeliveryReport::Recipient.new(address: 'a@example.com', status: :bounced, delivery_report: Osm::Email::DeliveryReport.new(id: 2, section_id: 1))
|
376
|
+
@api.should_receive(:perform_query).once.with('ext/settings/emails/?action=unBlockEmail', {"section_id"=>1, "email"=>"a@example.com", "email_id"=>2}){ {'status'=>false} }
|
377
|
+
recipient.unblock_address(@api).should == false
|
378
|
+
end
|
379
|
+
|
380
|
+
it "Gets something other than a hash" do
|
381
|
+
recipient = Osm::Email::DeliveryReport::Recipient.new(address: 'a@example.com', status: :bounced, delivery_report: Osm::Email::DeliveryReport.new(id: 2, section_id: 1))
|
382
|
+
@api.should_receive(:perform_query).once.with('ext/settings/emails/?action=unBlockEmail', {"section_id"=>1, "email"=>"a@example.com", "email_id"=>2}){ [] }
|
383
|
+
recipient.unblock_address(@api).should == false
|
384
|
+
end
|
385
|
+
|
386
|
+
describe "Doesn't try to unblock when status is" do
|
387
|
+
|
388
|
+
before :each do
|
389
|
+
@recipient = Osm::Email::DeliveryReport::Recipient.new(address: 'a@example.com', delivery_report: Osm::Email::DeliveryReport.new(id: 2, section_id: 1))
|
390
|
+
@api.should_not_receive(:perform_query)
|
391
|
+
end
|
392
|
+
|
393
|
+
(Osm::Email::DeliveryReport::VALID_STATUSES - [:bounced]).each do |status|
|
394
|
+
it status do
|
395
|
+
@recipient.status = status
|
396
|
+
@recipient.unblock_address(@api).should == true
|
397
|
+
end
|
398
|
+
end # each status
|
399
|
+
end
|
400
|
+
|
401
|
+
end # unlock address in OSM
|
402
|
+
|
403
|
+
describe "Check status helpers -" do
|
404
|
+
before :each do
|
405
|
+
@processed_recipient = Osm::Email::DeliveryReport::Recipient.new(status: :processed)
|
406
|
+
@delivered_recipient = Osm::Email::DeliveryReport::Recipient.new(status: :delivered)
|
407
|
+
@bounced_recipient = Osm::Email::DeliveryReport::Recipient.new(status: :bounced)
|
408
|
+
end
|
409
|
+
|
410
|
+
it "processed?" do
|
411
|
+
@processed_recipient.processed?.should == true
|
412
|
+
@delivered_recipient.processed?.should == false
|
413
|
+
@bounced_recipient.processed?.should == false
|
414
|
+
end
|
415
|
+
|
416
|
+
it "delivered?" do
|
417
|
+
@processed_recipient.delivered?.should == false
|
418
|
+
@delivered_recipient.delivered?.should == true
|
419
|
+
@bounced_recipient.delivered?.should == false
|
420
|
+
end
|
421
|
+
|
422
|
+
it "bounced?" do
|
423
|
+
@processed_recipient.bounced?.should == false
|
424
|
+
@delivered_recipient.bounced?.should == false
|
425
|
+
@bounced_recipient.bounced?.should == true
|
426
|
+
end
|
427
|
+
|
428
|
+
end
|
429
|
+
|
430
|
+
it "Converts to a string" do
|
431
|
+
recipient = Osm::Email::DeliveryReport::Recipient.new(address: 'recipient@example.com', status: :delivered)
|
432
|
+
recipient.to_s.should == 'recipient@example.com - delivered'
|
433
|
+
end
|
434
|
+
|
435
|
+
it "Sorts by delivery_report then id" do
|
436
|
+
report1 = Osm::Email::DeliveryReport.new(id: 1)
|
437
|
+
report2 = Osm::Email::DeliveryReport.new(id: 2)
|
438
|
+
|
439
|
+
recipient1 = Osm::Email::DeliveryReport::Recipient.new(delivery_report: report1, id: 1)
|
440
|
+
recipient2 = Osm::Email::DeliveryReport::Recipient.new(delivery_report: report2, id: 1)
|
441
|
+
recipient3 = Osm::Email::DeliveryReport::Recipient.new(delivery_report: report2, id: 2)
|
442
|
+
|
443
|
+
recipients = [recipient3, recipient1, recipient2]
|
444
|
+
recipients.sort.should == [recipient1, recipient2, recipient3]
|
445
|
+
end
|
446
|
+
|
447
|
+
end # describe Email -> DeliveryReport -> Recipient
|
448
|
+
|
449
|
+
describe "Email" do
|
450
|
+
|
451
|
+
describe "Attribute validity -" do
|
452
|
+
before :each do
|
453
|
+
@email = Osm::Email::DeliveryReport::Email.new(
|
454
|
+
to: 'to@example.com',
|
455
|
+
from: 'from@example.com',
|
456
|
+
subject: 'Subject of email',
|
457
|
+
body: 'Body of email message.',
|
458
|
+
)
|
459
|
+
end
|
460
|
+
%w{to from subject body}.each do |attribute|
|
461
|
+
it attribute do
|
462
|
+
@email.send("#{attribute}=", nil)
|
463
|
+
@email.valid?.should == false
|
464
|
+
@email.errors.messages[attribute.to_sym].should == ["can't be blank"]
|
465
|
+
end
|
466
|
+
end
|
467
|
+
end # describe Email -> DeliveryReport -> Email : invalid without
|
468
|
+
|
469
|
+
it "Converts to a string" do
|
470
|
+
email = Osm::Email::DeliveryReport::Email.new(
|
471
|
+
to: 'to@example.com',
|
472
|
+
from: '"Sender" <from@example.com>',
|
473
|
+
subject: 'What the email is about',
|
474
|
+
body: '<p>Hello person.</p>'
|
475
|
+
)
|
476
|
+
email.to_s.should == "To: to@example.com\nFrom: \"Sender\" <from@example.com>\n\nWhat the email is about\n\nHello person."
|
477
|
+
end
|
478
|
+
|
479
|
+
it "Sorts by subject then from then to" do
|
480
|
+
email1 = Osm::Email::DeliveryReport::Email.new(subject: 'a', from: 'a', to: 'a')
|
481
|
+
email2 = Osm::Email::DeliveryReport::Email.new(subject: 'b', from: 'a', to: 'a')
|
482
|
+
email3 = Osm::Email::DeliveryReport::Email.new(subject: 'b', from: 'b', to: 'a')
|
483
|
+
email4 = Osm::Email::DeliveryReport::Email.new(subject: 'b', from: 'b', to: 'b')
|
484
|
+
|
485
|
+
emails = [email2, email3, email4, email1]
|
486
|
+
emails.sort.should == [email1, email2, email3, email4]
|
487
|
+
end
|
488
|
+
|
489
|
+
describe "Fetch email from OSM" do
|
490
|
+
|
491
|
+
it "For a delivery report" do
|
492
|
+
@api.should_receive(:perform_query).with('ext/settings/emails/?action=getSentEmail§ion_id=1&email_id=2&email=&member_id=').once{ {'data'=>{'to'=>'1 Recipient', 'from'=>'"From" <from@example.com>', 'subject'=>'Subject of email', 'sent'=>'16/04/2016 13:45'}, 'status'=>true, 'error'=>nil, 'meta'=>[]} }
|
493
|
+
@api.should_receive(:perform_query).with('ext/settings/emails/?action=getSentEmailContent§ion_id=1&email_id=2&email=&member_id=', {}, true).once{ 'This is the body of the email.' }
|
494
|
+
|
495
|
+
email = Osm::Email::DeliveryReport::Email.fetch_from_osm(@api, 1, 2)
|
496
|
+
email.to.should == '1 Recipient'
|
497
|
+
email.from.should == '"From" <from@example.com>'
|
498
|
+
email.subject.should == 'Subject of email'
|
499
|
+
email.body.should == 'This is the body of the email.'
|
500
|
+
end
|
501
|
+
|
502
|
+
it "For a recipient" do
|
503
|
+
@api.should_receive(:perform_query).with('ext/settings/emails/?action=getSentEmail§ion_id=1&email_id=2&email=to@example.com&member_id=3').once{ {'data'=>{'to'=>'to@example.com', 'from'=>'"From" <from@example.com>', 'subject'=>'Subject of email', 'sent'=>'16/04/2016 13:45'}, 'status'=>true, 'error'=>nil, 'meta'=>[]} }
|
504
|
+
@api.should_receive(:perform_query).with('ext/settings/emails/?action=getSentEmailContent§ion_id=1&email_id=2&email=to@example.com&member_id=3', {}, true).once{ 'This is the body of the email.' }
|
505
|
+
|
506
|
+
email = Osm::Email::DeliveryReport::Email.fetch_from_osm(@api, 1, 2, 3, 'to@example.com')
|
507
|
+
email.to.should == 'to@example.com'
|
508
|
+
email.from.should == '"From" <from@example.com>'
|
509
|
+
email.subject.should == 'Subject of email'
|
510
|
+
email.body.should == 'This is the body of the email.'
|
511
|
+
end
|
512
|
+
|
513
|
+
describe "Error getting meta data" do
|
514
|
+
|
515
|
+
it "Didn't get a Hash" do
|
516
|
+
@api.should_receive(:perform_query).with('ext/settings/emails/?action=getSentEmail§ion_id=1&email_id=2&email=&member_id=').once{ nil }
|
517
|
+
expect{ Osm::Email::DeliveryReport::Email.fetch_from_osm(@api, 1, 2) }.to raise_error Osm::Error, 'Unexpected format for response - got a NilClass'
|
518
|
+
end
|
519
|
+
|
520
|
+
it "Got an error from OSM" do
|
521
|
+
@api.should_receive(:perform_query).with('ext/settings/emails/?action=getSentEmail§ion_id=1&email_id=2&email=&member_id=').once{ {'success'=>false, 'error'=>'Error message'} }
|
522
|
+
expect{ Osm::Email::DeliveryReport::Email.fetch_from_osm(@api, 1, 2) }.to raise_error Osm::Error, 'Error message'
|
523
|
+
end
|
524
|
+
|
525
|
+
end
|
526
|
+
|
527
|
+
it "Error getting body" do
|
528
|
+
@api.should_receive(:perform_query).with('ext/settings/emails/?action=getSentEmail§ion_id=1&email_id=2&email=&member_id=').once{ {'data'=>{'to'=>'1 Recipient', 'from'=>'"From" <from@example.com>', 'subject'=>'Subject of email', 'sent'=>'16/04/2016 13:45'}, 'status'=>true, 'error'=>nil, 'meta'=>[]} }
|
529
|
+
@api.should_receive(:perform_query).with('ext/settings/emails/?action=getSentEmailContent§ion_id=1&email_id=2&email=&member_id=', {}, true).once{ raise Osm::Forbidden, 'Email not found' }
|
530
|
+
expect{ Osm::Email::DeliveryReport::Email.fetch_from_osm(@api, 1, 2) }.to raise_error Osm::Error, 'Email not found'
|
531
|
+
end
|
532
|
+
|
533
|
+
end # describe Email -> DeliveryReport -> Email : fetch email from osm
|
534
|
+
|
535
|
+
end # describe Email -> DeliveryReport -> Email
|
536
|
+
|
537
|
+
end # describe Email -> DeliveryReport
|
538
|
+
|
539
|
+
end
|