Class: DCAS::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/dcas.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Client

Instantiate a new Client object which can do authenticated actions in a DCAS FTPS bucket.

Raises:

  • (ArgumentError)


19
20
21
22
23
24
25
26
27
28
29
# File 'lib/dcas.rb', line 19

def initialize(options={})
  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}
  @username = options[:username].to_s
  @password = options[:password].to_s
  @company_alias = options[:company_alias].to_s
  @company_username = options[:company_username].to_s
  @company_password = options[:company_password].to_s
  @cache_location = options[:cache_location].to_s || DEFAULT_CACHE_LOCATION
  @incoming_bucket = DEFAULT_INCOMING_BUCKET
  @testing = TESTING
end

Instance Attribute Details

#cache_locationObject

Returns the value of attribute cache_location.



32
33
34
# File 'lib/dcas.rb', line 32

def cache_location
  @cache_location
end

#company_aliasObject (readonly)

Returns the value of attribute company_alias.



31
32
33
# File 'lib/dcas.rb', line 31

def company_alias
  @company_alias
end

#company_passwordObject (readonly)

Returns the value of attribute company_password.



31
32
33
# File 'lib/dcas.rb', line 31

def company_password
  @company_password
end

#company_usernameObject (readonly)

Returns the value of attribute company_username.



31
32
33
# File 'lib/dcas.rb', line 31

def company_username
  @company_username
end

#incoming_bucketObject

Returns the value of attribute incoming_bucket.



32
33
34
# File 'lib/dcas.rb', line 32

def incoming_bucket
  @incoming_bucket
end

#passwordObject (readonly)

Returns the value of attribute password.



31
32
33
# File 'lib/dcas.rb', line 31

def password
  @password
end

#testingObject

Returns the value of attribute testing.



32
33
34
# File 'lib/dcas.rb', line 32

def testing
  @testing
end

#usernameObject (readonly)

Returns the value of attribute username.



31
32
33
# File 'lib/dcas.rb', line 31

def username
  @username
end

Instance Method Details

#available_response_filesObject

Checks for response files in the DCAS incoming responses bucket.



138
139
140
141
142
143
144
145
146
147
148
# File 'lib/dcas.rb', line 138

def available_response_files
  with_ftp do |ftp|
    # 3) List the *.csv files in the OUTGOING bucket.
    result = if ftp.nlst.include?(DCAS::DEFAULT_OUTGOING_BUCKET)
      ftp.chdir(DCAS::DEFAULT_OUTGOING_BUCKET)
      ftp.nlst.select {|f| f =~ /\.csv$/}
    else
      []
    end
  end
end

#batchesObject

:nodoc:



35
36
37
# File 'lib/dcas.rb', line 35

def batches
  @batches ||= []
end

#download_response_files!Object

Downloads all response files in the DCAS incoming responses bucket.



151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/dcas.rb', line 151

def download_response_files!
  files_downloaded = []
  File.makedirs(cache_location + '/returns')
  with_ftp do |ftp|
    files = ftp.list('*.csv')
    files.each do |filels|
      size, file = filels.split(/ +/)[4], filels.split(/ +/)[8..-1].join(' ')
      ftp.get(file, cache_location + '/returns/' + user_suffix + '_' + file)
      files_downloaded << file
    end
  end
  files_downloaded
end

#new_batch(batch_id) ⇒ Object

Begin a new batch associated with this client.



40
41
42
43
# File 'lib/dcas.rb', line 40

def new_batch(batch_id)
  batches << DCAS::PaymentBatch.new(self, batch_id)
  batches.last
end

#submit_batch!(batch, lock_object = nil) ⇒ Object

Writes one batch to file and submits it to the DCAS incoming payments bucket. You can optionally supply a ‘lock’ object, which must respond to:

#submit_locked?
#submit_lock!(filename)
#submit_finished!(filename)
#submit_failed!(filename)

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.



110
111
112
113
114
115
116
117
# File 'lib/dcas.rb', line 110

def submit_batch!(batch, lock_object=nil)
  File.makedirs(cache_location)
  filename = cache_location + "/" + batch.filename
  # 1) Create the file locally.
  File.open(filename, 'w') {|f| f << batch.to_csv }
  # 2) Upload it to the DCAS incoming payments bucket.
  submit_payments_file!(filename, lock_object)
end

#submit_batches!(lock_object = nil) ⇒ Object

Writes all batches to file and submits them to the DCAS incoming payments bucket. You can optionally supply a ‘lock’ object, which must respond to:

#submit_locked?
#submit_lock!(filename)
#submit_finished!(filename)
#submit_failed!(filename)


125
126
127
128
129
130
131
132
133
134
135
# File 'lib/dcas.rb', line 125

def submit_batches!(lock_object=nil)
  File.makedirs(cache_location)
   = 0
  with_ftp do # causes all batches to be uploaded in a single session
    # 1) Gather all payments for this client.
    batches.each do |batch| # 2) For each file type (ach, cc) yet to be uploaded:
       += 1 if submit_batch!(batch, lock_object)
    end
  end
  
end

#submit_payments_file!(filename, lock_object = nil) ⇒ Object

Uploads a single payments file to the DCAS incoming payments bucket. You can optionally supply a ‘lock’ object, which must respond to:

#submit_locked?(filename)
#submit_lock!(filename)
#submit_finished!(filename)
#submit_failed!(filename)

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.



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/dcas.rb', line 52

def submit_payments_file!(filename, lock_object=nil)
  shortname = filename.match(/[\\\/]([^\\\/]+)$/)[1]
  if lock_object && lock_object.submit_locked?(shortname)
    # raise RuntimeError, "Submit for #{shortname} is locked!"
    return nil
  else
    lock_object.submit_lock!(shortname) if lock_object
    res = with_ftp do |ftp|
      # 1) Create the STAGING folder if it's not already there.
      begin
        ftp.mkdir(DCAS::STAGING_BUCKET) unless ftp.nlst.include?(DCAS::STAGING_BUCKET)
        ftp.chdir(DCAS::STAGING_BUCKET)
        # 2) Delete the same filename from the STAGING folder if one exists.
        ftp.delete(shortname) if ftp.nlst.include?(shortname)
        # 3) Upload the file into the STAGING folder.
        puts "Uploading #{filename} as #{shortname}..."
        ftp.put(filename, shortname)
        true
      rescue Object
        lock_object.submit_failed!(shortname) if lock_object
        false
      end && begin
        # 4) If we're still connected, check the file size of the file, then move it out of STAGING and mark file as completed.
        if ftp.nlst.include?(shortname) && ftp.size(shortname) == File.size(filename)
          begin
            ftp.rename(shortname, "../#{incoming_bucket}/#{shortname}") unless testing || incoming_bucket == DCAS::STAGING_BUCKET
            true
          rescue Object
            false
          end && begin
            lock_object.submit_finished!(shortname) if lock_object
            true
          end
        else
          if lock_object
            lock_object.submit_failed!(shortname)
            false
          else
            raise RuntimeError, "FAILED uploading `#{filename}' - incomplete or unsuccessful upload. Please try again."
          end
        end
      rescue Object
        lock_object.submit_failed!(shortname) if lock_object
        false
      end
    end
    lock_object.submit_failed!(shortname) if lock_object && res.nil?
    res
  end
end