BillNye 0.0.1
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 +7 -0
- data/Rakefile +13 -0
- data/lib/bill-nye.rb +143 -0
- data/lib/bill-nye/bnlogger.rb +26 -0
- data/lib/bill-nye/credit.rb +11 -0
- data/lib/bill-nye/debit.rb +12 -0
- data/lib/bill-nye/version.rb +3 -0
- metadata +50 -0
checksums.yaml
ADDED
|
@@ -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
|
data/Rakefile
ADDED
|
@@ -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
|
data/lib/bill-nye.rb
ADDED
|
@@ -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
|
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: []
|