funds 0.0.1 → 0.0.2
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/lib/Account.rb +7 -2
- data/lib/AccountType.rb +8 -0
- data/lib/FinancialInstitution.rb +2 -0
- data/lib/Global.rb +5 -0
- data/lib/Holding.rb +1 -1
- data/lib/OFXClient.rb +116 -44
- data/lib/Statement.rb +10 -0
- metadata +6 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 0db9c72387ade29fb2ef3dedab5dc4469e2a8ff6
         | 
| 4 | 
            +
              data.tar.gz: ced4164d106752494680015d8e1c808dd1cacb54
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 5fe11328dfad265a80c9e3fef9320648a0982aa31f1a0cd240a72739d644e947b1f7cbc8b201d93a5a7422982f90660238b44be94bcff9675b27bd84741c6eb4
         | 
| 7 | 
            +
              data.tar.gz: 579c54df22d5cb27c2e845af56d7344ae76673338152f87334ba6e0ec039926ba56d977e1761536bbe8497199271984eadc18c432781ea41fa6d34bbaa7c9263
         | 
    
        data/lib/Account.rb
    CHANGED
    
    | @@ -1,10 +1,15 @@ | |
| 1 1 | 
             
            class Account
         | 
| 2 2 |  | 
| 3 3 | 
             
                attr_accessor :holdings
         | 
| 4 | 
            -
                attr_accessor : | 
| 4 | 
            +
                attr_accessor :accountNumber
         | 
| 5 | 
            +
                attr_accessor :type
         | 
| 6 | 
            +
                attr_accessor :routingNumber
         | 
