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 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 = DCAS::Client.new(:username => 'angola', :password => '4ng014', :cache_location => './EFT')
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
1
+ 0.2.0
data/dcas-ruby.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{dcas-ruby}
8
- s.version = "0.1.0"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["BehindLogic"]
data/lib/dcas/payment.rb CHANGED
@@ -25,6 +25,10 @@ module DCAS
25
25
  payments.first.class.name.gsub(/.*::/,'').downcase
26
26
  end
27
27
 
28
+ def filename
29
+ "#{@client.company_user}_#{type}.csv"
30
+ end
31
+
28
32
  # Generates a payment batch file and returns its contents.
29
33
  def to_csv
30
34
  FasterCSV.generate do |csv|
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, :company_password, and :cache_location" if [:username, :password, :company_alias, :company_username, :company_password, :cache_location].any? {|k| !options.has_key?(k)}
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, :cache_location
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
- def submit_payments_file!(filename)
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
- with_ftp do |ftp|
45
- # 1) Create the STAGING folder if it's not already there.
46
- ftp.mkdir(DCAS::STAGING_BUCKET) unless ftp.nlst.include?(DCAS::STAGING_BUCKET)
47
- ftp.chdir(DCAS::STAGING_BUCKET)
48
- # 2) Delete the same filename from the STAGING folder if one exists.
49
- ftp.delete(shortname) if ftp.nlst.include?(shortname)
50
- # 3) Upload the file into the STAGING folder.
51
- ftp.put(filename, shortname)
52
- # 4) If we're still connected, check the file size of the file, then move it out of STAGING and mark file as completed.
53
- if ftp.nlst.include?(shortname) && ftp.size(shortname) == File.size(filename)
54
- ftp.rename(shortname, "../#{DCAS::OUTGOING_BUCKET}/#{shortname}") unless DCAS::TESTING
55
- else
56
- raise RuntimeError, "FAILED uploading `#{filename}' - incomplete or unsuccessful upload. Please try again."
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
- def submit_batches!
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
- filename = cache_location + "/#{company_user}_#{batch.type}_#{Time.now.strftime("%Y%m%d")}.csv"
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(1)
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(1)
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(1)
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(1)
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
- - '00111428'
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
- - '00111200'
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
- - '00111829'
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
- - '00111282'
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
- - '00111795'
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
- - '00111537'
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
- - '00111892'
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
- - '00111172'
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
- - '00111284'
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
- - '00111756'
75
+ - '11756'
76
76
  - 'Polly Clark'
77
77
  - '18.88'
78
78
  - 'Checking'
@@ -1,69 +1,69 @@
1
1
  ---
2
2
  -
3
- - '00111532'
3
+ - '11532'
4
4
  - 'Kipp Owen'
5
5
  - '18.88'
6
6
  - 'VISA'
7
7
  - '4508288028044788'
8
8
  - '12/2010'
9
9
  -
10
- - '00111382'
10
+ - '11382'
11
11
  - 'Brooke Racquet'
12
12
  - '18.88'
13
13
  - 'VISA'
14
14
  - '4979170284809229'
15
15
  - '12/2011'
16
16
  -
17
- - '00111018'
17
+ - '11018'
18
18
  - 'Pat Sylvester'
19
19
  - '18.88'
20
20
  - 'MCRD'
21
21
  - '5280827180294022'
22
22
  - '12/2012'
23
23
  -
24
- - '00111992'
24
+ - '11992'
25
25
  - 'Vicki Tolliki'
26
26
  - '18.88'
27
27
  - 'MCRD'
28
28
  - '5173179138280429'
29
29
  - '12/2011'
30
30
  -
31
- - '00111247'
31
+ - '11247'
32
32
  - 'Cheryl Barger'
33
33
  - '18.88'
34
34
  - 'VISA'
35
35
  - '4247972792081828'
36
36
  - '12/2010'
37
37
  -
38
- - '00111028'
38
+ - '11028'
39
39
  - 'Melissa Fletcher'
40
40
  - '18.88'
41
41
  - 'MCRD'
42
42
  - '5428208180420824'
43
43
  - '12/2011'
44
44
  -
45
- - '00111384'
45
+ - '11384'
46
46
  - 'Mack Payne'
47
47
  - '18.88'
48
48
  - 'MCRD'
49
49
  - '5425682492949922'
50
50
  - '12/2012'
51
51
  -
52
- - '00111742'
52
+ - '11742'
53
53
  - 'Melissa Latcher'
54
54
  - '18.88'
55
55
  - 'MCRD'
56
56
  - '5208372629781292'
57
57
  - '12/2011'
58
58
  -
59
- - '00111402'
59
+ - '11402'
60
60
  - 'Caroline Sieben'
61
61
  - '18.88'
62
62
  - 'MCRD'
63
63
  - '5181381081538389'
64
64
  - '12/2012'
65
65
  -
66
- - '00111208'
66
+ - '11208'
67
67
  - 'Charlotte Sue Hiran'
68
68
  - '18.88'
69
69
  - 'MCRD'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dcas-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - BehindLogic