osm 1.2.25 → 1.3.0
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 +7 -0
- data/lib/osm.rb +1 -1
- data/lib/osm/event.rb +11 -2
- data/lib/osm/online_payment.rb +521 -0
- data/osm.gemspec +1 -0
- data/spec/osm/event_spec.rb +12 -0
- data/spec/osm/online_payment_spec.rb +490 -0
- data/version.rb +1 -1
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 651a0cdcdd3d694935cd01e1500494bf8cd4c7cf
|
4
|
+
data.tar.gz: 3e28fa840b8b180292c469f068f6667c01f9bbc9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6a31dd0a2da75b15f7c53fb2346e238d0044c3ecca6f04ad14c49bd06818f856987d185474f88a016b76f5df76e889e10464012ace57829bad3d6e049cf8c617
|
7
|
+
data.tar.gz: 0bf8a3ac116819ddda8b030c5caad9b6e77896be6b0e9d075ff92905bc82fda39c536d9ca215d58e221a1e40e9e5bbbba830feaff57abda82488c8e84d4f934b
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
## Version 1.3.0
|
2
|
+
|
3
|
+
* Add fetching of file names for events (unable to download)
|
4
|
+
* Add fetching of payment schedules - Osm::OnlinePayment::Schedule
|
5
|
+
* Add fetching of member's payments for a schedule
|
6
|
+
* Add updating a member's payment status
|
7
|
+
|
1
8
|
## Version 1.2.25
|
2
9
|
|
3
10
|
* Add fetching My.SCOUT parent login history - Osm::Myscout::ParentLoginHistory.get_for_section
|
data/README.md
CHANGED
@@ -113,8 +113,13 @@ however it should be noted that when the OSM API adds a feature it can be diffic
|
|
113
113
|
* Groupings (e.g. Sixes, Patrols)
|
114
114
|
* Invoices (Gold required)
|
115
115
|
* Members
|
116
|
+
* My.SCOUT Templates
|
116
117
|
* Notepad
|
117
118
|
* Notepads
|
119
|
+
* Online Payments:
|
120
|
+
* Schedules
|
121
|
+
* Payment Statuses
|
122
|
+
* Payment Status History
|
118
123
|
* Programme
|
119
124
|
* Register Data
|
120
125
|
* Register Structure
|
@@ -140,6 +145,8 @@ however it should be noted that when the OSM API adds a feature it can be diffic
|
|
140
145
|
* Grouping
|
141
146
|
* Invoices (Gold required)
|
142
147
|
* Member
|
148
|
+
* My.SCOUT Templates
|
149
|
+
* Online payments - payment status
|
143
150
|
* Register Attendance
|
144
151
|
|
145
152
|
### Create
|
data/lib/osm.rb
CHANGED
@@ -174,7 +174,7 @@ module Osm
|
|
174
174
|
replace_with = options[:replace_with] || {}
|
175
175
|
|
176
176
|
values = instance.attributes.sort.map{ |(k,v)|
|
177
|
-
(replace_with.keys.include?(k) && !v.nil?) ? "#{k}.#{replace_with[k]}: #{v.try(replace_with[k])}" : "#{k}: #{v.inspect}"
|
177
|
+
(replace_with.keys.include?(k) && !v.nil?) ? "#{k}.#{replace_with[k]}: #{v.try(replace_with[k]).inspect}" : "#{k}: #{v.inspect}"
|
178
178
|
}
|
179
179
|
|
180
180
|
return "#<#{instance.class.name} #{values.join(', ')} >"
|
data/lib/osm/event.rb
CHANGED
@@ -28,6 +28,8 @@ module Osm
|
|
28
28
|
# @return [Boolean] if the event has been archived
|
29
29
|
# @!attribute [rw] badges
|
30
30
|
# @return [Array<Osm::Event::BadgeLink>] the badge links for the event
|
31
|
+
# @!attribute [rw] files
|
32
|
+
# @return [Array<String>] the files attached to this event
|
31
33
|
# @!attribute [rw] columns
|
32
34
|
# @return [Array<Osm::Event::Column>] the custom columns for the event
|
33
35
|
# @!attribute [rw] notepad
|
@@ -59,6 +61,7 @@ module Osm
|
|
59
61
|
attribute :notes, :type => String, :default => ''
|
60
62
|
attribute :archived, :type => Boolean, :default => false
|
61
63
|
attribute :badges, :default => []
|
64
|
+
attribute :files, :default => []
|
62
65
|
attribute :columns, :default => []
|
63
66
|
attribute :notepad, :type => String, :default => ''
|
64
67
|
attribute :public_notepad, :type => String, :default => ''
|
@@ -72,8 +75,8 @@ module Osm
|
|
72
75
|
|
73
76
|
if ActiveModel::VERSION::MAJOR < 4
|
74
77
|
attr_accessible :id, :section_id, :name, :start, :finish, :cost, :location, :notes, :archived,
|
75
|
-
:fields, :badges, :columns, :notepad, :public_notepad, :confirm_by_date,
|
76
|
-
:reminders, :attendance_limit, :attendance_limit_includes_leaders,
|
78
|
+
:fields, :badges, :files, :columns, :notepad, :public_notepad, :confirm_by_date,
|
79
|
+
:allow_changes, :reminders, :attendance_limit, :attendance_limit_includes_leaders,
|
77
80
|
:attendance_reminder, :allow_booking
|
78
81
|
end
|
79
82
|
|
@@ -83,6 +86,7 @@ module Osm
|
|
83
86
|
validates_presence_of :name
|
84
87
|
validates :badges, :array_of => {:item_type => Osm::Event::BadgeLink, :item_valid => true}
|
85
88
|
validates :columns, :array_of => {:item_type => Osm::Event::Column, :item_valid => true}
|
89
|
+
validates :files, :array_of => {:item_type => String}
|
86
90
|
validates_inclusion_of :allow_changes, :in => [true, false]
|
87
91
|
validates_inclusion_of :reminders, :in => [true, false]
|
88
92
|
validates_inclusion_of :attendance_limit_includes_leaders, :in => [true, false]
|
@@ -120,7 +124,12 @@ module Osm
|
|
120
124
|
unless data['items'].nil?
|
121
125
|
data['items'].map { |i| i['eventid'].to_i }.each do |event_id|
|
122
126
|
event_data = api.perform_query("events.php?action=getEvent§ionid=#{section_id}&eventid=#{event_id}")
|
127
|
+
files_data = api.perform_query("ext/uploads/events/?action=listAttachments§ionid=#{section_id}&eventid=#{event_id}")
|
128
|
+
files = files_data.is_a?(Hash) ? files_data['files'] : files_data
|
129
|
+
files = [] unless files.is_a?(Array)
|
130
|
+
|
123
131
|
event = self.new_event_from_data(event_data)
|
132
|
+
event.files = files
|
124
133
|
events.push event
|
125
134
|
ids.push event.id
|
126
135
|
cache_write(api, ['event', event.id], event)
|
@@ -0,0 +1,521 @@
|
|
1
|
+
module Osm
|
2
|
+
|
3
|
+
class OnlinePayment
|
4
|
+
|
5
|
+
class Schedule < Osm::Model
|
6
|
+
class Payment < Osm::Model; end # Ensure the constant exists for the validators
|
7
|
+
class PaymentStatus < Osm::Model; end # Ensure the constant exists for validators
|
8
|
+
|
9
|
+
SORT_BY = [:section_id, :name, :id]
|
10
|
+
PAY_NOW_OPTIONS = {
|
11
|
+
-1 => 'Allowed at all times',
|
12
|
+
0 => 'Permanently disabled',
|
13
|
+
7 => 'Allowed within 1 week of due day',
|
14
|
+
14 => 'Allowed within 2 weeks of due day',
|
15
|
+
21 => 'Allowed within 3 weeks of due day',
|
16
|
+
28 => 'Allowed within 4 weeks of due day',
|
17
|
+
42 => 'Allowed within 6 weeks of due day',
|
18
|
+
56 => 'Allowed within 8 weeks of due day',
|
19
|
+
}
|
20
|
+
|
21
|
+
# @!attribute [rw] id
|
22
|
+
# @return [FixNum] the schedule's ID
|
23
|
+
# @!attribute [rw] section_id
|
24
|
+
# @return [FixNum] the ID of the section the schedule belongs to
|
25
|
+
# @!attribute [rw] account_id
|
26
|
+
# @return [FixNum] the ID of the bank account this schedule is tied to
|
27
|
+
# @!attribute [rw] name
|
28
|
+
# @return [String] the name of the schedule
|
29
|
+
# @!attribute [rw] description
|
30
|
+
# @return [String] the description of what the schedule is for
|
31
|
+
# @!attribute [rw] archived
|
32
|
+
# @return [Boolean] whether the schedule has been archived
|
33
|
+
# @!attribute [rw] gift_aid
|
34
|
+
# @return [Boolean] whether payments made using this schedule are eligable for gift aid
|
35
|
+
# @!attribute [rw] require_all
|
36
|
+
# @return [Boolean] whether to require all payments within the schedule by default
|
37
|
+
# @!attribute [rw] pay_now
|
38
|
+
# @return [FixNum] controls the use of the pay now feature in OSM, see the PAY_NOW_OPTIONS hash
|
39
|
+
# @!attribute [rw] annual_limit
|
40
|
+
# @return [String] the maximum amount you'll be able to collect in a rolling 12 month period using this schedule
|
41
|
+
# @!attribute [rw] payments
|
42
|
+
# @return [Array<Payment>] the payments which make up this schedule
|
43
|
+
|
44
|
+
|
45
|
+
attribute :id, type: Integer
|
46
|
+
attribute :section_id, type: Integer
|
47
|
+
attribute :account_id, type: Integer
|
48
|
+
attribute :name, type: String
|
49
|
+
attribute :description, type: String, default: ''
|
50
|
+
attribute :archived, type: Boolean
|
51
|
+
attribute :gift_aid, type: Boolean
|
52
|
+
attribute :require_all, type: Boolean
|
53
|
+
attribute :pay_now, type: Integer
|
54
|
+
attribute :annual_limit, type: String
|
55
|
+
attribute :payments, type: Object, default: []
|
56
|
+
|
57
|
+
if ActiveModel::VERSION::MAJOR < 4
|
58
|
+
attr_accessible :id, :section_id, :account_id, :name, :description, :archived, :gift_aid,
|
59
|
+
:require_all, :pay_now, :annual_limit, :payments
|
60
|
+
end
|
61
|
+
|
62
|
+
validates_numericality_of :id, only_integer: true, greater_than: 0
|
63
|
+
validates_numericality_of :section_id, only_integer: true, greater_than: 0
|
64
|
+
validates_numericality_of :account_id, only_integer: true, greater_than: 0
|
65
|
+
validates_presence_of :annual_limit
|
66
|
+
validates_presence_of :name
|
67
|
+
validates_inclusion_of :pay_now, in: PAY_NOW_OPTIONS.keys
|
68
|
+
validates_inclusion_of :archived, in: [true, false]
|
69
|
+
validates_inclusion_of :gift_aid, in: [true, false]
|
70
|
+
validates_inclusion_of :require_all, in: [true, false]
|
71
|
+
validates :payments, array_of: {item_type: Osm::OnlinePayment::Schedule::Payment, item_valid: true}
|
72
|
+
|
73
|
+
|
74
|
+
# @!method initialize
|
75
|
+
# Initialize a new Schedule
|
76
|
+
# @param [Hash] attributes The hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
|
77
|
+
|
78
|
+
|
79
|
+
# Get a simple list of schedules for a section
|
80
|
+
# @param [Osm::Api] api The api to use to make the request
|
81
|
+
# @param [Osm::Section, Fixnum, #to_i] section The section (or its ID) to get the due badges for
|
82
|
+
# @!macro options_get
|
83
|
+
# @return [Array<Hash>]
|
84
|
+
def self.get_list_for_section(api, section, options={})
|
85
|
+
require_ability_to(api, :read, :finance, section, options)
|
86
|
+
section_id = section.to_i
|
87
|
+
cache_key = ['online_payments', 'schedule_list', section_id]
|
88
|
+
|
89
|
+
if !options[:no_cache] && Osm::Model.cache_exist?(api, cache_key)
|
90
|
+
return cache_read(api, cache_key)
|
91
|
+
end
|
92
|
+
|
93
|
+
data = api.perform_query("ext/finances/onlinepayments/?action=getSchemes§ionid=#{section_id}")
|
94
|
+
data = data.is_a?(Hash) ? data['items'] : nil
|
95
|
+
data ||= []
|
96
|
+
data.map!{ |i| {id: Osm::to_i_or_nil(i['schemeid']), name: i['name'].to_s } }
|
97
|
+
|
98
|
+
cache_write(api, cache_key, data)
|
99
|
+
return data
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
# Get all payment schedules for a section
|
104
|
+
# @param [Osm::Api] api The api to use to make the request
|
105
|
+
# @param [Osm::Section, Fixnum, #to_i] section The section (or its ID) to get the due badges for
|
106
|
+
# @!macro options_get
|
107
|
+
# @return [Array<Osm::OnlinePayment::Schedule>]
|
108
|
+
def self.get_for_section(api, section, options={})
|
109
|
+
require_ability_to(api, :read, :finance, section, options)
|
110
|
+
|
111
|
+
get_list_for_section(api, section, options).map do |schedule|
|
112
|
+
get(api, section, schedule[:id], options)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
# Get a payment schedules for a section
|
118
|
+
# @param [Osm::Api] api The api to use to make the request
|
119
|
+
# @param [Osm::Section, Fixnum, #to_i] section The section (or its ID) to get the due badges for
|
120
|
+
# @param [Fixnum, #to_i] schedule The ID of the payment schedule to get
|
121
|
+
# @!macro options_get
|
122
|
+
# @return [Array<Osm::OnlinePayment::Schedule>]
|
123
|
+
def self.get(api, section, schedule, options={})
|
124
|
+
require_ability_to(api, :read, :finance, section, options)
|
125
|
+
section_id = section.to_i
|
126
|
+
schedule_id = schedule.to_i
|
127
|
+
cache_key = ['online_payments', 'schedule', schedule_id]
|
128
|
+
|
129
|
+
if !options[:no_cache] && cache_exist?(api, cache_key)
|
130
|
+
data = cache_read(api, cache_key)
|
131
|
+
return data if data.section_id.eql?(section_id)
|
132
|
+
end
|
133
|
+
|
134
|
+
data = api.perform_query("ext/finances/onlinepayments/?action=getPaymentSchedule§ionid=#{section_id}&schemeid=#{schedule_id}&allpayments=true")
|
135
|
+
schedule = new(
|
136
|
+
id: Osm::to_i_or_nil(data['schemeid']),
|
137
|
+
section_id: section_id,
|
138
|
+
account_id: Osm::to_i_or_nil(data['accountid']),
|
139
|
+
name: data['name'],
|
140
|
+
description: data['description'],
|
141
|
+
archived: data['archived'].eql?('1'),
|
142
|
+
gift_aid: data['giftaid'].eql?('1'),
|
143
|
+
require_all: data['defaulton'].eql?('1'),
|
144
|
+
pay_now: data['paynow'],
|
145
|
+
annual_limit: data['preauth_amount'],
|
146
|
+
)
|
147
|
+
|
148
|
+
(data['payments'] || []).each do |payment_data|
|
149
|
+
payment = Payment.new(
|
150
|
+
amount: payment_data['amount'],
|
151
|
+
archived: payment_data['archived'].eql?('1'),
|
152
|
+
due_date: Osm::parse_date(payment_data['date']),
|
153
|
+
name: payment_data['name'].to_s,
|
154
|
+
id: Osm::to_i_or_nil(payment_data['paymentid']),
|
155
|
+
schedule: schedule,
|
156
|
+
)
|
157
|
+
schedule.payments.push payment
|
158
|
+
end
|
159
|
+
|
160
|
+
cache_write(api, cache_key, schedule)
|
161
|
+
return schedule
|
162
|
+
end
|
163
|
+
|
164
|
+
|
165
|
+
# Get payments made by members for the schedule
|
166
|
+
# @param [Osm::Api] api The api to use to make the request
|
167
|
+
# @param [Osm::Term, Fixnum, #to_i] term The term (or it's id) to get details for (defaults to current term)
|
168
|
+
# @!macro options_get
|
169
|
+
# @return [Array<Osm::OnlinePayment::Schedule::PaymentsForMember>]
|
170
|
+
def get_payments_for_members(api, term=nil, options={})
|
171
|
+
require_ability_to(api, :read, :finance, section_id, options)
|
172
|
+
|
173
|
+
if term.nil?
|
174
|
+
section = Osm::Section.get(api, section_id, options)
|
175
|
+
term = section.waiting? ? -1 : Osm::Term.get_current_term_for_section(api, section)
|
176
|
+
end
|
177
|
+
|
178
|
+
cache_key = ['online_payments', 'for_members', id, term.to_i]
|
179
|
+
if !options[:no_cache] && cache_exist?(api, cache_key)
|
180
|
+
return cache_read(api, cache_key)
|
181
|
+
end
|
182
|
+
|
183
|
+
data = api.perform_query("ext/finances/onlinepayments/?action=getPaymentStatus§ionid=#{section_id}&schemeid=#{id}&termid=#{term.to_i}")
|
184
|
+
data = data['items'] || []
|
185
|
+
data.map! do |item|
|
186
|
+
payments_data = {}
|
187
|
+
payments.each do |payment|
|
188
|
+
unless item[payment.id.to_s].nil?
|
189
|
+
payments_data[payment.id] = PaymentStatus.build_from_json(item[payment.id.to_s], payment)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
PaymentsForMember.new(
|
194
|
+
member_id: Osm::to_i_or_nil(item['scoutid']),
|
195
|
+
section_id: section_id,
|
196
|
+
grouping_id: Osm::to_i_or_nil(item['patrolid']),
|
197
|
+
first_name: item['firstname'],
|
198
|
+
last_name: item['lastname'],
|
199
|
+
start_date: require_all ? Osm::parse_date(item['startdate']) : nil,
|
200
|
+
direct_debit: item['directdebit'].downcase.to_sym,
|
201
|
+
payments: payments_data,
|
202
|
+
schedule: self,
|
203
|
+
)
|
204
|
+
end
|
205
|
+
|
206
|
+
cache_write(api, cache_key, data)
|
207
|
+
return data
|
208
|
+
end
|
209
|
+
|
210
|
+
|
211
|
+
|
212
|
+
# Get unarchived payments for the schedule
|
213
|
+
# @return [Array<Osm::OnlinePayment::Schedule::Payment>]
|
214
|
+
def current_payments
|
215
|
+
payments.select{ |p| !p.archived? }
|
216
|
+
end
|
217
|
+
# Check if there are any unarchived payments for the schedule
|
218
|
+
# @return [Boolean]
|
219
|
+
def current_payments?
|
220
|
+
payments.any?{ |p| !p.archived? }
|
221
|
+
end
|
222
|
+
|
223
|
+
# Get archived payments for the schedule
|
224
|
+
# @return [Array<Osm::OnlinePayment::Schedule::Payment>]
|
225
|
+
def archived_payments
|
226
|
+
payments.select{ |p| p.archived? }
|
227
|
+
end
|
228
|
+
# Check if there are any archived payments for the schedule
|
229
|
+
# @return [Boolean]
|
230
|
+
def archived_payments?
|
231
|
+
payments.any?{ |p| p.archived? }
|
232
|
+
end
|
233
|
+
|
234
|
+
def to_s
|
235
|
+
"#{id} -> #{name}"
|
236
|
+
end
|
237
|
+
|
238
|
+
|
239
|
+
class Payment < Osm::Model
|
240
|
+
# @!attribute [rw] id
|
241
|
+
# @return [FixNum] the payment's ID
|
242
|
+
# @!attribute [rw] amount
|
243
|
+
# @return [Sreing] the amount of the payment
|
244
|
+
# @!attribute [rw] name
|
245
|
+
# @return [String] the name given to the payment
|
246
|
+
# @!attribute [rw] archived
|
247
|
+
# @return [Boolean] whether the payment has been archived
|
248
|
+
# @!attribute [rw] date
|
249
|
+
# @return [Date] the payment's due date
|
250
|
+
# @!attribute [rw] schedule
|
251
|
+
# @return [Osm::OnlnePayment::Schedule] the schedule the payment belongs to
|
252
|
+
|
253
|
+
attribute :id, type: Integer
|
254
|
+
attribute :amount, type: String
|
255
|
+
attribute :name, type: String
|
256
|
+
attribute :archived, type: Boolean
|
257
|
+
attribute :due_date, type: Object
|
258
|
+
attribute :schedule, type: Object
|
259
|
+
|
260
|
+
if ActiveModel::VERSION::MAJOR < 4
|
261
|
+
attr_accessible :id, :amount, :name, :archived, :due_date, :schedule
|
262
|
+
end
|
263
|
+
|
264
|
+
validates_numericality_of :id, only_integer: true, greater_than: 0
|
265
|
+
validates_presence_of :amount
|
266
|
+
validates_presence_of :name
|
267
|
+
validates_presence_of :due_date
|
268
|
+
validates_presence_of :schedule
|
269
|
+
validates_inclusion_of :archived, in: [true, false]
|
270
|
+
|
271
|
+
|
272
|
+
# @!method initialize
|
273
|
+
# Initialize a new Payment
|
274
|
+
# @param [Hash] attributes The hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
|
275
|
+
|
276
|
+
|
277
|
+
# Check if the payment is past due (or will be past due on the passed date)
|
278
|
+
# @param [Date] date The date to check for (defaults to today)
|
279
|
+
# @return [Boolean]
|
280
|
+
def past_due?(date=Date.today)
|
281
|
+
date > due_date
|
282
|
+
end
|
283
|
+
|
284
|
+
def inspect
|
285
|
+
Osm.inspect_instance(self, {:replace_with => {'schedule' => :to_s}})
|
286
|
+
end
|
287
|
+
|
288
|
+
end # Schedule::Payment class
|
289
|
+
|
290
|
+
|
291
|
+
class PaymentsForMember < Osm::Model
|
292
|
+
attribute :first_name, type: String
|
293
|
+
attribute :last_name, type: String
|
294
|
+
attribute :member_id, type: Integer
|
295
|
+
attribute :direct_debit, type: Object
|
296
|
+
attribute :start_date, type: Object
|
297
|
+
attribute :payments, type: Object, default: {} # payment_id -> Array of statuses
|
298
|
+
attribute :schedule, type: Object
|
299
|
+
|
300
|
+
if ActiveModel::VERSION::MAJOR < 4
|
301
|
+
attr_accessible :first_name, :last_name, :member_id, :direct_debit, :start_date, :payments, :schedule
|
302
|
+
end
|
303
|
+
|
304
|
+
validates_numericality_of :member_id, only_integer: true, greater_than: 0
|
305
|
+
validates_presence_of :first_name
|
306
|
+
validates_presence_of :last_name
|
307
|
+
validates_presence_of :schedule
|
308
|
+
validates_inclusion_of :direct_debit, in: [:active, :inactive, :cancelled]
|
309
|
+
validates :payments, hash: {key_type: Fixnum, value_type: Array}
|
310
|
+
|
311
|
+
|
312
|
+
# @!method initialize
|
313
|
+
# Initialize a new Schedule
|
314
|
+
# @param [Hash] attributes The hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
|
315
|
+
|
316
|
+
|
317
|
+
# Get the most recent status for a member's payment
|
318
|
+
# @param [Osm::OnlinePayment::Schedule::Payment, Fixnum, #to_i] payment The payment (or it's ID) to check
|
319
|
+
# @return [Boolean]
|
320
|
+
def latest_status_for(payment)
|
321
|
+
@latest_status ||= Hash[ payments.map{ |k,v| [k, v.sort[0]] } ]
|
322
|
+
@latest_status[payment.to_i]
|
323
|
+
end
|
324
|
+
|
325
|
+
# Check if the status of a member's payment is considered paid
|
326
|
+
# @param [Osm::OnlinePayment::Schedule::Payment, Fixnum, #to_i] payment The payment (or it's ID) to check
|
327
|
+
# @return [Boolean, nil]
|
328
|
+
def paid?(payment)
|
329
|
+
status = latest_status_for(payment.to_i)
|
330
|
+
return nil if status.nil?
|
331
|
+
[:paid, :paid_manually, :received, :initiated].include?(status.status)
|
332
|
+
end
|
333
|
+
|
334
|
+
# Check if the status of a member's payment is considered unpaid
|
335
|
+
# @param [Osm::OnlinePayment::Schedule::Payment, Fixnum, #to_i] payment The payment (or it's ID) to check
|
336
|
+
# @return [Boolean, nil]
|
337
|
+
def unpaid?(payment)
|
338
|
+
status = latest_status_for(payment.to_i)
|
339
|
+
return nil if status.nil?
|
340
|
+
[:required].include?(status.status)
|
341
|
+
end
|
342
|
+
|
343
|
+
# Check if a payment is over due (or will be over due on the passed date)
|
344
|
+
# @param [Osm::OnlinePayment::Schedule::Payment, Fixnum, #to_i] payment The payment (or it's ID) to check
|
345
|
+
# @param [Date] date The date to check for (defaults to today)
|
346
|
+
# @return [Boolean] whether the member's payment is unpaid and the payment's due date has passed
|
347
|
+
def over_due?(payment, date=nil)
|
348
|
+
unpaid?(payment) && payment.past_due?(date)
|
349
|
+
end
|
350
|
+
|
351
|
+
# Check if the member has an active direct debit for this schedule
|
352
|
+
# @return [Boolean]
|
353
|
+
def active_direct_debit?
|
354
|
+
direct_debit.eql?(:active)
|
355
|
+
end
|
356
|
+
|
357
|
+
# Update the status of a payment for the member in OSM
|
358
|
+
# @param [Osm::Api] api The api to use to make the request
|
359
|
+
# @param [Osm::OnlinePayment::Schedule::Payment, Fixnum, #to_i] payment The payment (or it's ID) to update
|
360
|
+
# @param [Symbol] status What to update the status to (:required, :not_required or :paid_manually)
|
361
|
+
# @param [Boolean] gift_aid Whether to update the gift aid record too (only relevant when setting to :paid_manually)
|
362
|
+
# @return [Boolean] whether the update was made in OSM
|
363
|
+
def update_payment_status(api, payment, status, gift_aid=false)
|
364
|
+
payment_id = payment.to_i
|
365
|
+
fail ArgumentError, "#{payment_id} is not a valid payment for the schedule." unless schedule.payments.map(&:id).include?(payment_id)
|
366
|
+
fail ArgumentError, "status must be either :required, :not_required or :paid_manually. You passed in #{status.inspect}" unless [:required, :not_required, :paid_manually].include?(status)
|
367
|
+
|
368
|
+
gift_aid = false unless payment.schedule.gift_aid?
|
369
|
+
api_status = {
|
370
|
+
required: 'Payment required',
|
371
|
+
not_required: 'Payment not required',
|
372
|
+
paid_manually: 'Paid manually',
|
373
|
+
}[status]
|
374
|
+
|
375
|
+
data = api.perform_query("ext/finances/onlinepayments/?action=updatePaymentStatus", {
|
376
|
+
'sectionid' => schedule.section_id,
|
377
|
+
'schemeid' => schedule.id,
|
378
|
+
'scoutid' => member_id,
|
379
|
+
'paymentid' => payment_id,
|
380
|
+
'giftaid' => gift_aid,
|
381
|
+
'value' => api_status,
|
382
|
+
})
|
383
|
+
|
384
|
+
data = data[payment_id.to_s]
|
385
|
+
return false if data.nil? # No data (at all) for this payment
|
386
|
+
data = PaymentStatus.build_from_json(data)
|
387
|
+
return false if data.nil? # No history for payment so it didn't get updated
|
388
|
+
data = data.sort[0]
|
389
|
+
return false if data.nil? # No history for payment so it didn't get updated
|
390
|
+
return false unless data.status.eql?(status) # Latest status is not what we set
|
391
|
+
return true
|
392
|
+
end
|
393
|
+
|
394
|
+
# Mark a payment as required by the member
|
395
|
+
# @param [Osm::Api] api The api to use to make the request
|
396
|
+
# @param [Osm::OnlinePayment::Schedule::Payment, Fixnum, #to_i] payment The payment (or it's ID) to update
|
397
|
+
# @return [Boolean] whether the update was made in OSM
|
398
|
+
def mark_payment_required(api, payment)
|
399
|
+
update_payment_status(api, payment, :required)
|
400
|
+
end
|
401
|
+
|
402
|
+
# Mark a payment as not required by the member
|
403
|
+
# @param [Osm::Api] api The api to use to make the request
|
404
|
+
# @param [Osm::OnlinePayment::Schedule::Payment, Fixnum, #to_i] payment The payment (or it's ID) to update
|
405
|
+
# @return [Boolean] whether the update was made in OSM
|
406
|
+
def mark_payment_not_required(api, payment)
|
407
|
+
update_payment_status(api, payment, :not_required)
|
408
|
+
end
|
409
|
+
|
410
|
+
# Mark a payment as paid by the member
|
411
|
+
# @param [Osm::Api] api The api to use to make the request
|
412
|
+
# @param [Osm::OnlinePayment::Schedule::Payment, Fixnum, #to_i] payment The payment (or it's ID) to update
|
413
|
+
# @param [Boolean] gift_aid Whether to update the gift aid record too
|
414
|
+
# @return [Boolean] whether the update was made in OSM
|
415
|
+
def mark_payment_paid_manually(api, payment, gift_aid=false)
|
416
|
+
update_payment_status(api, payment, :paid_manually, gift_aid)
|
417
|
+
end
|
418
|
+
|
419
|
+
end # Schedule::PaymentsForMember class
|
420
|
+
|
421
|
+
|
422
|
+
class PaymentStatus < Osm::Model
|
423
|
+
VALID_STATUSES = [:required, :not_required, :initiated, :paid, :received, :paid_manually]
|
424
|
+
|
425
|
+
attribute :id, type: Integer
|
426
|
+
attribute :payment, type: Object
|
427
|
+
attribute :timestamp, type: Object
|
428
|
+
attribute :status, type: Object
|
429
|
+
attribute :details, type: String
|
430
|
+
attribute :updated_by, type: String
|
431
|
+
attribute :updated_by_id, type: Integer
|
432
|
+
|
433
|
+
if ActiveModel::VERSION::MAJOR < 4
|
434
|
+
attr_accessible :id, :payment, :timestamp, :status, :details, :updated_by, :updated_by_id
|
435
|
+
end
|
436
|
+
|
437
|
+
validates_numericality_of :id, only_integer: true, greater_than: 0
|
438
|
+
validates_numericality_of :updated_by_id, only_integer: true, greater_than_or_equal_to: -2
|
439
|
+
validates_presence_of :payment
|
440
|
+
validates_presence_of :timestamp
|
441
|
+
validates_presence_of :updated_by
|
442
|
+
validates_inclusion_of :status, in: VALID_STATUSES
|
443
|
+
|
444
|
+
|
445
|
+
# @!method initialize
|
446
|
+
# Initialize a new PaymentStatus
|
447
|
+
# @param [Hash] attributes The hash of attributes (see attributes for descriptions, use Symbol of attribute name as the key)
|
448
|
+
|
449
|
+
|
450
|
+
# @!method required?
|
451
|
+
# Whether the status is :required
|
452
|
+
# @return (Boolean)
|
453
|
+
# @!method not_required?
|
454
|
+
# Whether the status is :not_required
|
455
|
+
# @return (Boolean)
|
456
|
+
# @!method initiated?
|
457
|
+
# Whether the status is :initiated
|
458
|
+
# @return (Boolean)
|
459
|
+
# @!method paid?
|
460
|
+
# Whether the status is :paid
|
461
|
+
# @return (Boolean)
|
462
|
+
# @!method received?
|
463
|
+
# Whether the status is :received
|
464
|
+
# @return (Boolean)
|
465
|
+
# @!method paid_manually?
|
466
|
+
# Whether the status is :paid_manually
|
467
|
+
# @return (Boolean)
|
468
|
+
VALID_STATUSES.each do |attribute|
|
469
|
+
define_method "#{attribute}?" do
|
470
|
+
status.eql?(attribute)
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
|
475
|
+
def <=>(another)
|
476
|
+
result = -(self.timestamp <=> another.try(:timestamp))
|
477
|
+
result = self.payment <=> another.try(:payment) if result.eql?(0)
|
478
|
+
result = self.id <=> another.try(:id) if result.eql?(0)
|
479
|
+
return result
|
480
|
+
end
|
481
|
+
|
482
|
+
def inspect
|
483
|
+
Osm.inspect_instance(self, {:replace_with => {'payment' => :id}})
|
484
|
+
end
|
485
|
+
|
486
|
+
protected
|
487
|
+
def self.build_from_json(json, payment=nil)
|
488
|
+
data = ActiveSupport::JSON.decode(json)
|
489
|
+
return [] unless data.is_a?(Hash)
|
490
|
+
data = data['status']
|
491
|
+
return [] unless data.is_a?(Array)
|
492
|
+
|
493
|
+
status_map = {
|
494
|
+
'Payment required' => :required,
|
495
|
+
'Payment not required' => :not_required,
|
496
|
+
'Initiated' => :initiated,
|
497
|
+
'Paid' => :paid,
|
498
|
+
'Received' => :received,
|
499
|
+
'Paid manually' => :paid_manually,
|
500
|
+
}
|
501
|
+
|
502
|
+
data.map! do |item|
|
503
|
+
new(
|
504
|
+
id: Osm::to_i_or_nil(item['statusid']),
|
505
|
+
payment: payment,
|
506
|
+
timestamp: Time.strptime(item['statustimestamp'], '%d/%m/%Y %H:%M'),
|
507
|
+
status: status_map[item['status']],
|
508
|
+
details: item['details'],
|
509
|
+
updated_by: item['firstname'],
|
510
|
+
updated_by_id: item['who'].to_i,
|
511
|
+
)
|
512
|
+
end
|
513
|
+
end
|
514
|
+
|
515
|
+
end # Schedule::PaymentStatus class
|
516
|
+
|
517
|
+
end # Schedule class
|
518
|
+
|
519
|
+
end
|
520
|
+
|
521
|
+
end
|
data/osm.gemspec
CHANGED
@@ -32,5 +32,6 @@ Gem::Specification.new do |s|
|
|
32
32
|
s.add_development_dependency 'rb-inotify', '~> 0.9'
|
33
33
|
s.add_development_dependency 'coveralls', '~> 0.7'
|
34
34
|
s.add_development_dependency 'simplecov', '~> 0.7'
|
35
|
+
s.add_development_dependency 'listen', '< 3.1' # Actually required by another dependency but >= 3.1 causing issues
|
35
36
|
|
36
37
|
end
|
data/spec/osm/event_spec.rb
CHANGED
@@ -16,6 +16,7 @@ describe "Event" do
|
|
16
16
|
:notes => 'None',
|
17
17
|
:archived => '0',
|
18
18
|
:badges => [],
|
19
|
+
:files => [],
|
19
20
|
:columns => [],
|
20
21
|
:notepad => 'notepad',
|
21
22
|
:public_notepad => 'public notepad',
|
@@ -39,6 +40,7 @@ describe "Event" do
|
|
39
40
|
event.notes.should == 'None'
|
40
41
|
event.archived.should == false
|
41
42
|
event.badges.should == []
|
43
|
+
event.files.should == []
|
42
44
|
event.columns.should == []
|
43
45
|
event.notepad.should == 'notepad'
|
44
46
|
event.public_notepad.should == 'public notepad'
|
@@ -208,6 +210,7 @@ describe "Event" do
|
|
208
210
|
|
209
211
|
FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/events.php?action=getEvents§ionid=1&showArchived=true", :body => @events_body.to_json, :content_type => 'application/json')
|
210
212
|
FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/events.php?action=getEvent§ionid=1&eventid=2", :body => @event_body.to_json, :content_type => 'application/json')
|
213
|
+
FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/ext/uploads/events/?action=listAttachments§ionid=1&eventid=2", :body => '{"files":["file1.txt", "file2.txt"]}', :content_type => 'application/json')
|
211
214
|
|
212
215
|
Osm::Model.stub(:get_user_permissions) { {:events => [:read, :write]} }
|
213
216
|
end
|
@@ -252,9 +255,16 @@ describe "Event" do
|
|
252
255
|
event.badges[1].badge_type.should == :staged
|
253
256
|
event.badges[1].requirement_id.should == 4
|
254
257
|
event.badges[1].data.should == '1'
|
258
|
+
event.files.should == ['file1.txt', 'file2.txt']
|
255
259
|
event.valid?.should == true
|
256
260
|
end
|
257
261
|
|
262
|
+
it "Handles no files being an empty array not a hash" do
|
263
|
+
FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/ext/uploads/events/?action=listAttachments§ionid=1&eventid=2", :body => '[]', :content_type => 'application/json')
|
264
|
+
expect{ @event = Osm::Event.get(@api, 1, 2) }.to_not raise_error
|
265
|
+
@event.files.should == []
|
266
|
+
end
|
267
|
+
|
258
268
|
it "Handles a blank config" do
|
259
269
|
@event_body['config'] = ''
|
260
270
|
FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/events.php?action=getEvent§ionid=1&eventid=2", :body => @event_body.to_json,:content_type => 'application/json')
|
@@ -313,6 +323,8 @@ describe "Event" do
|
|
313
323
|
FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/events.php?action=getEvents§ionid=1&showArchived=true", :body => body.to_json, :content_type => 'application/json')
|
314
324
|
FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/events.php?action=getEvent§ionid=1&eventid=1", :body => {'config' => '[]', 'archived' => '0', 'eventid' => '1'}.to_json, :content_type => 'application/json')
|
315
325
|
FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/events.php?action=getEvent§ionid=1&eventid=2", :body => {'config' => '[]', 'archived' => '1', 'eventid' => '2'}.to_json, :content_type => 'application/json')
|
326
|
+
FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/ext/uploads/events/?action=listAttachments§ionid=1&eventid=1", :body => '[]', :content_type => 'application/json')
|
327
|
+
FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/ext/uploads/events/?action=listAttachments§ionid=1&eventid=2", :body => '[]', :content_type => 'application/json')
|
316
328
|
|
317
329
|
events = Osm::Event.get_for_section(@api, 1)
|
318
330
|
OsmTest::Cache.clear
|
@@ -0,0 +1,490 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe "Online payments" do
|
5
|
+
|
6
|
+
describe "Schedule" do
|
7
|
+
|
8
|
+
it "Create" do
|
9
|
+
schedule = Osm::OnlinePayment::Schedule.new(
|
10
|
+
id: 1,
|
11
|
+
section_id: 2,
|
12
|
+
account_id: 3,
|
13
|
+
name: 'A payment schedule',
|
14
|
+
description: 'What this payment schedule is used for',
|
15
|
+
archived: true,
|
16
|
+
gift_aid: true,
|
17
|
+
require_all: true,
|
18
|
+
pay_now: 14,
|
19
|
+
annual_limit: '100',
|
20
|
+
payments: [],
|
21
|
+
)
|
22
|
+
schedule.id.should == 1
|
23
|
+
schedule.section_id.should == 2
|
24
|
+
schedule.account_id.should == 3
|
25
|
+
schedule.name.should == 'A payment schedule'
|
26
|
+
schedule.description.should == 'What this payment schedule is used for'
|
27
|
+
schedule.archived.should == true
|
28
|
+
schedule.gift_aid.should == true
|
29
|
+
schedule.require_all.should == true
|
30
|
+
schedule.pay_now.should == 14
|
31
|
+
schedule.annual_limit.should == '100'
|
32
|
+
schedule.payments.should == []
|
33
|
+
schedule.valid?.should == true
|
34
|
+
end
|
35
|
+
|
36
|
+
it "Provides current payments" do
|
37
|
+
payment1 = Osm::OnlinePayment::Schedule::Payment.new(id: 1, archived: false)
|
38
|
+
payment2 = Osm::OnlinePayment::Schedule::Payment.new(id: 2, archived: true)
|
39
|
+
schedule = Osm::OnlinePayment::Schedule.new(payments: [payment1, payment2])
|
40
|
+
schedule.current_payments.should == [payment1]
|
41
|
+
end
|
42
|
+
|
43
|
+
it "Checks for current payments" do
|
44
|
+
payment1 = Osm::OnlinePayment::Schedule::Payment.new(id: 1, archived: false)
|
45
|
+
payment2 = Osm::OnlinePayment::Schedule::Payment.new(id: 2, archived: true)
|
46
|
+
schedule = Osm::OnlinePayment::Schedule.new()
|
47
|
+
|
48
|
+
schedule.payments = [payment1]
|
49
|
+
schedule.current_payments?.should == true
|
50
|
+
|
51
|
+
schedule.payments = [payment2]
|
52
|
+
schedule.current_payments?.should == false
|
53
|
+
end
|
54
|
+
|
55
|
+
it "Provides archived payments" do
|
56
|
+
payment1 = Osm::OnlinePayment::Schedule::Payment.new(id: 1, archived: false)
|
57
|
+
payment2 = Osm::OnlinePayment::Schedule::Payment.new(id: 2, archived: true)
|
58
|
+
schedule = Osm::OnlinePayment::Schedule.new(payments: [payment1, payment2])
|
59
|
+
schedule.archived_payments.should == [payment2]
|
60
|
+
end
|
61
|
+
|
62
|
+
it "Checks for archived payments" do
|
63
|
+
payment1 = Osm::OnlinePayment::Schedule::Payment.new(id: 1, archived: false)
|
64
|
+
payment2 = Osm::OnlinePayment::Schedule::Payment.new(id: 2, archived: true)
|
65
|
+
schedule = Osm::OnlinePayment::Schedule.new()
|
66
|
+
|
67
|
+
schedule.payments = [payment2]
|
68
|
+
schedule.archived_payments?.should == true
|
69
|
+
|
70
|
+
schedule.payments = [payment1]
|
71
|
+
schedule.archived_payments?.should == false
|
72
|
+
end
|
73
|
+
|
74
|
+
it "Sorts by section_id, name then id" do
|
75
|
+
schedule1 = Osm::OnlinePayment::Schedule.new(section_id: 1, name: 'A', id: 1)
|
76
|
+
schedule2 = Osm::OnlinePayment::Schedule.new(section_id: 2, name: 'A', id: 1)
|
77
|
+
schedule3 = Osm::OnlinePayment::Schedule.new(section_id: 2, name: 'B', id: 1)
|
78
|
+
schedule4 = Osm::OnlinePayment::Schedule.new(section_id: 2, name: 'B', id: 2)
|
79
|
+
schedules = [schedule3, schedule2, schedule4, schedule1]
|
80
|
+
schedules.sort.should == [schedule1, schedule2, schedule3, schedule4]
|
81
|
+
end
|
82
|
+
|
83
|
+
it "Converts to a string" do
|
84
|
+
schedule = Osm::OnlinePayment::Schedule.new(id: 1, name: 'Name')
|
85
|
+
schedule.to_s.should == '1 -> Name'
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
describe "Uses OSM's API" do
|
90
|
+
|
91
|
+
it "Gets summary list" do
|
92
|
+
@api.should_receive(:perform_query).with('ext/finances/onlinepayments/?action=getSchemes§ionid=1'){ {'items'=>[{"schemeid"=>"539","name"=>"Events"}]} }
|
93
|
+
result = Osm::OnlinePayment::Schedule.get_list_for_section(@api, 1)
|
94
|
+
result.should == [{id: 539, name: 'Events'}]
|
95
|
+
end
|
96
|
+
|
97
|
+
it "Gets an individual schedule" do
|
98
|
+
data = {"schemeid"=>"2","sectionid"=>"1","accountid"=>"3","name"=>"Schedule name","preauth_amount"=>"12.34","description"=>"Schedule description","giftaid"=>"1","defaulton"=>"1","paynow"=>"-1","archived"=>"1","payments"=>[{"paymentid"=>"4","schemeid"=>"2","date"=>"2013-03-21","amount"=>"1.23","name"=>"Payment name","archived"=>"1"}]}
|
99
|
+
@api.should_receive(:perform_query).with('ext/finances/onlinepayments/?action=getPaymentSchedule§ionid=1&schemeid=2&allpayments=true'){ data }
|
100
|
+
schedule = Osm::OnlinePayment::Schedule.get(@api, 1, 2)
|
101
|
+
schedule.id.should == 2
|
102
|
+
schedule.section_id.should == 1
|
103
|
+
schedule.account_id.should == 3
|
104
|
+
schedule.name.should == 'Schedule name'
|
105
|
+
schedule.description.should == 'Schedule description'
|
106
|
+
schedule.archived.should == true
|
107
|
+
schedule.gift_aid.should == true
|
108
|
+
schedule.require_all.should == true
|
109
|
+
schedule.pay_now.should == -1
|
110
|
+
schedule.annual_limit.should == '12.34'
|
111
|
+
schedule.payments.count.should == 1
|
112
|
+
schedule.valid?.should == true
|
113
|
+
payment = schedule.payments[0]
|
114
|
+
payment.id.should == 4
|
115
|
+
payment.amount.should == '1.23'
|
116
|
+
payment.name.should == 'Payment name'
|
117
|
+
payment.archived.should == true
|
118
|
+
payment.due_date.should == Date.new(2013, 3, 21)
|
119
|
+
payment.schedule.should == schedule
|
120
|
+
payment.valid?.should == true
|
121
|
+
end
|
122
|
+
|
123
|
+
it "Gets all schedules for a section" do
|
124
|
+
Osm::OnlinePayment::Schedule.should_receive(:get_list_for_section).with(@api, 5, {}){ [{id: 6, name: 'A'}, {id: 7, name: 'B'}] }
|
125
|
+
Osm::OnlinePayment::Schedule.should_receive(:get).with(@api, 5, 6, {}){ 'A' }
|
126
|
+
Osm::OnlinePayment::Schedule.should_receive(:get).with(@api, 5, 7, {}){ 'B' }
|
127
|
+
Osm::OnlinePayment::Schedule.get_for_section(@api, 5).should == ['A', 'B']
|
128
|
+
end
|
129
|
+
|
130
|
+
describe "Gets member's payments" do
|
131
|
+
|
132
|
+
before :each do
|
133
|
+
@payment = Osm::OnlinePayment::Schedule::Payment.new(id: 4)
|
134
|
+
@schedule = Osm::OnlinePayment::Schedule.new(
|
135
|
+
id: 1,
|
136
|
+
section_id: 2,
|
137
|
+
payments: [@payment]
|
138
|
+
)
|
139
|
+
body = {'items'=>[ {
|
140
|
+
'directdebit'=>'Active', 'firstname'=>'John', 'lastname'=>'Snow', 'patrolid'=>'5', 'scoutid'=>'6',
|
141
|
+
'startdate'=>'2015-02-03',
|
142
|
+
'4'=>'{"status":[{"statusid":"7","scoutid":"6","schemeid":"1","paymentid":"8","statustimestamp":"03/02/2016 20:51","status":"Paid manually","details":"","editable":"1","latest":"1","who":"0","firstname":"System"}]}',
|
143
|
+
} ]}
|
144
|
+
@api.should_receive(:perform_query).with('ext/finances/onlinepayments/?action=getPaymentStatus§ionid=2&schemeid=1&termid=3').once{ body }
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'For a "collect all" schedule' do
|
148
|
+
@schedule.require_all = true
|
149
|
+
p4m = @schedule.get_payments_for_members(@api, 3)
|
150
|
+
p4m.is_a?(Array).should == true
|
151
|
+
p4m.size.should == 1
|
152
|
+
p4m = p4m[0]
|
153
|
+
p4m.member_id.should == 6
|
154
|
+
p4m.first_name.should == 'John'
|
155
|
+
p4m.last_name.should == 'Snow'
|
156
|
+
p4m.start_date.should == Date.new(2015, 2, 3)
|
157
|
+
p4m.direct_debit.should == :active
|
158
|
+
p4m.payments.size.should == 1
|
159
|
+
payment = p4m.payments[4][0]
|
160
|
+
payment.id.should == 7
|
161
|
+
payment.payment.should == @payment
|
162
|
+
payment.timestamp.should == Time.new(2016, 2, 3, 20, 51)
|
163
|
+
payment.status.should == :paid_manually
|
164
|
+
payment.details.should == ''
|
165
|
+
payment.updated_by.should == 'System'
|
166
|
+
payment.updated_by_id.should == 0
|
167
|
+
payment.valid?.should == true
|
168
|
+
p4m.valid?.should == true
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'For a "not collect all" schedule' do
|
172
|
+
@schedule.require_all = false
|
173
|
+
p4m = @schedule.get_payments_for_members(@api, 3)[0]
|
174
|
+
p4m.start_date.should == nil # Only difference to a "collect all" type
|
175
|
+
p4m.valid?.should == true
|
176
|
+
end
|
177
|
+
|
178
|
+
it "When it needs to fetch a term" do
|
179
|
+
section = Osm::Section.new(id: 2)
|
180
|
+
Osm::Term.stub(:get_current_term_for_section).and_return(Osm::Term.new(id: 3))
|
181
|
+
Osm::Section.stub(:get).and_return(section)
|
182
|
+
p4m = @schedule.get_payments_for_members(@api)[0]
|
183
|
+
p4m.member_id.should == 6
|
184
|
+
p4m.valid?.should == true
|
185
|
+
end
|
186
|
+
|
187
|
+
end # describe Schedule : Uses OSM's API : Get member's payments
|
188
|
+
|
189
|
+
end # describe Schedule : Uses OSM's API
|
190
|
+
|
191
|
+
|
192
|
+
describe "Payment" do
|
193
|
+
|
194
|
+
it "Create" do
|
195
|
+
schedule = Osm::OnlinePayment::Schedule.new()
|
196
|
+
schedule.stub('valid?'){ true }
|
197
|
+
payment = Osm::OnlinePayment::Schedule::Payment.new(
|
198
|
+
id: 1,
|
199
|
+
amount: '12.34',
|
200
|
+
name: 'A payment',
|
201
|
+
archived: true,
|
202
|
+
due_date: Date.new(2016, 5, 1),
|
203
|
+
schedule: schedule,
|
204
|
+
)
|
205
|
+
payment.id.should == 1
|
206
|
+
payment.amount.should == '12.34'
|
207
|
+
payment.name.should == 'A payment'
|
208
|
+
payment.archived.should == true
|
209
|
+
payment.due_date.should == Date.new(2016, 5, 1)
|
210
|
+
payment.schedule.should == schedule
|
211
|
+
payment.valid?.should == true
|
212
|
+
end
|
213
|
+
|
214
|
+
it "Checks if a payment is past due" do
|
215
|
+
payment = Osm::OnlinePayment::Schedule::Payment.new(due_date: Date.new(2016, 5, 2))
|
216
|
+
payment.past_due?(Date.new(2016, 5, 1)).should == false
|
217
|
+
payment.past_due?(Date.new(2016, 5, 2)).should == false
|
218
|
+
payment.past_due?(Date.new(2016, 5, 3)).should == true
|
219
|
+
end
|
220
|
+
|
221
|
+
end # describe Schedule -> Payment
|
222
|
+
|
223
|
+
|
224
|
+
describe "PaymentsForMember" do
|
225
|
+
|
226
|
+
it "Create" do
|
227
|
+
schedule = Osm::OnlinePayment::Schedule.new
|
228
|
+
p4m = Osm::OnlinePayment::Schedule::PaymentsForMember.new(
|
229
|
+
first_name: 'John',
|
230
|
+
last_name: 'Smith',
|
231
|
+
member_id: 1,
|
232
|
+
direct_debit: :active,
|
233
|
+
start_date: Date.new(2016, 6, 7),
|
234
|
+
payments: {},
|
235
|
+
schedule: schedule,
|
236
|
+
)
|
237
|
+
p4m.first_name.should == 'John'
|
238
|
+
p4m.last_name.should == 'Smith'
|
239
|
+
p4m.member_id.should == 1
|
240
|
+
p4m.direct_debit.should == :active
|
241
|
+
p4m.start_date.should == Date.new(2016, 6, 7)
|
242
|
+
p4m.payments.should == {}
|
243
|
+
p4m.schedule.should == schedule
|
244
|
+
p4m.valid?.should == true
|
245
|
+
end
|
246
|
+
|
247
|
+
it "Gets most recent status for a payment" do
|
248
|
+
payments = {
|
249
|
+
1 => [Osm::OnlinePayment::Schedule::PaymentStatus.new(id: 1, timestamp: Time.new(2016, 1, 2, 3, 4))],
|
250
|
+
2 => [Osm::OnlinePayment::Schedule::PaymentStatus.new(id: 2, timestamp: Time.new(2016, 1, 2, 3, 4))],
|
251
|
+
3 => [Osm::OnlinePayment::Schedule::PaymentStatus.new(id: 3, timestamp: Time.new(2016, 1, 2, 3, 4)), Osm::OnlinePayment::Schedule::PaymentStatus.new(id: 4, timestamp: Time.new(2016, 1, 2, 3, 5))],
|
252
|
+
}
|
253
|
+
p4m = Osm::OnlinePayment::Schedule::PaymentsForMember.new(payments: payments)
|
254
|
+
|
255
|
+
p4m.latest_status_for(1).id.should == 1
|
256
|
+
p4m.latest_status_for(Osm::OnlinePayment::Schedule::Payment.new(id: 2)).id.should == 2
|
257
|
+
p4m.latest_status_for(3).id.should == 4
|
258
|
+
end
|
259
|
+
|
260
|
+
it "Works out if a payment is paid" do
|
261
|
+
payments = {
|
262
|
+
1 => [Osm::OnlinePayment::Schedule::PaymentStatus.new(status: :required)],
|
263
|
+
2 => [Osm::OnlinePayment::Schedule::PaymentStatus.new(status: :not_required)],
|
264
|
+
3 => [Osm::OnlinePayment::Schedule::PaymentStatus.new(status: :initiated)],
|
265
|
+
4 => [Osm::OnlinePayment::Schedule::PaymentStatus.new(status: :paid)],
|
266
|
+
5 => [Osm::OnlinePayment::Schedule::PaymentStatus.new(status: :received)],
|
267
|
+
6 => [Osm::OnlinePayment::Schedule::PaymentStatus.new(status: :paid_manually)],
|
268
|
+
}
|
269
|
+
p4m = Osm::OnlinePayment::Schedule::PaymentsForMember.new(payments: payments)
|
270
|
+
|
271
|
+
p4m.paid?(1).should == false
|
272
|
+
p4m.paid?(2).should == false
|
273
|
+
p4m.paid?(3).should == true
|
274
|
+
p4m.paid?(4).should == true
|
275
|
+
p4m.paid?(5).should == true
|
276
|
+
p4m.paid?(6).should == true
|
277
|
+
p4m.paid?(7).should == nil
|
278
|
+
end
|
279
|
+
|
280
|
+
it "Works out if a payment is unpaid" do
|
281
|
+
payments = {
|
282
|
+
1 => [Osm::OnlinePayment::Schedule::PaymentStatus.new(status: :required)],
|
283
|
+
2 => [Osm::OnlinePayment::Schedule::PaymentStatus.new(status: :not_required)],
|
284
|
+
3 => [Osm::OnlinePayment::Schedule::PaymentStatus.new(status: :initiated)],
|
285
|
+
4 => [Osm::OnlinePayment::Schedule::PaymentStatus.new(status: :paid)],
|
286
|
+
5 => [Osm::OnlinePayment::Schedule::PaymentStatus.new(status: :received)],
|
287
|
+
6 => [Osm::OnlinePayment::Schedule::PaymentStatus.new(status: :paid_manually)],
|
288
|
+
}
|
289
|
+
p4m = Osm::OnlinePayment::Schedule::PaymentsForMember.new(payments: payments)
|
290
|
+
|
291
|
+
p4m.unpaid?(1).should == true
|
292
|
+
p4m.unpaid?(2).should == false
|
293
|
+
p4m.unpaid?(3).should == false
|
294
|
+
p4m.unpaid?(4).should == false
|
295
|
+
p4m.unpaid?(5).should == false
|
296
|
+
p4m.unpaid?(6).should == false
|
297
|
+
p4m.unpaid?(7).should == nil
|
298
|
+
end
|
299
|
+
|
300
|
+
it "Tells if the user has an active direct debit" do
|
301
|
+
p4m = Osm::OnlinePayment::Schedule::PaymentsForMember.new(direct_debit: :active)
|
302
|
+
p4m.active_direct_debit?.should == true
|
303
|
+
|
304
|
+
p4m = Osm::OnlinePayment::Schedule::PaymentsForMember.new(direct_debit: :inactive)
|
305
|
+
p4m.active_direct_debit?.should == false
|
306
|
+
end
|
307
|
+
|
308
|
+
describe "Works out if a payment is over due" do
|
309
|
+
|
310
|
+
before :each do
|
311
|
+
@payment = Osm::OnlinePayment::Schedule::Payment.new(id: 1, due_date: Date.new(2016, 1, 2))
|
312
|
+
paid_payments = { 1 => [Osm::OnlinePayment::Schedule::PaymentStatus.new(status: :paid, payment: @payment)] }
|
313
|
+
@paid = Osm::OnlinePayment::Schedule::PaymentsForMember.new(payments: paid_payments)
|
314
|
+
unpaid_payments = { 1 => [Osm::OnlinePayment::Schedule::PaymentStatus.new(status: :required, payment: @payment)] }
|
315
|
+
@unpaid = Osm::OnlinePayment::Schedule::PaymentsForMember.new(payments: unpaid_payments)
|
316
|
+
end
|
317
|
+
|
318
|
+
it "Due date in over" do
|
319
|
+
date = Date.new(2016, 1, 3)
|
320
|
+
@paid.over_due?(@payment, date).should == false
|
321
|
+
@unpaid.over_due?(@payment, date).should == true
|
322
|
+
end
|
323
|
+
|
324
|
+
it "Due date in present" do
|
325
|
+
# Due today means that it is not over being due
|
326
|
+
date = Date.new(2016, 1, 2)
|
327
|
+
@paid.over_due?(@payment, date).should == false
|
328
|
+
@unpaid.over_due?(@payment, date).should == false
|
329
|
+
end
|
330
|
+
|
331
|
+
it "Due date in future" do
|
332
|
+
date = Date.new(2016, 1, 1)
|
333
|
+
@paid.over_due?(@payment, date).should == false
|
334
|
+
@unpaid.over_due?(@payment, date).should == false
|
335
|
+
end
|
336
|
+
|
337
|
+
end # describe Schedule -> PaymentsForMember : is payment past due?
|
338
|
+
|
339
|
+
describe "Update a payment in OSM" do
|
340
|
+
|
341
|
+
before :each do
|
342
|
+
@schedule = Osm::OnlinePayment::Schedule.new(id: 10, section_id: 4, gift_aid: true)
|
343
|
+
@payment = Osm::OnlinePayment::Schedule::Payment.new(id: 1, schedule: @schedule)
|
344
|
+
@schedule.payments = [@payment]
|
345
|
+
@status = Osm::OnlinePayment::Schedule::PaymentStatus.new(id: 2, payment: @payment)
|
346
|
+
@p4m = Osm::OnlinePayment::Schedule::PaymentsForMember.new(member_id: 3, payments: {1=>[@status]}, schedule: @schedule)
|
347
|
+
end
|
348
|
+
|
349
|
+
describe "Using update_payment_status method" do
|
350
|
+
it "Success" do
|
351
|
+
@api.should_receive(:perform_query).with('ext/finances/onlinepayments/?action=updatePaymentStatus', {'sectionid'=>4,'schemeid'=>10,'scoutid'=>3,'paymentid'=>1,'giftaid'=>false,'value'=>'Payment not required'})
|
352
|
+
.once{ {'scoutid'=>'3', 'firstname'=>'John', 'lastname'=>'Smith', 'patrolid'=>'5', 'startdate'=>'1970-01-01', 'directdebit'=>'cancelled', '1'=>'{"status":[{"statusid":"6","scoutid":"3","schemeid":"4","paymentid":"1","statustimestamp":"01/02/2003 04:05","status":"Payment not required","details":"","editable":"0","latest":"1","who":"0","firstname":"System generated"}]}'} }
|
353
|
+
@p4m.update_payment_status(@api, @payment, :not_required).should == true
|
354
|
+
end
|
355
|
+
|
356
|
+
describe "Failure" do
|
357
|
+
it "No history for payment" do
|
358
|
+
@api.should_receive(:perform_query).with('ext/finances/onlinepayments/?action=updatePaymentStatus', {'sectionid'=>4,'schemeid'=>10,'scoutid'=>3,'paymentid'=>1,'giftaid'=>true,'value'=>'Paid manually'})
|
359
|
+
.once{ {'scoutid'=>'3', 'firstname'=>'John', 'lastname'=>'Smith', 'patrolid'=>'5', 'startdate'=>'1970-01-01', 'directdebit'=>'cancelled', '1'=>'{"status":[]}'} }
|
360
|
+
@p4m.update_payment_status(@api, @payment, :paid_manually, true).should == false
|
361
|
+
end
|
362
|
+
|
363
|
+
it "No payment data" do
|
364
|
+
@api.should_receive(:perform_query).with('ext/finances/onlinepayments/?action=updatePaymentStatus', {'sectionid'=>4,'schemeid'=>10,'scoutid'=>3,'paymentid'=>1,'giftaid'=>true,'value'=>'Paid manually'})
|
365
|
+
.once{ {'scoutid'=>'3', 'firstname'=>'John', 'lastname'=>'Smith', 'patrolid'=>'5', 'startdate'=>'1970-01-01', 'directdebit'=>'cancelled'} }
|
366
|
+
@p4m.update_payment_status(@api, @payment, :paid_manually, true).should == false
|
367
|
+
end
|
368
|
+
|
369
|
+
it "Latest status is not what we set" do
|
370
|
+
@api.should_receive(:perform_query).with('ext/finances/onlinepayments/?action=updatePaymentStatus', {'sectionid'=>4,'schemeid'=>10,'scoutid'=>3,'paymentid'=>1,'giftaid'=>true,'value'=>'Paid manually'})
|
371
|
+
.once{ {'scoutid'=>'3', 'firstname'=>'John', 'lastname'=>'Smith', 'patrolid'=>'5', 'startdate'=>'1970-01-01', 'directdebit'=>'cancelled', '1'=>'{"status":[{"statusid":"6","scoutid":"3","schemeid":"4","paymentid":"1","statustimestamp":"01/02/2003 04:05","status":"Payment not required","details":"","editable":"0","latest":"1","who":"0","firstname":"System generated"}]}'} }
|
372
|
+
@p4m.update_payment_status(@api, @payment, :paid_manually, true).should == false
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
it "Fails if payment is not in the schedule" do
|
377
|
+
expect{ @p4m.update_payment_status(@api, 2, :paid_manually) }.to raise_error ArgumentError, '2 is not a valid payment for the schedule.'
|
378
|
+
end
|
379
|
+
|
380
|
+
it "Fails if given a bad status" do
|
381
|
+
expect{ @p4m.update_payment_status(@api, 1, :invalid) }.to raise_error ArgumentError, 'status must be either :required, :not_required or :paid_manually. You passed in :invalid'
|
382
|
+
end
|
383
|
+
|
384
|
+
describe "Ignores gift aid parameter if appropriate" do # pass in true and check if calls out with false
|
385
|
+
it "Schedule is a gift aid one" do
|
386
|
+
@api.should_receive(:perform_query).with('ext/finances/onlinepayments/?action=updatePaymentStatus', {'sectionid'=>4,'schemeid'=>10,'scoutid'=>3,'paymentid'=>1,'giftaid'=>true,'value'=>'Paid manually'})
|
387
|
+
.once{ {'scoutid'=>'3', 'firstname'=>'John', 'lastname'=>'Smith', 'patrolid'=>'5', 'startdate'=>'1970-01-01', 'directdebit'=>'cancelled', '1'=>'{"status":[{"statusid":"6","scoutid":"3","schemeid":"4","paymentid":"1","statustimestamp":"01/02/2003 04:05","status":"Paid manually","details":"","editable":"0","latest":"1","who":"0","firstname":"System generated"}]}'} }
|
388
|
+
@p4m.update_payment_status(@api, @payment, :paid_manually, true).should == true
|
389
|
+
end
|
390
|
+
|
391
|
+
it "Schedule is NOT a gift aid one" do
|
392
|
+
@schedule.gift_aid = false
|
393
|
+
@api.should_receive(:perform_query).with('ext/finances/onlinepayments/?action=updatePaymentStatus', {'sectionid'=>4,'schemeid'=>10,'scoutid'=>3,'paymentid'=>1,'giftaid'=>false,'value'=>'Paid manually'})
|
394
|
+
.once{ {'scoutid'=>'3', 'firstname'=>'John', 'lastname'=>'Smith', 'patrolid'=>'5', 'startdate'=>'1970-01-01', 'directdebit'=>'cancelled', '1'=>'{"status":[{"statusid":"6","scoutid":"3","schemeid":"4","paymentid":"1","statustimestamp":"01/02/2003 04:05","status":"Paid manually","details":"","editable":"0","latest":"1","who":"0","firstname":"System generated"}]}'} }
|
395
|
+
@p4m.update_payment_status(@api, @payment, :paid_manually, true).should == true
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
end # Using update_payment_status method
|
400
|
+
|
401
|
+
describe "Using" do
|
402
|
+
it "mark_payment_required" do
|
403
|
+
@p4m.should_receive(:update_payment_status).with(@api, @payment, :required).once{ true }
|
404
|
+
@p4m.mark_payment_required(@api, @payment).should == true
|
405
|
+
end
|
406
|
+
|
407
|
+
it "mark_payment_not_required" do
|
408
|
+
@p4m.should_receive(:update_payment_status).with(@api, @payment, :not_required).once{ true }
|
409
|
+
@p4m.mark_payment_not_required(@api, @payment).should == true
|
410
|
+
end
|
411
|
+
|
412
|
+
describe "mark_payment_paid_manually" do
|
413
|
+
it "Updating gift aid" do
|
414
|
+
@p4m.should_receive(:update_payment_status).with(@api, @payment, :paid_manually, true).once{ true }
|
415
|
+
@p4m.mark_payment_paid_manually(@api, @payment, true).should == true
|
416
|
+
end
|
417
|
+
|
418
|
+
it "Not updating gift aid" do
|
419
|
+
@p4m.should_receive(:update_payment_status).with(@api, @payment, :paid_manually, false).once{ true }
|
420
|
+
@p4m.mark_payment_paid_manually(@api, @payment, false).should == true
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
end
|
425
|
+
|
426
|
+
end # describe Schedule -> PaymentsForMember : Update a payment in OSM
|
427
|
+
|
428
|
+
end # describe Schedule -> PaymentsForMember
|
429
|
+
|
430
|
+
|
431
|
+
describe "Payment status" do
|
432
|
+
|
433
|
+
it "Create" do
|
434
|
+
payment = Osm::OnlinePayment::Schedule::Payment.new
|
435
|
+
payment.stub('valid?'){ true }
|
436
|
+
status = Osm::OnlinePayment::Schedule::PaymentStatus.new(
|
437
|
+
id: 1,
|
438
|
+
payment: payment,
|
439
|
+
details: 'Details',
|
440
|
+
timestamp: Time.new(2016, 4, 5, 6, 7),
|
441
|
+
status: :paid,
|
442
|
+
updated_by: 'My.SCOUT',
|
443
|
+
updated_by_id: -2,
|
444
|
+
)
|
445
|
+
status.id.should == 1
|
446
|
+
status.payment.should == payment
|
447
|
+
status.details.should == 'Details'
|
448
|
+
status.timestamp.should == Time.new(2016, 4, 5, 6, 7)
|
449
|
+
status.status.should == :paid
|
450
|
+
status.updated_by.should == 'My.SCOUT'
|
451
|
+
status.updated_by_id.should == -2
|
452
|
+
status.valid?.should == true
|
453
|
+
end
|
454
|
+
|
455
|
+
it "Sorts by timestamp (desc), payment then id" do
|
456
|
+
status1 = Osm::OnlinePayment::Schedule::PaymentStatus.new(timestamp: Time.new(2016, 1, 2, 3, 6), payment: 1, id: 1)
|
457
|
+
status2 = Osm::OnlinePayment::Schedule::PaymentStatus.new(timestamp: Time.new(2016, 1, 2, 3, 5), payment: 1, id: 1)
|
458
|
+
status3 = Osm::OnlinePayment::Schedule::PaymentStatus.new(timestamp: Time.new(2016, 1, 2, 3, 5), payment: 2, id: 1)
|
459
|
+
status4 = Osm::OnlinePayment::Schedule::PaymentStatus.new(timestamp: Time.new(2016, 1, 2, 3, 5), payment: 2, id: 2)
|
460
|
+
statuses = [status3, status1, status4, status2]
|
461
|
+
statuses.sort.should == [status1, status2, status3, status4]
|
462
|
+
end
|
463
|
+
|
464
|
+
describe "Has status checking method for" do
|
465
|
+
before :each do
|
466
|
+
@payments = []
|
467
|
+
Osm::OnlinePayment::Schedule::PaymentStatus::VALID_STATUSES.each do |status|
|
468
|
+
payment = Osm::OnlinePayment::Schedule::PaymentStatus.new(status: status)
|
469
|
+
@payments.push payment
|
470
|
+
instance_variable_set("@#{status}_payment", payment)
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
Osm::OnlinePayment::Schedule::PaymentStatus::VALID_STATUSES.each do |status|
|
475
|
+
it status.to_s do
|
476
|
+
payment = instance_variable_get("@#{status}_payment")
|
477
|
+
payment.send("#{status}?").should == true
|
478
|
+
(Osm::OnlinePayment::Schedule::PaymentStatus::VALID_STATUSES - [status]).each do |i|
|
479
|
+
payment.send("#{i}?").should == false
|
480
|
+
end
|
481
|
+
end
|
482
|
+
end
|
483
|
+
end
|
484
|
+
|
485
|
+
end # describe Schedule -> PaymentStatus
|
486
|
+
|
487
|
+
|
488
|
+
end # describe Schedule
|
489
|
+
|
490
|
+
end
|
data/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: osm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Gauld
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-05-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -202,6 +202,20 @@ dependencies:
|
|
202
202
|
- - "~>"
|
203
203
|
- !ruby/object:Gem::Version
|
204
204
|
version: '0.7'
|
205
|
+
- !ruby/object:Gem::Dependency
|
206
|
+
name: listen
|
207
|
+
requirement: !ruby/object:Gem::Requirement
|
208
|
+
requirements:
|
209
|
+
- - "<"
|
210
|
+
- !ruby/object:Gem::Version
|
211
|
+
version: '3.1'
|
212
|
+
type: :development
|
213
|
+
prerelease: false
|
214
|
+
version_requirements: !ruby/object:Gem::Requirement
|
215
|
+
requirements:
|
216
|
+
- - "<"
|
217
|
+
- !ruby/object:Gem::Version
|
218
|
+
version: '3.1'
|
205
219
|
description: Use the Online Scout Manager API (https://www.onlinescoutmanager.co.uk)
|
206
220
|
to retrieve and save data.
|
207
221
|
email:
|
@@ -239,6 +253,7 @@ files:
|
|
239
253
|
- lib/osm/member.rb
|
240
254
|
- lib/osm/model.rb
|
241
255
|
- lib/osm/myscout.rb
|
256
|
+
- lib/osm/online_payment.rb
|
242
257
|
- lib/osm/register.rb
|
243
258
|
- lib/osm/section.rb
|
244
259
|
- lib/osm/sms.rb
|
@@ -263,6 +278,7 @@ files:
|
|
263
278
|
- spec/osm/member_spec.rb
|
264
279
|
- spec/osm/model_spec.rb
|
265
280
|
- spec/osm/myscout_spec.rb
|
281
|
+
- spec/osm/online_payment_spec.rb
|
266
282
|
- spec/osm/osm_spec.rb
|
267
283
|
- spec/osm/register_spec.rb
|
268
284
|
- spec/osm/section_spec.rb
|