| 5 7 |  | 
| 6 | 
            -
                def initialize( | 
| 8 | 
            +
                def initialize(accountNumber, type)
         | 
| 9 | 
            +
                    @accountNumber = accountNumber
         | 
| 10 | 
            +
                    @type = type
         | 
| 7 11 | 
             
                    @holdings = Array.new
         | 
| 12 | 
            +
                    @routing = -1
         | 
| 8 13 | 
             
                end
         | 
| 9 14 |  | 
| 10 15 | 
             
            end
         | 
    
        data/lib/AccountType.rb
    ADDED
    
    
    
        data/lib/FinancialInstitution.rb
    CHANGED
    
    
    
        data/lib/Holding.rb
    CHANGED
    
    
    
        data/lib/OFXClient.rb
    CHANGED
    
    | @@ -1,55 +1,65 @@ | |
| 1 1 | 
             
            require "./FinancialInstitution.rb"
         | 
| 2 | 
            +
            require "./Account.rb"
         | 
| 3 | 
            +
            require "./AccountType.rb"
         | 
| 4 | 
            +
            require "./Global.rb"
         | 
| 2 5 | 
             
            require "rubygems"
         | 
| 3 6 | 
             
            require "httpclient"
         | 
| 4 7 | 
             
            require "nokogiri"
         | 
| 5 8 |  | 
| 6 9 | 
             
            class OFXClient
         | 
| 7 10 |  | 
| 8 | 
            -
                def self. | 
| 11 | 
            +
                def self.get_statement(fi, account, username, password, startDate, endDate)
         | 
| 9 12 |  | 
| 10 | 
            -
                     | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
                         | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
                         | 
| 27 | 
            -
                         | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
                         | 
| 32 | 
            -
             | 
| 13 | 
            +
                    if(account.type.eql?(AccountType::CHECKING) || account.type.eql?(AccountType::SAVINGS))
         | 
| 14 | 
            +
                        ofx = OFXClient::create_headers() + 
         | 
| 15 | 
            +
                        '<OFX>' +
         | 
| 16 | 
            +
                        create_signon(fi, username, password) +
         | 
| 17 | 
            +
                        '<BANKMSGSRQV1>' +
         | 
| 18 | 
            +
                        '<STMTTRNRQ>' +
         | 
| 19 | 
            +
                        '<TRNUID>' + OFXClient::generate_uuid(32) +
         | 
| 20 | 
            +
                        '<CLTCOOKIE>' + OFXClient::generate_uuid(5) +
         | 
| 21 | 
            +
                        '<STMTRQ>' +
         | 
| 22 | 
            +
                        '<BANKACCTFROM>' +
         | 
| 23 | 
            +
                        '<BANKID>' + account.routingNumber +
         | 
| 24 | 
            +
                        '<ACCTID>' + account.accountNumber +
         | 
| 25 | 
            +
                        '<ACCTTYPE>' + account.type +
         | 
| 26 | 
            +
                        '</BANKACCTFROM>' +
         | 
| 27 | 
            +
                        '<INCTRAN>' +
         | 
| 28 | 
            +
                        '<DTSTART>' + startDate +
         | 
| 29 | 
            +
                        '<DTEND>' + endDate +
         | 
| 30 | 
            +
                        '<INCLUDE>Y</INCTRAN>' +
         | 
| 31 | 
            +
                        '</STMTRQ>' +
         | 
| 32 | 
            +
                        '</STMTTRNRQ>' +
         | 
| 33 | 
            +
                        '</BANKMSGSRQV1>' +
         | 
| 34 | 
            +
                        '</OFX>';
         | 
| 35 | 
            +
                        
         | 
| 36 | 
            +
                        OFXClient::post_ofx(fi.url, ofx);
         | 
| 33 37 | 
             
                    end
         | 
| 34 38 |  | 
| 35 | 
            -
                     | 
| 36 | 
            -
                    # nokogiri's builder cannot do this
         | 
| 37 | 
            -
                    ofxDeclaration = "\n<?OFX OFXHEADER=\"200\" VERSION=\"211\" SECURITY=\"NONE\" OLDFILEUID=\"NONE\" NEWFILEUID=\"NONE\"?>"
         | 
| 38 | 
            -
                    xml = builder.to_xml.insert(21, ofxDeclaration)
         | 
| 39 | 
            -
                    #puts xml
         | 
| 39 | 
            +
                    if(account.type.eql?(AccountType::CREDITCARD))
         | 
| 40 40 |  | 
| 41 | 
            +
                        ofx = OFXClient::create_headers() + 
         | 
| 42 | 
            +
                        '<OFX>' +
         | 
| 43 | 
            +
                        create_signon(fi, username, password) +
         | 
| 44 | 
            +
                        '<CREDITCARDMSGSRQV1>' +
         | 
| 45 | 
            +
                        '<CCSTMTTRNRQ>' +
         | 
| 46 | 
            +
                        '<TRNUID>' + OFXClient::generate_uuid(32) +
         | 
| 47 | 
            +
                        '<CLTCOOKIE>' + OFXClient::generate_uuid(5) +
         | 
| 48 | 
            +
                        '<CCSTMTRQ>' +
         | 
| 49 | 
            +
                        '<CCACCTFROM>' +
         | 
| 50 | 
            +
                        '<ACCTID>' + account.accountNumber  +
         | 
| 51 | 
            +
                        '</CCACCTFROM>' +
         | 
| 52 | 
            +
                        '<INCTRAN>' +
         | 
| 53 | 
            +
                        '<DTSTART>' + startDate +
         | 
| 54 | 
            +
                        '<INCLUDE>Y</INCTRAN>' +
         | 
| 55 | 
            +
                        '</CCSTMTRQ>' +
         | 
| 56 | 
            +
                        '</CCSTMTTRNRQ>' +
         | 
| 57 | 
            +
                        '</CREDITCARDMSGSRQV1>' +
         | 
| 58 | 
            +
                        '</OFX>';
         | 
| 59 | 
            +
                        
         | 
| 60 | 
            +
                        OFXClient::post_ofx(fi.url, ofx);
         | 
| 41 61 |  | 
| 42 | 
            -
                     | 
| 43 | 
            -
                    
         | 
| 44 | 
            -
                    #required headers
         | 
| 45 | 
            -
                    extheader = [['Content-Type', 'application/x-ofx']]
         | 
| 46 | 
            -
                    extheader.push(['Content-Length', xml.bytesize.to_s])
         | 
| 47 | 
            -
                    
         | 
| 48 | 
            -
             | 
| 49 | 
            -
                    
         | 
| 50 | 
            -
                end
         | 
| 51 | 
            -
                
         | 
| 52 | 
            -
                def self.investment_holdings(fi, username, password, accountNumber)
         | 
| 62 | 
            +
                    end
         | 
| 53 63 |  | 
| 54 64 | 
             
                end
         | 
| 55 65 |  | 
| @@ -70,15 +80,16 @@ class OFXClient | |
| 70 80 | 
             
                    return OFXClient::doc_to_hash(doc)
         | 
| 71 81 | 
             
                end
         | 
| 72 82 |  | 
| 73 | 
            -
                def self.get_institution( | 
| 83 | 
            +
                def self.get_institution(iid)
         | 
| 74 84 | 
             
                    httpClient = HTTPClient.new
         | 
| 75 | 
            -
                    res = httpClient.get_content("http://www.ofxhome.com/api.php?lookup=" +  | 
| 85 | 
            +
                    res = httpClient.get_content("http://www.ofxhome.com/api.php?lookup=" + iid.to_s)
         | 
| 76 86 | 
             
                    doc = Nokogiri::XML(res)
         | 
| 77 87 |  | 
| 78 88 | 
             
                    institutionElements = doc.xpath("//institution")
         | 
| 79 89 |  | 
| 80 90 | 
             
                    if(institutionElements.length == 1)
         | 
| 81 | 
            -
                       if(institutionElements.first["id"].eql?  | 
| 91 | 
            +
                       if(institutionElements.first["id"].eql? iid.to_s)
         | 
| 92 | 
            +
                            fid = doc.xpath("//institution//fid").first.content.to_i
         | 
| 82 93 | 
             
                            name = doc.xpath("//institution//name").first.content
         | 
| 83 94 | 
             
                            org = doc.xpath("//institution//org").first.content
         | 
| 84 95 | 
             
                            url = doc.xpath("//institution//url").first.content
         | 
| @@ -96,8 +107,37 @@ class OFXClient | |
| 96 107 | 
             
                    end
         | 
| 97 108 | 
             
                end
         | 
| 98 109 |  | 
| 110 | 
            +
                def self.post_ofx(url, ofxBody)
         | 
| 111 | 
            +
                
         | 
| 112 | 
            +
                    httpClient = HTTPClient.new
         | 
| 113 | 
            +
                    #required headers
         | 
| 114 | 
            +
                    extheader = [['Content-Type', 'application/x-ofx']]
         | 
| 115 | 
            +
                    extheader = [['User-Agent', 'funds']]
         | 
| 116 | 
            +
                    #extheader.push(['Content-Length', ofxBody.bytesize.to_s])
         | 
| 117 | 
            +
                    extheader.push(['Accept', 'application/ofx'])
         | 
| 118 | 
            +
                    
         | 
| 119 | 
            +
                    res = httpClient.post(url, ofxBody, extheader, nil)
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                    return res.body
         | 
| 122 | 
            +
                    
         | 
| 123 | 
            +
                end
         | 
| 124 | 
            +
             | 
| 99 125 | 
             
                private
         | 
| 100 126 |  | 
| 127 | 
            +
                def self.generate_uuid(length)
         | 
| 128 | 
            +
                
         | 
| 129 | 
            +
                    chars = ("0".."9").to_a.concat(("A".."Z").to_a.concat(("a".."z").to_a))
         | 
| 130 | 
            +
                    radix = chars.length      
         | 
| 131 | 
            +
                    uuid = Array.new
         | 
| 132 | 
            +
                    
         | 
| 133 | 
            +
                    (0...length).each do |i|
         | 
| 134 | 
            +
                        uuid.push(chars[rand(chars.length)])
         | 
| 135 | 
            +
                    end
         | 
| 136 | 
            +
                    
         | 
| 137 | 
            +
                    return uuid.join
         | 
| 138 | 
            +
                    
         | 
| 139 | 
            +
                end
         | 
| 140 | 
            +
                
         | 
| 101 141 | 
             
                def self.doc_to_hash(doc)
         | 
| 102 142 | 
             
                    hash = Hash.new
         | 
| 103 143 | 
             
                    doc.xpath("//institutionid").each do |node|
         | 
| @@ -105,6 +145,38 @@ class OFXClient | |
| 105 145 | 
             
                    end
         | 
| 106 146 | 
             
                    return hash
         | 
| 107 147 | 
             
                end
         | 
| 108 | 
            -
             | 
| 148 | 
            +
                
         | 
| 149 | 
            +
                def self.create_headers
         | 
| 150 | 
            +
                     
         | 
| 151 | 
            +
                     return 'OFXHEADER:100\r\n' +
         | 
| 152 | 
            +
                     'DATA:OFXSGML\r\n' +
         | 
| 153 | 
            +
                     'VERSION:'+ '102' +'\r\n' +
         | 
| 154 | 
            +
                     'SECURITY:NONE\r\n' +
         | 
| 155 | 
            +
                     'ENCODING:USASCII\r\n' +
         | 
| 156 | 
            +
                     'CHARSET:1252\r\n' +
         | 
| 157 | 
            +
                     'COMPRESSION:NONE\r\n' +
         | 
| 158 | 
            +
                     'OLDFILEUID:NONE\r\n' +
         | 
| 159 | 
            +
                     'NEWFILEUID:' + OFXClient::generate_uuid(32) + '\r\n' +
         | 
| 160 | 
            +
                     '\r\n'
         | 
| 161 | 
            +
                end
         | 
| 162 | 
            +
                
         | 
| 163 | 
            +
                def self.create_signon(fi, username, password)
         | 
| 164 | 
            +
                
         | 
| 165 | 
            +
                    return '<SIGNONMSGSRQV1>' +
         | 
| 166 | 
            +
                    '<SONRQ>' +
         | 
| 167 | 
            +
                    '<DTCLIENT>' + Time.new.strftime("%Y%m%d%H%M%S") +
         | 
| 168 | 
            +
                    '<USERID>' + username +
         | 
| 169 | 
            +
                    '<USERPASS>' + password +
         | 
| 170 | 
            +
                    '<LANGUAGE>ENG' +
         | 
| 171 | 
            +
                    '<FI>' +
         | 
| 172 | 
            +
                    '<ORG>' + fi.org +
         | 
| 173 | 
            +
                    '<FID>' + fi.fid.to_s +
         | 
| 174 | 
            +
                    '</FI>' +
         | 
| 175 | 
            +
                    '<APPID>' + "funds" +
         | 
| 176 | 
            +
                    '<APPVER>' + Global::VERSION +
         | 
| 177 | 
            +
                    '</SONRQ>' +
         | 
| 178 | 
            +
                    '</SIGNONMSGSRQV1>'
         | 
| 179 | 
            +
                  
         | 
| 180 | 
            +
                end
         | 
| 109 181 |  | 
| 110 182 | 
             
            end
         | 
    
        data/lib/Statement.rb
    ADDED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: funds
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.0. | 
| 4 | 
            +
              version: 0.0.2
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Justin Forsyth
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2016-02- | 
| 11 | 
            +
            date: 2016-02-17 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: nokogiri
         | 
| @@ -45,10 +45,13 @@ extensions: [] | |
| 45 45 | 
             
            extra_rdoc_files: []
         | 
| 46 46 | 
             
            files:
         | 
| 47 47 | 
             
            - lib/Account.rb
         | 
| 48 | 
            +
            - lib/AccountType.rb
         | 
| 48 49 | 
             
            - lib/FinancialInstitution.rb
         | 
| 50 | 
            +
            - lib/Global.rb
         | 
| 49 51 | 
             
            - lib/Holding.rb
         | 
| 50 52 | 
             
            - lib/OFXClient.rb
         | 
| 51 | 
            -
             | 
| 53 | 
            +
            - lib/Statement.rb
         | 
| 54 | 
            +
            homepage: https://github.com/jf-rce/funds
         | 
| 52 55 | 
             
            licenses:
         | 
| 53 56 | 
             
            - MIT
         | 
| 54 57 | 
             
            metadata: {}
         |