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
  @outgoing_bucket = DEFAULT_OUTGOING_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

#outgoing_bucketObject

Returns the value of attribute outgoing_bucket.



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

def outgoing_bucket
  @outgoing_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.



131
132
133
134
135
136
137
138
139
140
141
# File 'lib/dcas.rb', line 131

def available_response_files
  with_ftp do |ftp|
    # 3) List the *.csv files in the INCOMING bucket.
    result = if ftp.nlst.include?(DCAS::INCOMING_BUCKET)
      ftp.chdir(DCAS::INCOMING_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.



144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/dcas.rb', line 144

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 outgoing 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.



103
104
105
106
107
108
109
110
# File 'lib/dcas.rb', line 103

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 outgoing 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 outgoing payments bucket. You can optionally supply a ‘lock’ object, which must respond to:

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


118
119
120
121
122
123
124
125
126
127
128
# File 'lib/dcas.rb', line 118

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 outgoing 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
# 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)
          ftp.rename(shortname, "../#{outgoing_bucket}/#{shortname}") unless testing || outgoing_bucket == DCAS::STAGING_BUCKET
          lock_object.submit_finished!(shortname) if lock_object
          true
        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
        false
      end
    end
    lock_object.submit_failed!(shortname) if lock_object && res.nil?
    res
  end
end