dcas-ruby 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/API.rdoc +8 -1
- data/VERSION +1 -1
- data/dcas-ruby.gemspec +1 -1
- data/lib/dcas/payment.rb +4 -0
- data/lib/dcas.rb +66 -29
- data/spec/dcas_spec.rb +4 -4
- data/spec/fixtures/ach_payments.yml +10 -10
- data/spec/fixtures/credit_card_payments.yml +10 -10
- metadata +1 -1
data/API.rdoc
CHANGED
@@ -7,7 +7,14 @@
|
|
7
7
|
* Parse response files
|
8
8
|
|
9
9
|
=== First you must set up the login info and a cache location
|
10
|
-
angola =
|
10
|
+
angola = DCAS::Client.new(
|
11
|
+
:username => 'angola',
|
12
|
+
:password => '4ng014',
|
13
|
+
:company_alias => 'angolaHQ',
|
14
|
+
:company_username => 'angolatw',
|
15
|
+
:company_password => 'secret',
|
16
|
+
:cache_location => './PaymentFileStore'
|
17
|
+
)
|
11
18
|
|
12
19
|
=== Create a Payment Batch
|
13
20
|
ach_payments = angola.new_batch(batch_id)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/dcas-ruby.gemspec
CHANGED
data/lib/dcas/payment.rb
CHANGED
data/lib/dcas.rb
CHANGED
@@ -6,6 +6,7 @@ module DCAS
|
|
6
6
|
OUTGOING_BUCKET = 'outgoing'
|
7
7
|
INCOMING_BUCKET = 'incoming'
|
8
8
|
STAGING_BUCKET = 'staging'
|
9
|
+
DEFAULT_CACHE_LOCATION = 'EFT'
|
9
10
|
|
10
11
|
class << self
|
11
12
|
# Parses the responses from a response file and returns an array of DCAS::Response objects.
|
@@ -16,16 +17,17 @@ module DCAS
|
|
16
17
|
class Client
|
17
18
|
# Instantiate a new Client object which can do authenticated actions in a DCAS FTPS bucket.
|
18
19
|
def initialize(options={})
|
19
|
-
raise ArgumentError, "must include :username, :password, :company_alias, :company_username,
|
20
|
-
@username = options[:username]
|
21
|
-
@password = options[:password]
|
22
|
-
@company_alias = options[:company_alias]
|
23
|
-
@company_username = options[:company_username]
|
24
|
-
@company_password = options[:company_password]
|
25
|
-
@cache_location = options[:cache_location]
|
20
|
+
raise ArgumentError, "must include :username, :password, :company_alias, :company_username, and :company_password" if [:username, :password, :company_alias, :company_username, :company_password].any? {|k| options[k].to_s.length == 0}
|
21
|
+
@username = options[:username].to_s
|
22
|
+
@password = options[:password].to_s
|
23
|
+
@company_alias = options[:company_alias].to_s
|
24
|
+
@company_username = options[:company_username].to_s
|
25
|
+
@company_password = options[:company_password].to_s
|
26
|
+
@cache_location = options[:cache_location].to_s || DEFAULT_CACHE_LOCATION
|
26
27
|
end
|
27
28
|
|
28
|
-
attr_reader :username, :password, :company_alias, :company_username, :company_password
|
29
|
+
attr_reader :username, :password, :company_alias, :company_username, :company_password
|
30
|
+
attr_accessor :cache_location
|
29
31
|
|
30
32
|
# :nodoc:
|
31
33
|
def batches
|
@@ -39,40 +41,75 @@ module DCAS
|
|
39
41
|
end
|
40
42
|
|
41
43
|
# Uploads a single payments file to the DCAS outgoing payments bucket.
|
42
|
-
|
44
|
+
# You can optionally supply a 'lock' object, which must respond to:
|
45
|
+
# #submit_locked?(filename)
|
46
|
+
# #submit_lock!(filename)
|
47
|
+
# #submit_finished!(filename)
|
48
|
+
# #submit_failed!(filename)
|
49
|
+
# If a lock_object is supplied, the method will mark it as failed and return false instead of raising an error, in case of failure.
|
50
|
+
def submit_payments_file!(filename, lock_object=nil)
|
43
51
|
shortname = filename.gsub(/.*[\\\/][^\\\/]+$/,'')
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
52
|
+
if lock_object && lock_object.submit_locked?(shortname)
|
53
|
+
raise RuntimeError, "Submit for #{shortname} is locked!"
|
54
|
+
else
|
55
|
+
lock_object.submit_lock!(shortname) if lock_object
|
56
|
+
with_ftp do |ftp|
|
57
|
+
# 1) Create the STAGING folder if it's not already there.
|
58
|
+
ftp.mkdir(DCAS::STAGING_BUCKET) unless ftp.nlst.include?(DCAS::STAGING_BUCKET)
|
59
|
+
ftp.chdir(DCAS::STAGING_BUCKET)
|
60
|
+
# 2) Delete the same filename from the STAGING folder if one exists.
|
61
|
+
ftp.delete(shortname) if ftp.nlst.include?(shortname)
|
62
|
+
# 3) Upload the file into the STAGING folder.
|
63
|
+
ftp.put(filename, shortname)
|
64
|
+
# 4) If we're still connected, check the file size of the file, then move it out of STAGING and mark file as completed.
|
65
|
+
if ftp.nlst.include?(shortname) && ftp.size(shortname) == File.size(filename)
|
66
|
+
ftp.rename(shortname, "../#{DCAS::OUTGOING_BUCKET}/#{shortname}") unless DCAS::TESTING
|
67
|
+
lock_object.submit_finished!(shortname) if lock_object
|
68
|
+
else
|
69
|
+
if lock_object
|
70
|
+
lock_object.submit_failed!(shortname)
|
71
|
+
return false
|
72
|
+
else
|
73
|
+
raise RuntimeError, "FAILED uploading `#{filename}' - incomplete or unsuccessful upload. Please try again."
|
74
|
+
end
|
75
|
+
end
|
57
76
|
end
|
58
77
|
end
|
59
78
|
true
|
60
79
|
end
|
61
80
|
|
81
|
+
# Writes one batch to file and submits it to the DCAS outgoing payments bucket.
|
82
|
+
# You can optionally supply a 'lock' object, which must respond to:
|
83
|
+
# #submit_locked?
|
84
|
+
# #submit_lock!(filename)
|
85
|
+
# #submit_finished!(filename)
|
86
|
+
# #submit_failed!(filename)
|
87
|
+
# If a lock_object is supplied, the method will mark it as failed and return false instead of raising an error, in case of failure.
|
88
|
+
def submit_batch!(batch, lock_object=nil)
|
89
|
+
File.makedirs(cache_location)
|
90
|
+
filename = cache_location + "/" + batch.filename
|
91
|
+
# 1) Create the file locally.
|
92
|
+
File.open(filename) {|f| f << batch.to_csv }
|
93
|
+
# 2) Upload it to the DCAS outgoing payments bucket.
|
94
|
+
submit_payments_file!(filename, lock_object)
|
95
|
+
end
|
96
|
+
|
62
97
|
# Writes all batches to file and submits them to the DCAS outgoing payments bucket.
|
63
|
-
|
98
|
+
# You can optionally supply a 'lock' object, which must respond to:
|
99
|
+
# #submit_locked?
|
100
|
+
# #submit_lock!(filename)
|
101
|
+
# #submit_finished!(filename)
|
102
|
+
# #submit_failed!(filename)
|
103
|
+
def submit_batches!(lock_object=nil)
|
64
104
|
File.makedirs(cache_location)
|
65
105
|
batches_submitted = 0
|
66
|
-
with_ftp do
|
106
|
+
with_ftp do # causes all batches to be uploaded in a single session
|
67
107
|
# 1) Gather all payments for this client.
|
68
108
|
batches.each do |batch| # 2) For each file type (ach, cc) yet to be uploaded:
|
69
|
-
|
70
|
-
# 1) Create the file locally.
|
71
|
-
File.open(filename) {|f| f << batch.to_csv }
|
72
|
-
# 2) Upload it to the DCAS outgoing payments bucket.
|
73
|
-
batches_submitted += 1 if submit_payments_file!(filename)
|
109
|
+
batches_submitted += 1 if submit_batch!(batch, lock_object)
|
74
110
|
end
|
75
111
|
end
|
112
|
+
batches_submitted
|
76
113
|
end
|
77
114
|
|
78
115
|
# Checks for response files in the DCAS incoming responses bucket.
|
data/spec/dcas_spec.rb
CHANGED
@@ -14,14 +14,14 @@ describe "Dcas - Comprehensive failure frequency test" do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
it "should generate Ach payment files correctly" do
|
17
|
-
ach_batch = @fake_client.new_batch(
|
17
|
+
ach_batch = @fake_client.new_batch('1001')
|
18
18
|
Fixtures[:TestPayments][:Ach].collect {|p| ach_batch << DCAS::AchPayment.new(*p) }
|
19
19
|
ach_payments_file = ach_batch.to_csv
|
20
20
|
ach_payments_file.should eql(File.read('spec/fixtures/ach_payments.csv'))
|
21
21
|
end
|
22
22
|
|
23
23
|
it "should generate CreditCard payment files correctly" do
|
24
|
-
cc_batch = @fake_client.new_batch(
|
24
|
+
cc_batch = @fake_client.new_batch('1001')
|
25
25
|
Fixtures[:TestPayments][:CreditCard].collect {|p| cc_batch << DCAS::CreditCardPayment.new(*p) }
|
26
26
|
cc_payments_file = cc_batch.to_csv
|
27
27
|
cc_payments_file.should eql(File.read('spec/fixtures/credit_card_payments.csv'))
|
@@ -32,10 +32,10 @@ describe "Dcas - Comprehensive failure frequency test" do
|
|
32
32
|
# Depends: Fixture load of a list of DCAS logins to test
|
33
33
|
# Depends: Fixed test files
|
34
34
|
Fixtures[:Clients].each do |client|
|
35
|
-
cc_batch = client.new_batch(
|
35
|
+
cc_batch = client.new_batch('123')
|
36
36
|
Fixtures[:TestPayments][:CreditCard].each {|p| cc_batch << DCAS::CreditCardPayment.new(*p) }
|
37
37
|
|
38
|
-
ach_batch = client.new_batch(
|
38
|
+
ach_batch = client.new_batch('123')
|
39
39
|
Fixtures[:TestPayments][:Ach].each {|p| ach_batch << DCAS::AchPayment.new(*p) }
|
40
40
|
|
41
41
|
client.submit_batches!.should eql(Fixtures[:PaymentFiles].length)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
---
|
2
2
|
-
|
3
|
-
- '
|
3
|
+
- '11428'
|
4
4
|
- 'Dan Hall'
|
5
5
|
- '18.88'
|
6
6
|
- 'Checking'
|
@@ -8,7 +8,7 @@
|
|
8
8
|
- '182045828'
|
9
9
|
- '2010010'
|
10
10
|
-
|
11
|
-
- '
|
11
|
+
- '11200'
|
12
12
|
- 'Karie Moore'
|
13
13
|
- '18.88'
|
14
14
|
- 'Checking'
|
@@ -16,7 +16,7 @@
|
|
16
16
|
- '584218548'
|
17
17
|
- '2010010'
|
18
18
|
-
|
19
|
-
- '
|
19
|
+
- '11829'
|
20
20
|
- 'Therese Boon'
|
21
21
|
- '18.88'
|
22
22
|
- 'Checking'
|
@@ -24,7 +24,7 @@
|
|
24
24
|
- '94217885428'
|
25
25
|
- '2010010'
|
26
26
|
-
|
27
|
-
- '
|
27
|
+
- '11282'
|
28
28
|
- 'Gretchen Gutierrez'
|
29
29
|
- '18.88'
|
30
30
|
- 'Savings'
|
@@ -32,7 +32,7 @@
|
|
32
32
|
- '24254'
|
33
33
|
- '2010010'
|
34
34
|
-
|
35
|
-
- '
|
35
|
+
- '11795'
|
36
36
|
- 'Audrice Pitto'
|
37
37
|
- '18.88'
|
38
38
|
- 'Checking'
|
@@ -40,7 +40,7 @@
|
|
40
40
|
- '280458548254'
|
41
41
|
- '2010010'
|
42
42
|
-
|
43
|
-
- '
|
43
|
+
- '11537'
|
44
44
|
- 'Rachel Ruppert'
|
45
45
|
- '18.88'
|
46
46
|
- 'Checking'
|
@@ -48,7 +48,7 @@
|
|
48
48
|
- '641081508245'
|
49
49
|
- '2010010'
|
50
50
|
-
|
51
|
-
- '
|
51
|
+
- '11892'
|
52
52
|
- 'Judith Witlock'
|
53
53
|
- '18.88'
|
54
54
|
- 'Checking'
|
@@ -56,7 +56,7 @@
|
|
56
56
|
- '52488542858'
|
57
57
|
- '2010010'
|
58
58
|
-
|
59
|
-
- '
|
59
|
+
- '11172'
|
60
60
|
- 'Kris Martell'
|
61
61
|
- '18.88'
|
62
62
|
- 'Savings'
|
@@ -64,7 +64,7 @@
|
|
64
64
|
- '4728458248'
|
65
65
|
- '2010010'
|
66
66
|
-
|
67
|
-
- '
|
67
|
+
- '11284'
|
68
68
|
- 'Michell Penderson'
|
69
69
|
- '18.88'
|
70
70
|
- 'Checking'
|
@@ -72,7 +72,7 @@
|
|
72
72
|
- '38184599459'
|
73
73
|
- '2010010'
|
74
74
|
-
|
75
|
-
- '
|
75
|
+
- '11756'
|
76
76
|
- 'Polly Clark'
|
77
77
|
- '18.88'
|
78
78
|
- 'Checking'
|
@@ -1,69 +1,69 @@
|
|
1
1
|
---
|
2
2
|
-
|
3
|
-
- '
|
3
|
+
- '11532'
|
4
4
|
- 'Kipp Owen'
|
5
5
|
- '18.88'
|
6
6
|
- 'VISA'
|
7
7
|
- '4508288028044788'
|
8
8
|
- '12/2010'
|
9
9
|
-
|
10
|
-
- '
|
10
|
+
- '11382'
|
11
11
|
- 'Brooke Racquet'
|
12
12
|
- '18.88'
|
13
13
|
- 'VISA'
|
14
14
|
- '4979170284809229'
|
15
15
|
- '12/2011'
|
16
16
|
-
|
17
|
-
- '
|
17
|
+
- '11018'
|
18
18
|
- 'Pat Sylvester'
|
19
19
|
- '18.88'
|
20
20
|
- 'MCRD'
|
21
21
|
- '5280827180294022'
|
22
22
|
- '12/2012'
|
23
23
|
-
|
24
|
-
- '
|
24
|
+
- '11992'
|
25
25
|
- 'Vicki Tolliki'
|
26
26
|
- '18.88'
|
27
27
|
- 'MCRD'
|
28
28
|
- '5173179138280429'
|
29
29
|
- '12/2011'
|
30
30
|
-
|
31
|
-
- '
|
31
|
+
- '11247'
|
32
32
|
- 'Cheryl Barger'
|
33
33
|
- '18.88'
|
34
34
|
- 'VISA'
|
35
35
|
- '4247972792081828'
|
36
36
|
- '12/2010'
|
37
37
|
-
|
38
|
-
- '
|
38
|
+
- '11028'
|
39
39
|
- 'Melissa Fletcher'
|
40
40
|
- '18.88'
|
41
41
|
- 'MCRD'
|
42
42
|
- '5428208180420824'
|
43
43
|
- '12/2011'
|
44
44
|
-
|
45
|
-
- '
|
45
|
+
- '11384'
|
46
46
|
- 'Mack Payne'
|
47
47
|
- '18.88'
|
48
48
|
- 'MCRD'
|
49
49
|
- '5425682492949922'
|
50
50
|
- '12/2012'
|
51
51
|
-
|
52
|
-
- '
|
52
|
+
- '11742'
|
53
53
|
- 'Melissa Latcher'
|
54
54
|
- '18.88'
|
55
55
|
- 'MCRD'
|
56
56
|
- '5208372629781292'
|
57
57
|
- '12/2011'
|
58
58
|
-
|
59
|
-
- '
|
59
|
+
- '11402'
|
60
60
|
- 'Caroline Sieben'
|
61
61
|
- '18.88'
|
62
62
|
- 'MCRD'
|
63
63
|
- '5181381081538389'
|
64
64
|
- '12/2012'
|
65
65
|
-
|
66
|
-
- '
|
66
|
+
- '11208'
|
67
67
|
- 'Charlotte Sue Hiran'
|
68
68
|
- '18.88'
|
69
69
|
- 'MCRD'
|