Class: FirstDirect::Account

Inherits:
Struct
  • Object
show all
Includes:
Helpers
Defined in:
lib/firstdirect.rb

Overview

An Account represents an item listed on the first page we see on login. It has a pointer to its parent FirstDirect object, so that it can fetch pages etc.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Helpers

#colour, #strip_js, #trace

Instance Attribute Details

#balanceObject

Returns the value of attribute balance

Returns:

  • (Object)

    the current value of balance



230
231
232
# File 'lib/firstdirect.rb', line 230

def balance
  @balance
end

Returns the value of attribute link

Returns:

  • (Object)

    the current value of link



230
231
232
# File 'lib/firstdirect.rb', line 230

def link
  @link
end

#nameObject

Returns the value of attribute name

Returns:

  • (Object)

    the current value of name



230
231
232
# File 'lib/firstdirect.rb', line 230

def name
  @name
end

#numberObject

Returns the value of attribute number

Returns:

  • (Object)

    the current value of number



230
231
232
# File 'lib/firstdirect.rb', line 230

def number
  @number
end

#parentObject

Returns the value of attribute parent

Returns:

  • (Object)

    the current value of parent



230
231
232
# File 'lib/firstdirect.rb', line 230

def parent
  @parent
end

Instance Method Details

#download(options = {}) ⇒ Object

Fetch this account’s most recent statement.

By default:

  • we’ll fetch the data to yesterday;

  • we’ll fetch from a month before the to date;

  • we’ll fetch the data in ‘Microsoft Excel’ format, ie CSV, but you could choose any option that FirstDirect provide on their download page.

Example:

.download(:from => '2008-01-01')
.download(:from => '2008-01-01', :to => '2008-01-07')
.download(:to => '2008-01-07', :format => 'Quicken 97')

Raises:



317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
# File 'lib/firstdirect.rb', line 317

def download(options={})
  options[:to] ||= Time.now - 86400
  options[:from] ||= options[:to] - 30 * 86400
  options[:format] ||= 'Microsoft Excel'
  
  if Time.now - options[:to] < 86400
    $stderr.puts "we can't look at transactions from less than a day ago: #{to_age}s is too young"
    options[:to] -= 86400 
  end

  # Look for the download link
  download_a = page.search('//a[@class="fdActionLinkStatements"]').select do |elem|
    elem.inner_html.strip == 'download'
  end.first

  # Choose a date range
  date_page = trace('getting date page') { parent.agent.get Helpers.strip_js(download_a) }
  date_form = date_page.forms.first

  raise Error, "no date_form found" if date_form.nil?

  date_form['DownloadFormat']   = options[:format]
  date_form['DownloadFromDate'] = massage_time(options[:from])
  date_form['DownloadToDate']   = massage_time(options[:to])

  # LiveHTTPHeaders says that the form is posted with these parameters:
  #
  #   Transactions=1
  #   DownloadFromDate=05%2F04%2F2008
  #   DownloadToDate=03%2F07%2F2008
  #   DownloadFormat=Quicken+97
  #   SaveInCookie=UNSELECTED
  #   EVENTID=UPDATE
  #   CCID=????
  #   FEBCCID=
  #   MODIFIER=
  #   ALERTS=
  #   LINKID=
  #   MENUMODE=
  #   SupportsDirectPrint=FALSE
  #   UTI=0
  # 
  # However, I notice that the date_form's "EVENTID" and "CCID" aren't set
  # by default.  Maybe they are set by Javascript?
  #
  date_form['EVENTID'] = 'UPDATE'
  
  #
  # Oddly, unlike if we use a real browser, when we submit this date
  # form, we get back a page that contains the data we wanted, but inside
  # a <form></form> tag-pair.
  #
  page_with_data = trace('submitting date form'){ parent.agent.submit(date_form) }
  data = page_with_data.at('//form[@name="FsdtL2Wform"]').inner_html.strip
  if data.match(/^<!--/)
    raise Error, "data downloaded looks like rubbish: #{data[0..20]}"
  else
    return data
  end
end

#massage_time(t) ⇒ Object

Turn the given object t into a date acceptable by the download form: dd/mm/yyyy.



296
297
298
299
# File 'lib/firstdirect.rb', line 296

def massage_time(t)
  t = Time.parse(t.to_s) unless t.kind_of?(Time)
  t.strftime('%d/%m/%Y')
end

#page(options = {}) ⇒ Object

Go to the recent-statement page for this account, which we’ll need to do statement downloading.

The page is cached – if you want to force an update:

.page(:update => true)

This is a lazy accessor for @__page. Please don’t use @__page directly! In fact, I think I’ll rename it to @__page (from @page) to discourage such access!



251
252
253
254
255
256
# File 'lib/firstdirect.rb', line 251

def page(options={})
  if @__page.nil? or options[:update]
    trace('getting account page'){ @__page = parent.agent.get(link) }
  end
  @__page
end

#recent_statement_arrayObject

Parse a recent-statement from this Account’s page.



261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'lib/firstdirect.rb', line 261

def recent_statement_array
  data = []

  table = page.at('table.fdStatTable')
  headings = (table / 'thead/tr/th').map{ |el| el.inner_text.strip }
  data << headings

  last_row_data = nil
  (table / 'tbody/tr').each do |row|
    row_data = (row / 'td').map{ |el| el.inner_text.strip }
    row_data[0] = last_row_data[0] if row_data[0].empty? and last_row_data
    last_row_data = row_data
    data << row_data
  end

  return data
end

#recent_statement_csvObject

Return the recent-statement in CSV format.



282
283
284
285
286
287
288
289
290
# File 'lib/firstdirect.rb', line 282

def recent_statement_csv
  require 'csv'
  string = ''
  csv = CSV::Writer.create(string)
  for row in recent_statement_array
    csv << row
  end
  return string
end

#to_sObject



233
234
235
# File 'lib/firstdirect.rb', line 233

def to_s
  "#{name} (#{number}): #{balance}"
end