dinero 0.0.6 → 0.0.7
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +6 -4
- data/examples/scottrade.rb +32 -0
- data/lib/dinero.rb +1 -0
- data/lib/dinero/banks/scottrade.rb +119 -0
- data/lib/dinero/version.rb +1 -1
- data/spec/banks/scottrade_spec.rb +56 -0
- metadata +5 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 10736ddeeabb779f6f1654971c33c8169633337a
|
4
|
+
data.tar.gz: 71d3256e43c8e91f52655efafe2ce6a397f8a81f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 55469145a47545ba9829e3062ea1e4652d7e9b4911ed42f7217d23cb8b5c3d0c1b1a8a01d753f5ecfb78b66702d575890b32188c0fcd4ec5ce367b139da63f18
|
7
|
+
data.tar.gz: c149aeccd49f59004e5310777f4234e41082f86482dc6122adbc5e106ed26911f9fa2fe93ed55aa094cb7c6a98d38d39f245ed1dc39e0218796d32d0d393c3b3
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -26,10 +26,12 @@ Much like ActiveRecord sought to standardize the API for accessing and modeling
|
|
26
26
|
|
27
27
|
The following banks are implemented:
|
28
28
|
|
29
|
-
* Capital One - https://capitalone.com (only U.S. credit card logins -- there's also banking, loans, investing, business, and Canada/UK credit cards)
|
30
|
-
* Capital One 360 - https://capitalone360.com (formerly Ing Direct).
|
31
|
-
* South State Bank - https://www.southstatebank.com/
|
32
|
-
* San Diego County Credit Union - https://www.sdccu.com/
|
29
|
+
* Capital One - https://capitalone.com (only U.S. credit card logins -- there's also banking, loans, investing, business, and Canada/UK credit cards)
|
30
|
+
* Capital One 360 - https://capitalone360.com (formerly Ing Direct).
|
31
|
+
* South State Bank - https://www.southstatebank.com/
|
32
|
+
* San Diego County Credit Union - https://www.sdccu.com/
|
33
|
+
* Georgia's Own Credit Union - https://www.georgiasown.org/
|
34
|
+
* Scottrade - https://www.scottrade.com/
|
33
35
|
|
34
36
|
Currently, only Accounts balances are implemented. The following properties are available on each Account:
|
35
37
|
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require_relative '../lib/dinero'
|
2
|
+
require 'pry-byebug'
|
3
|
+
|
4
|
+
@config = YAML.load_file('spec/config/banks.yml').fetch("scottrade2", {})
|
5
|
+
|
6
|
+
@username = @config["username"]
|
7
|
+
@password = @config["password"]
|
8
|
+
|
9
|
+
def camelize term
|
10
|
+
string = term.to_s.sub(/^[a-z\d]*/) { $&.capitalize }
|
11
|
+
string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{$2.capitalize}" }
|
12
|
+
string.gsub!(/\//, '::')
|
13
|
+
string
|
14
|
+
end
|
15
|
+
|
16
|
+
def show_balances bank
|
17
|
+
puts "Retrieving your bank account information..."
|
18
|
+
bank.accounts
|
19
|
+
|
20
|
+
puts "+" + "-" * 80 + "+"
|
21
|
+
puts "| %35s | %12s | %11s | %11s |" % %w(name number balance available)
|
22
|
+
puts "+" + "-" * 80 + "+"
|
23
|
+
bank.accounts.each do |acct|
|
24
|
+
puts "| %35s | %12s | $%10.2f | $%10.2f |" % [acct.name, acct.number, acct.balance, acct.available]
|
25
|
+
end
|
26
|
+
puts "+" + "-" * 80 + "+"
|
27
|
+
end
|
28
|
+
|
29
|
+
bank = Dinero::Bank::Scottrade.new(username: @username, password: @password)
|
30
|
+
|
31
|
+
bank.login!
|
32
|
+
show_balances bank
|
data/lib/dinero.rb
CHANGED
@@ -10,6 +10,7 @@ require_relative 'dinero/banks/capital_one_360'
|
|
10
10
|
require_relative 'dinero/banks/south_state_bank'
|
11
11
|
require_relative 'dinero/banks/sdccu'
|
12
12
|
require_relative 'dinero/banks/georgias_own'
|
13
|
+
require_relative 'dinero/banks/scottrade'
|
13
14
|
|
14
15
|
# Models
|
15
16
|
require_relative 'dinero/account'
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module Dinero
|
2
|
+
module Bank
|
3
|
+
# San Diego County Credit Union
|
4
|
+
class Scottrade < Base
|
5
|
+
LOGIN_URL = "https://trading.scottrade.com/default.aspx"
|
6
|
+
CONNECTION_TIMEOUT = 20
|
7
|
+
|
8
|
+
def default_options
|
9
|
+
{ timeout: CONNECTION_TIMEOUT, login_url: LOGIN_URL }
|
10
|
+
end
|
11
|
+
|
12
|
+
def post_username!
|
13
|
+
screenshot_on_error do
|
14
|
+
wait.until { connection.find_element(id: "ctl00_body_txtAccountNumber") }
|
15
|
+
username_field = connection.find_element(id: "ctl00_body_txtAccountNumber")
|
16
|
+
username_field.send_keys username
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def post_password!
|
21
|
+
screenshot_on_error do
|
22
|
+
password_field = connection.find_element(id: "ctl00_body_txtPassword")
|
23
|
+
password_field.send_keys password
|
24
|
+
|
25
|
+
login_btn = connection.find_element(id: "ctl00_body_btnLogin")
|
26
|
+
login_btn.click
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def skip_confirmations_page
|
31
|
+
if connection.page_source =~ /has trade confirmations/
|
32
|
+
button = connection.find_element(id: "ctl00_body_btnViewLater")
|
33
|
+
button.click
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# <button type="button" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" role="button" aria-disabled="false"><span class="ui-button-text">Close</span></button>
|
38
|
+
def skip_monthly_statements_modal
|
39
|
+
if connection.page_source =~ /ui\-dialog\-title\-monthlyStatementsDiv/
|
40
|
+
button = connection.find_element(xpath: "button[@class='ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only']")
|
41
|
+
button.click
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def post_credentials!
|
46
|
+
post_username!
|
47
|
+
post_password!
|
48
|
+
skip_confirmations_page
|
49
|
+
skip_monthly_statements_modal
|
50
|
+
expand_bank_table
|
51
|
+
end
|
52
|
+
|
53
|
+
def after_successful_login
|
54
|
+
# the subdomain frequently changes, so capture the actual URL
|
55
|
+
# so we can return to the page if necessary.
|
56
|
+
@accounts_summary_url = connection.current_url
|
57
|
+
end
|
58
|
+
|
59
|
+
def on_accounts_summary_page?
|
60
|
+
connection.page_source =~ /Brokerage Balances/
|
61
|
+
end
|
62
|
+
|
63
|
+
def goto_accounts_summary_page
|
64
|
+
return if authenticated? && on_accounts_summary_page?
|
65
|
+
authenticated? ? connection.navigate.to(@accounts_summary_url) : login!
|
66
|
+
end
|
67
|
+
|
68
|
+
def expand_bank_table
|
69
|
+
return unless connection.page_source =~ /ctl00_PageContent_ctl02_w1_widgetContent1_lblDisplayBankBalanceLink/
|
70
|
+
expand_link = connection.find_element(id: "ctl00_PageContent_ctl02_w1_widgetContent1_lblDisplayBankBalanceLink")
|
71
|
+
expand_link.click
|
72
|
+
wait.until { connection.find_element(id: "bankBalance66") }
|
73
|
+
end
|
74
|
+
|
75
|
+
def brokerage_table
|
76
|
+
accounts_summary_document.css("#ctl00_PageContent_ctl02_w1_widgetContent1_tblBalanceElements66").first
|
77
|
+
end
|
78
|
+
|
79
|
+
def bank_table
|
80
|
+
table = accounts_summary_document.css("#bankBalance66")
|
81
|
+
end
|
82
|
+
|
83
|
+
def brokerage_data
|
84
|
+
rows = brokerage_table.xpath("tbody/tr").map{|tr| tr.xpath("td").map(&:text)}
|
85
|
+
available = rows.shift.last
|
86
|
+
rows.shift
|
87
|
+
rows.shift
|
88
|
+
balance = rows.shift.last
|
89
|
+
return { available: available, balance: balance }
|
90
|
+
end
|
91
|
+
|
92
|
+
def brokerage_account
|
93
|
+
data = brokerage_data
|
94
|
+
Account.new :brokerage, username, username, data[:balance], data[:available]
|
95
|
+
end
|
96
|
+
|
97
|
+
def bank_data
|
98
|
+
rows = bank_table.xpath("tbody/tr").map{|tr| tr.xpath("td").map(&:text)}
|
99
|
+
available = rows.shift.last
|
100
|
+
balance = rows.shift.last
|
101
|
+
return { available: available, balance: balance }
|
102
|
+
rescue
|
103
|
+
return nil
|
104
|
+
end
|
105
|
+
|
106
|
+
def bank_account
|
107
|
+
if data = bank_data
|
108
|
+
Account.new :bank, "Bank", "", data[:balance], data[:available]
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# extract account data from the account summary page
|
113
|
+
def accounts
|
114
|
+
return @accounts if @accounts
|
115
|
+
@accounts = [ brokerage_account, bank_account ].compact
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
data/lib/dinero/version.rb
CHANGED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
if bank_configured? :scottrade
|
4
|
+
|
5
|
+
RSpec.describe Dinero::Bank::Scottrade do
|
6
|
+
let(:bank_configuration) { bank_configurations[:scottrade] }
|
7
|
+
let(:account_types) { bank_configuration[:account_types] }
|
8
|
+
let(:accounts) { bank_configuration[:accounts] }
|
9
|
+
let(:acct_name) { bank_configuration[:acct_name] }
|
10
|
+
|
11
|
+
before(:all) do
|
12
|
+
VCR.use_cassette("accounts_scottrade", record: :new_episodes) do
|
13
|
+
@bank = Dinero::Bank::Scottrade.new(bank_configurations[:scottrade])
|
14
|
+
@bank.accounts
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it "authenticates" do
|
19
|
+
@bank.login!
|
20
|
+
expect(@bank.authenticated?).to eq true
|
21
|
+
end
|
22
|
+
|
23
|
+
it "retrieves accounts_summary_document" do
|
24
|
+
expect(@bank.accounts_summary_document).to be_kind_of Nokogiri::HTML::Document
|
25
|
+
end
|
26
|
+
|
27
|
+
it "has brokerage_table" do
|
28
|
+
expect(@bank.brokerage_data.size).to eq 2
|
29
|
+
end
|
30
|
+
|
31
|
+
it "gets expected accounts" do
|
32
|
+
expect(@bank.accounts.size).to eq accounts
|
33
|
+
end
|
34
|
+
|
35
|
+
it "extracts account names" do
|
36
|
+
expect(@bank.accounts.map(&:name)).to_not be_empty
|
37
|
+
end
|
38
|
+
|
39
|
+
it "extracts account numbers" do
|
40
|
+
expect(@bank.accounts.map(&:number).first).to start_with "513"
|
41
|
+
end
|
42
|
+
|
43
|
+
it "expects balances to be greater than zero" do
|
44
|
+
expect(@bank.accounts.map(&:balance).any?(&:zero?)).to eq false
|
45
|
+
end
|
46
|
+
|
47
|
+
it "expects availables to be greater than zero for bank accts" do
|
48
|
+
expect(@bank.accounts.map(&:available).any?(&:zero?)).to eq false
|
49
|
+
end
|
50
|
+
|
51
|
+
it "sets account types" do
|
52
|
+
expect(@bank.accounts.map(&:account_type).uniq).to eq account_types
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dinero
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Lang
|
@@ -169,6 +169,7 @@ files:
|
|
169
169
|
- Rakefile
|
170
170
|
- dinero.gemspec
|
171
171
|
- examples/get_balances.rb
|
172
|
+
- examples/scottrade.rb
|
172
173
|
- examples/sdccu.rb
|
173
174
|
- lib/dinero.rb
|
174
175
|
- lib/dinero/account.rb
|
@@ -176,6 +177,7 @@ files:
|
|
176
177
|
- lib/dinero/banks/capital_one.rb
|
177
178
|
- lib/dinero/banks/capital_one_360.rb
|
178
179
|
- lib/dinero/banks/georgias_own.rb
|
180
|
+
- lib/dinero/banks/scottrade.rb
|
179
181
|
- lib/dinero/banks/sdccu.rb
|
180
182
|
- lib/dinero/banks/south_state_bank.rb
|
181
183
|
- lib/dinero/version.rb
|
@@ -183,6 +185,7 @@ files:
|
|
183
185
|
- spec/banks/capital_one_360_spec.rb
|
184
186
|
- spec/banks/capital_one_spec.rb
|
185
187
|
- spec/banks/georgias_own_spec.rb
|
188
|
+
- spec/banks/scottrade_spec.rb
|
186
189
|
- spec/banks/sdccu_spec.rb
|
187
190
|
- spec/banks/south_state_bank_spec.rb
|
188
191
|
- spec/fixtures/vcr_cassettes/.keep
|
@@ -217,6 +220,7 @@ test_files:
|
|
217
220
|
- spec/banks/capital_one_360_spec.rb
|
218
221
|
- spec/banks/capital_one_spec.rb
|
219
222
|
- spec/banks/georgias_own_spec.rb
|
223
|
+
- spec/banks/scottrade_spec.rb
|
220
224
|
- spec/banks/sdccu_spec.rb
|
221
225
|
- spec/banks/south_state_bank_spec.rb
|
222
226
|
- spec/fixtures/vcr_cassettes/.keep
|