BillNye 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3de6dd9e9afa2ebc5f350f1a8329f7992a2ddf47
4
+ data.tar.gz: c104e7ba8656b3927ee5ec3c36a2f19f5edf4a67
5
+ SHA512:
6
+ metadata.gz: d999246d438adbac9831056adf0065e8eb9b1963132b06b5892640101f36ea2c1e4e7ca6b2565a260924cd08a2b4798232d4bb3d3fe70aab2cdf689d9e109d25
7
+ data.tar.gz: f0ab16c7bfe0d3d82743445c00040f85a9e1aef5b28742c6b188dc18160073b19a0f3b6e923da9d9f7d62d84712418cc56c2d8b1004efaf070ccfd77f2cf1ac2
@@ -0,0 +1,13 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ desc "Run specs"
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task default: :spec
8
+
9
+ desc "Use this to generate simplecov test coverage"
10
+ task :coverage do |t|
11
+ ENV["COVERAGE"] = 'true'
12
+ Rake::Task[:spec].execute
13
+ end
@@ -0,0 +1,143 @@
1
+ require_relative 'bill-nye/version'
2
+ require_relative 'bill-nye/bnlogger'
3
+ require_relative 'bill-nye/debit'
4
+ require_relative 'bill-nye/credit'
5
+ require 'date'
6
+ require 'csv'
7
+ require 'time'
8
+
9
+ module BillNye
10
+
11
+ class BillNye
12
+
13
+ def initialize()
14
+ @REGEX_PURCHASE = / *(?<process_date>[0-9]{2}\/[0-9]{2}) +(?<type>Card Purchase[a-zA-Z ]+)(?<usage_date>[0-9]{2}\/[0-9]{2}) (?<source>.+)(?<amount>[-,0-9]+.[0-9]{2}) +(?<balance>[-,0-9]+\.[0-9]{2})/
15
+ @REX_TRANSFER = / *(?<process_date>[0-9]{2}\/[0-9]{2}) +(?<type>[a-zA-Z .0-9#:]+) +(?<amount>[-,0-9,]+.[0-9]{2}) +(?<balance>[-,0-9,]+.[0-9]{2})/
16
+ @REX_PUR_RECUR = / *(?<process_date>[0-9]{2}\/[0-9]{2}) +(?<type>Recurring Card Purchase) (?<usage_date>[0-9]{2}\/[0-9]{2}) (?<source>.+) *(?<amount>[-,0-9]+.[0-9]{2}) +(?<balance>[-,0-9]+\.[0-9]{2})/
17
+ @REX_PUR_RETURN = / *(?<process_date>[0-9]{2}\/[0-9]{2}) +(?<type>Purchase Return) +(?<usage_date>[0-9]{2}\/[0-9]{2}) (?<source>.+) (?<amount>[-,0-9]*.[0-9]{2}) +(?<balance>[-,0-9]+\.[0-9]{2})/
18
+ @REX_ATM_WITH = / *(?<process_date>[0-9]{2}\/[0-9]{2}) +(?<type>Non-Chase ATM Withdraw) +(?<usage_date>[0-9]{2}\/[0-9]{2}) (?<source>.+) (?<amount>[-,0-9]+.[0-9]{2}) +(?<balance>[-,0-9]+.[0-9]{2})/
19
+ @REX_ATM_FEE = / *(?<process_date>[0-9]{2}\/[0-9]{2}) +(?<type>.*Fee.*) +(?<amount>[-,0-9]*.[0-9]{2}) +(?<balance>[-,0-9,]*.[0-9]{2})/
20
+ @REX_CREDIT = / *(?<process_date>[0-9]{2}\/[0-9]{2}) + (?<source>.+ )(?<amount>[-,0-9]+.[0-9]{2})/
21
+ @REX_SAVINGS = / +SAVINGS SUMMARY/
22
+
23
+ @log = BNLogger.log
24
+ end
25
+
26
+ def parse_pdfs(dir, type)
27
+ _xaction_list = []
28
+ Dir.foreach(dir) do |pdf|
29
+ begin
30
+ _xactions = parse_pdf("#{dir}#{pdf}", type)
31
+ _xaction_list << _xactions
32
+ rescue
33
+ p "Failed to convert #{pdf} to text."
34
+ end
35
+ end
36
+ return _xaction_list
37
+ end
38
+
39
+ def parse_pdf(pdf, type)
40
+ _xactions = []
41
+ begin
42
+ `pdftotext -layout #{pdf}`
43
+ _match = /(?<filename>.+).pdf/.match(pdf)
44
+ txt = "#{_match[:filename]}.txt"
45
+ rescue => e
46
+ p "Error #{e}: Failed to convert #{pdf} to text."
47
+ end
48
+
49
+ File.open("#{txt}", "r") do |file_handle|
50
+ file_handle.each_line do |line|
51
+ case type
52
+ when 1
53
+ _debit = parse_debit(line)
54
+ when 2
55
+ _debit = parse_credit
56
+ end
57
+
58
+ if !_debit.nil?
59
+ _xactions << _debit
60
+ end
61
+ end
62
+ end
63
+
64
+ return _xactions
65
+ end
66
+
67
+ def parse_credit(line)
68
+ match = @REX_CREDIT.match(line)
69
+ processDate = match[:process_date].strip
70
+ type = "Credit"
71
+ source = match[:source].strip
72
+ amount = match[:amount].strip
73
+ return Credit.new(processDate, type, source, amount)
74
+ end
75
+
76
+ def parse_debit(line)
77
+ _debit = nil
78
+ begin
79
+ if !@REGEX_PURCHASE.match(line).nil?
80
+ _match = @REGEX_PURCHASE.match(line)
81
+ _debit = parse_default(_match)
82
+ @log.info{ "Match PURCHASE: #{_debit}" }
83
+ elsif !@REX_PUR_RECUR.match(line).nil?
84
+ _match = @REX_PUR_RECUR.match(line)
85
+ _debit = parse_default(_match)
86
+ @log.info{ "Match PURCHASE RECURRING: #{_debit}" }
87
+ elsif !@REX_PUR_RETURN.match(line).nil?
88
+ _match = @REX_PUR_RETURN.match(line)
89
+ _debit = parse_default(_match)
90
+ @log.info{ "Match PURCHASE RETURN: #{_debit}" }
91
+ elsif !@REX_ATM_WITH.match(line).nil?
92
+ _match = @REX_ATM_WITH.match(line)
93
+ _debit = parse_atm_with(_match)
94
+ @log.info{ "Match ATM WITH: #{_debit}" }
95
+ elsif !@REX_ATM_FEE.match(line).nil?
96
+ _match = @REX_ATM_FEE.match(line)
97
+ _debit = parse_transfer_or_fee(_match)
98
+ @log.info{ "ATM FEE: #{_debit}" }
99
+ elsif !@REX_TRANSFER.match(line).nil?
100
+ _match = @REX_TRANSFER.match(line)
101
+ _debit = parse_transfer_or_fee(_match)
102
+ @log.info{ "Match TRANSFER: #{_debit}" }
103
+ else
104
+ @log.error{ "NO-MATCH on: #{_debit}" }
105
+ end
106
+ rescue => e
107
+ @log.error{"Error #{e} on: #{_debit}"}
108
+ end
109
+ return _debit
110
+ end
111
+
112
+ def parse_default(match)
113
+ processDate = match[:process_date].strip
114
+ source = match[:source].strip
115
+ amount = match[:amount].strip
116
+ type = match[:type].strip
117
+ usageDate = match[:usage_date].strip
118
+ balance = match[:balance].strip
119
+ return Debit.new(processDate, type, usageDate, source, amount, balance)
120
+ end
121
+
122
+ def parse_transfer_or_fee(match)
123
+ processDate = match[:process_date].strip
124
+ type = match[:type].strip
125
+ usageDate = processDate
126
+ source = ""
127
+ amount = match[:amount].strip
128
+ balance = match[:balance].strip
129
+ return Debit.new(processDate, type, usageDate, source, amount, balance)
130
+ end
131
+
132
+ def parse_atm_with(match)
133
+ processDate = match[:process_date].strip
134
+ source = match[:type].strip
135
+ amount = match[:amount].strip
136
+ type = match[:type].strip
137
+ usageDate = processDate
138
+ balance = match[:balance].strip
139
+ return Debit.new(processDate, type, usageDate, source, amount, balance)
140
+ end
141
+
142
+ end #class
143
+ end #module
@@ -0,0 +1,26 @@
1
+ require 'logger'
2
+
3
+ module BillNye
4
+ class BNLogger
5
+ def self.configure()
6
+ #log_file = config["logging"]["file"] unless config["logging"]["file"].nil?
7
+ #log_level = config["logging"]["level"] unless config["logging"]["level"].nil?
8
+ #log_level = config["logging"]["rotation"] unless config["logging"]["rotation"].nil?
9
+
10
+ log_file ||= "log.txt"#STDOUT
11
+ log_level ||= 'info'
12
+ log_rotation ||= 'daily'
13
+
14
+ @logger = Logger.new(log_file, log_rotation)
15
+ @logger.level = Logger.const_get(log_level.upcase.to_sym)
16
+ @logger.formatter = proc do |severity, datetime, progname, msg|
17
+ "#{datetime}: [#{severity}] : #{msg}\n"
18
+ end
19
+ end
20
+
21
+ def self.log
22
+ return @logger
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,11 @@
1
+
2
+
3
+ class Credit
4
+ def initialize(_pDate, _type, _source, _amount)
5
+ @pDate = _pDate
6
+ @type = _type
7
+ @uDate = _uDate
8
+ @source = _source
9
+ @amount = _amount
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+
2
+
3
+ class Debit
4
+ def initialize(_pDate, _type, _uDate, _source, _amount, _balance)
5
+ @pDate = _pDate
6
+ @type = _type
7
+ @uDate = _uDate
8
+ @source = _source
9
+ @amount = _amount
10
+ @balance = _balance
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module BillNye
2
+ VERSION = '0.0.1'
3
+ end
metadata ADDED
@@ -0,0 +1,50 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: BillNye
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Keenin Vye
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-07-20 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: This library facilitates in the parsing of Chase bank statements.
14
+ email:
15
+ - KeeninVye@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - Rakefile
21
+ - lib/bill-nye.rb
22
+ - lib/bill-nye/bnlogger.rb
23
+ - lib/bill-nye/credit.rb
24
+ - lib/bill-nye/debit.rb
25
+ - lib/bill-nye/version.rb
26
+ homepage: https://github.com/KeeninVye/BillNye
27
+ licenses:
28
+ - MIT
29
+ metadata: {}
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ required_rubygems_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ requirements: []
45
+ rubyforge_project:
46
+ rubygems_version: 2.6.12
47
+ signing_key:
48
+ specification_version: 4
49
+ summary: Just what the description says.
50
+ test_files: []