banco 1.0.0
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/LICENSE +19 -0
- data/README +12 -0
- data/bin/banco +51 -0
- data/lib/banco/get_file.rb +40 -0
- data/lib/banco/reader.rb +65 -0
- data/lib/banco/reporter.rb +70 -0
- data/lib/banco/transaction.rb +31 -0
- data/lib/banco/viewable.rb +180 -0
- data/spec/banco/reader_spec.rb +14 -0
- data/spec/banco/reporter_spec.rb +54 -0
- data/spec/banco/transaction_spec.rb +47 -0
- metadata +81 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 46ea6fd6061ec915ad68f9f440e8f8ebde2e68f8
|
|
4
|
+
data.tar.gz: 8e547c123763df3b53cf35ed8b79fcddce711072
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 9ac616b841ca909252d1e5716450185dd057f5de1c8f28caa6dcdef98982d81a7d596639fbd9d53e67ceffb77ea2863cb9a04f8cf2d44bc49d180a6c2b1c2244
|
|
7
|
+
data.tar.gz: ccc7d6ceebfb4434c8b04da880e823e0ad9ea13239bd802aebca8dbc9c6fa41cb9849cc47ca24218500b697f88abbd60a6dcf154930899229070a3f007fdf23c
|
data/LICENSE
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Copyright (c) 2017 Ian Marley
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
in the Software without restriction, including without limitation the rights
|
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
|
+
SOFTWARE.
|
data/README
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Welcome to Banco !
|
|
2
|
+
|
|
3
|
+
Banco has been developed to summarize statements downloaded from your bank.
|
|
4
|
+
Install as a Rubygem, navigate to the directory your .csv files are in and execute from the command line with 'banco'.
|
|
5
|
+
|
|
6
|
+
Banco will only accept comma seperated value files (.csv) and will produce a summary for the period uploaded from the file.
|
|
7
|
+
|
|
8
|
+
Remove the header line from your downloaded bank statement and Banco will total the incoming & outgoing transactions for the period. Reporting the bottom line aswell as summing up the values for similar transactions. This is achieved by matching the description name, currently set at the first 9 characters of the string, you can change this to be more or less exact.
|
|
9
|
+
|
|
10
|
+
Hope your numbers are positive !
|
|
11
|
+
code@s33d.co
|
|
12
|
+
https://github.com/s33dco/banco
|
data/bin/banco
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require_relative '../lib/banco/viewable'
|
|
4
|
+
require_relative '../lib/banco/get_file'
|
|
5
|
+
require_relative '../lib/banco/reader'
|
|
6
|
+
require_relative '../lib/banco/reporter'
|
|
7
|
+
|
|
8
|
+
module Banco
|
|
9
|
+
def self.starter
|
|
10
|
+
Viewable::prompt
|
|
11
|
+
file = GetFile.new
|
|
12
|
+
file.make_name
|
|
13
|
+
reader = file.name
|
|
14
|
+
reader = Reader.new(file.csv_file_name, file.summary_name)
|
|
15
|
+
reader.read_in_csv_data
|
|
16
|
+
report = reader.report_name
|
|
17
|
+
report = Reporter.new(reader.csv_file_name, reader.report_name, reader.all_from_csv)
|
|
18
|
+
end
|
|
19
|
+
Viewable::hello
|
|
20
|
+
report = starter
|
|
21
|
+
loop do
|
|
22
|
+
report.menu
|
|
23
|
+
answer = gets.chomp.downcase
|
|
24
|
+
case answer
|
|
25
|
+
when 'a'
|
|
26
|
+
print report.transactions_all
|
|
27
|
+
when 'o'
|
|
28
|
+
print report.transactions_out
|
|
29
|
+
when "i"
|
|
30
|
+
print report.transactions_in
|
|
31
|
+
when "m"
|
|
32
|
+
print report.money_out_summary
|
|
33
|
+
when "n"
|
|
34
|
+
print report.money_in_summary
|
|
35
|
+
when "b"
|
|
36
|
+
print report.bottom_line
|
|
37
|
+
when "l"
|
|
38
|
+
report = starter
|
|
39
|
+
when "s"
|
|
40
|
+
report.save_summary_to_file
|
|
41
|
+
when "t"
|
|
42
|
+
report.save_transactions_to_file
|
|
43
|
+
when "q"
|
|
44
|
+
break
|
|
45
|
+
else
|
|
46
|
+
report.menu
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
Viewable::farewell
|
|
50
|
+
end
|
|
51
|
+
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module Banco
|
|
2
|
+
class GetFile
|
|
3
|
+
attr_reader :name, :csv_file_name, :summary_name
|
|
4
|
+
|
|
5
|
+
def make_name
|
|
6
|
+
@csv_file_name = gets.chomp.downcase
|
|
7
|
+
if @csv_file_name == 'q'
|
|
8
|
+
Viewable::farewell
|
|
9
|
+
exit
|
|
10
|
+
else
|
|
11
|
+
file_checker_cleaner(@csv_file_name)
|
|
12
|
+
@name = @csv_file_name.split('.').first
|
|
13
|
+
@doctype = @csv_file_name.split('.').last
|
|
14
|
+
@summary_name = @name
|
|
15
|
+
@csv_file_name
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def file_checker_cleaner(filename)
|
|
20
|
+
if filename =~/([^\s]+(\.csv)$)/
|
|
21
|
+
puts "\nloading #{filename}..."
|
|
22
|
+
else
|
|
23
|
+
puts "#{filename} won't work !".center(54)
|
|
24
|
+
puts "try again or 'q' to exit".center(54)
|
|
25
|
+
make_name
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
if __FILE__ == $0
|
|
32
|
+
file = Banco::GetFile.new()
|
|
33
|
+
file.make_name
|
|
34
|
+
puts "\n\n\n"
|
|
35
|
+
p file.valid_file
|
|
36
|
+
p file.name
|
|
37
|
+
p file.summary_name
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
|
data/lib/banco/reader.rb
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require_relative 'transaction'
|
|
2
|
+
require_relative 'viewable'
|
|
3
|
+
|
|
4
|
+
require 'csv'
|
|
5
|
+
|
|
6
|
+
module Banco
|
|
7
|
+
class Reader
|
|
8
|
+
include Viewable
|
|
9
|
+
|
|
10
|
+
attr_reader :all_from_csv, :report_name, :csv_file_name
|
|
11
|
+
|
|
12
|
+
def initialize(csv_file_name, report_name)
|
|
13
|
+
@csv_file_name = csv_file_name
|
|
14
|
+
@report_name = report_name
|
|
15
|
+
@all_from_csv = []
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def read_in_csv_data
|
|
19
|
+
begin
|
|
20
|
+
@csv_row_count = 1
|
|
21
|
+
CSV.foreach(@csv_file_name) do |row|
|
|
22
|
+
@all_from_csv << Transaction.new(row[0],row[1],row[2],row[3],row[4],@csv_row_count)
|
|
23
|
+
@csv_row_count += 1
|
|
24
|
+
end
|
|
25
|
+
rescue ArgumentError => e
|
|
26
|
+
non_numeric_in_csv(e, @csv_row_count)
|
|
27
|
+
puts "sorted ? ('y' to continue or 'q' to exit)".rjust(54)
|
|
28
|
+
input = gets.chomp.downcase
|
|
29
|
+
@all_from_csv = []
|
|
30
|
+
input == "y" ? retry : Viewable::farewell
|
|
31
|
+
rescue Errno::ENOENT => e
|
|
32
|
+
puts "Can't find file #{@csv_file_name} - have another go or (q) quit\n\n"
|
|
33
|
+
loop do
|
|
34
|
+
input = gets.chomp.downcase
|
|
35
|
+
case input
|
|
36
|
+
when 'q'
|
|
37
|
+
Viewable::farewell
|
|
38
|
+
exit
|
|
39
|
+
when /([^\s]+(\.csv)$)/
|
|
40
|
+
@csv_file_name = input
|
|
41
|
+
break
|
|
42
|
+
else
|
|
43
|
+
puts "\ninvalid file - try again or 'q' to quit\n\n"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
retry
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def non_numeric_in_csv(exception, row_number)
|
|
51
|
+
reason = exception.message.split(':')
|
|
52
|
+
puts "Please check row #{row_number} of #{@csv_file_name},"
|
|
53
|
+
puts "#{reason.last} should be a numeric value".rjust(54)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
if __FILE__ == $0
|
|
59
|
+
reader = Banco::Reader.new("test.csv", "test")
|
|
60
|
+
reader.read_in_csv_data
|
|
61
|
+
puts reader.report_name
|
|
62
|
+
puts reader.csv_file_name
|
|
63
|
+
puts reader.all_from_csv
|
|
64
|
+
p reader
|
|
65
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
require_relative 'transaction'
|
|
2
|
+
require_relative 'reader'
|
|
3
|
+
require_relative 'viewable'
|
|
4
|
+
require 'csv'
|
|
5
|
+
|
|
6
|
+
module Banco
|
|
7
|
+
class Reporter
|
|
8
|
+
|
|
9
|
+
include Viewable
|
|
10
|
+
|
|
11
|
+
attr_reader :all_transactions, :outgoing_trans, :incoming_trans,
|
|
12
|
+
:outgoings, :incomings, :outgoing_total, :incoming_total,
|
|
13
|
+
:name, :csv_file_name
|
|
14
|
+
|
|
15
|
+
def initialize(csv_file_name, report_name, transactions)
|
|
16
|
+
@csv_file_name = csv_file_name
|
|
17
|
+
@name = report_name
|
|
18
|
+
@all_transactions = transactions
|
|
19
|
+
@outgoing_trans = []
|
|
20
|
+
@incoming_trans = []
|
|
21
|
+
@outgoings = Hash.new(0)
|
|
22
|
+
@incomings = Hash.new(0)
|
|
23
|
+
puts "formating data..."
|
|
24
|
+
remove_blank_lines
|
|
25
|
+
split_in_out
|
|
26
|
+
total_outgoing
|
|
27
|
+
total_incoming
|
|
28
|
+
puts "\n\n"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def remove_blank_lines
|
|
33
|
+
@all_transactions.delete_if{|trans| trans.moneyin == 0 && trans.moneyout == 0}
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def split_in_out
|
|
37
|
+
@outgoing_trans, @incoming_trans = @all_transactions.partition{|trans| trans.moneyin == 0 && trans.moneyout > 0}
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def total_outgoing
|
|
41
|
+
@outgoing_trans.each{|trans| @outgoings[trans.description[0..8]] += trans.moneyout}
|
|
42
|
+
@outgoing_total = @outgoings.values.map.reduce(:+)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def total_incoming
|
|
46
|
+
@incoming_trans.each{|trans| @incomings[trans.description[0..8]] += trans.moneyin}
|
|
47
|
+
@incoming_total = @incomings.values.map.reduce(:+)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
if __FILE__ == $0
|
|
54
|
+
reader = Banco::Reader.new("test.csv", "test")
|
|
55
|
+
reader.read_in_csv_data
|
|
56
|
+
puts "\n\n\n#all csv data from reader object\n\n"
|
|
57
|
+
puts "#{reader.all_from_csv}\n\n"
|
|
58
|
+
report = Banco::Reporter.new(reader.csv_file_name, reader.report_name, reader.all_from_csv)
|
|
59
|
+
puts "#{report.name} is the Reporter object's name\nReporter object contents below, (3 arrays, 2 hashes):\n\n"
|
|
60
|
+
puts "\n\nall transactions array\n"
|
|
61
|
+
p report.all_transactions
|
|
62
|
+
puts "\n\noutgoings array\n"
|
|
63
|
+
p report.outgoing_trans
|
|
64
|
+
puts "\n\nincomings array\n"
|
|
65
|
+
p report.incoming_trans
|
|
66
|
+
puts "\n\nOutgoings hash\n"
|
|
67
|
+
p report.outgoings
|
|
68
|
+
puts "\n\nIncomings hash\n"
|
|
69
|
+
p report.incomings
|
|
70
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Banco
|
|
2
|
+
class Transaction
|
|
3
|
+
require 'bigdecimal'
|
|
4
|
+
attr_reader :date, :description, :type, :moneyin, :moneyout, :csv_row_count
|
|
5
|
+
|
|
6
|
+
def initialize(date_string, description, type, moneyin, moneyout, csv_row_count)
|
|
7
|
+
@csv_row_count = csv_row_count
|
|
8
|
+
@moneyin = convert(moneyin)
|
|
9
|
+
@moneyout = convert(moneyout)
|
|
10
|
+
@date = date_string
|
|
11
|
+
@description = '%-22.22s' % "#{description.upcase}"
|
|
12
|
+
@type = '%-8.8s' % "#{type.upcase}"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def convert(money)
|
|
16
|
+
money.nil? ? money = BigDecimal('0') : money = BigDecimal(money)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def to_s
|
|
20
|
+
"#{date} #{type} #{description}"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
if __FILE__ == $0
|
|
26
|
+
trans = Banco::Transaction.new("01/01/17", "Supermarket","Purchase", "72.90", "0","1")
|
|
27
|
+
p trans
|
|
28
|
+
t = Banco::Transaction.new
|
|
29
|
+
t.send(:initialize, "02/02/18", "new way", "credit", "0", '111.11','2')
|
|
30
|
+
p t
|
|
31
|
+
end
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
module Banco
|
|
2
|
+
module Viewable
|
|
3
|
+
def menu
|
|
4
|
+
puts "Enter :\n"
|
|
5
|
+
puts "'a' to view all transactions"
|
|
6
|
+
puts "'o' to view all outgoing transactions"
|
|
7
|
+
puts "'i' to view all incoming transactions"
|
|
8
|
+
puts "'m' for money out summary"
|
|
9
|
+
puts "'n' for money in summary"
|
|
10
|
+
puts "'b' for the bottom line"
|
|
11
|
+
puts "'s' to save summaries to file"
|
|
12
|
+
puts "'t' to save transactions to file"
|
|
13
|
+
puts "\n'l' to load a new file\n"
|
|
14
|
+
puts "\nor 'q' to quit\n\n\n"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def to_pounds(money)
|
|
18
|
+
format = sprintf("%10.2f", money.truncate(2))
|
|
19
|
+
"£#{format}"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def dashes
|
|
23
|
+
"---".center(55,"-")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def date_range
|
|
27
|
+
"(#{self.all_transactions.last.date} - #{self.all_transactions.first.date})"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def facts(transactions)
|
|
31
|
+
"#{transactions.size} transactions for period #{date_range}"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def money_out_summary
|
|
35
|
+
print_summary("Outgoings", self.outgoings, self.outgoing_total)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def money_in_summary
|
|
39
|
+
print_summary("Incomings", self.incomings, self.incoming_total)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def transactions_all
|
|
43
|
+
output = output_s = ""
|
|
44
|
+
output << dashes
|
|
45
|
+
output << "\n"
|
|
46
|
+
output << "All transactions:\n"
|
|
47
|
+
output << "#{facts(self.all_transactions)}\n\n"
|
|
48
|
+
self.all_transactions.each do |trans|
|
|
49
|
+
if trans.moneyout == 0
|
|
50
|
+
output << "#{trans} + #{to_pounds(trans.moneyin)}\n"
|
|
51
|
+
else
|
|
52
|
+
output << "#{trans} - #{to_pounds(trans.moneyout)}\n"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
output << dashes
|
|
56
|
+
output << "\n\n"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def transactions_out
|
|
60
|
+
output = output_s = ""
|
|
61
|
+
output << dashes
|
|
62
|
+
output << "\n"
|
|
63
|
+
output << "Outgoing Transactions:\n"
|
|
64
|
+
output << "#{facts(self.outgoing_trans)}\n\n"
|
|
65
|
+
self.outgoing_trans.each{|trans| output << "#{trans} - #{to_pounds(trans.moneyout)}\n"}
|
|
66
|
+
output << dashes
|
|
67
|
+
output << "\n\n"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def transactions_in
|
|
71
|
+
output = output_s = ""
|
|
72
|
+
output << dashes
|
|
73
|
+
output << "\n"
|
|
74
|
+
output << "Incoming Transactions :\n"
|
|
75
|
+
output << "#{facts(self.incoming_trans)}\n\n"
|
|
76
|
+
self.incoming_trans.each{|trans| output << "#{trans} + #{to_pounds(trans.moneyin)}\n"}
|
|
77
|
+
output << dashes
|
|
78
|
+
output << "\n\n"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def print_summary(kind, hash, total)
|
|
82
|
+
output = output_s = ""
|
|
83
|
+
output << dashes
|
|
84
|
+
output << "\n"
|
|
85
|
+
output << "#{kind} Summary, totals from #{hash.size} different sources :\n"
|
|
86
|
+
output << "#{date_range}\n"
|
|
87
|
+
hash.sort_by{|k,v| v}.reverse.each{|k,v| output << "#{k} #{to_pounds(v)}\n".rjust(54)}
|
|
88
|
+
output << "\n"
|
|
89
|
+
output << "Total #{kind}: #{to_pounds(total)}\n".rjust(54)
|
|
90
|
+
output << dashes
|
|
91
|
+
output << "\n\n"
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def bottom_line
|
|
95
|
+
output = output_s = ""
|
|
96
|
+
output << dashes
|
|
97
|
+
output << "\n"
|
|
98
|
+
output << "#{facts(self.all_transactions)}".rjust(54)
|
|
99
|
+
output << "\n\n"
|
|
100
|
+
output << "Money In : #{to_pounds(self.incoming_total)}".rjust(54)
|
|
101
|
+
output << "\n"
|
|
102
|
+
output << "Money Out : #{to_pounds(self.outgoing_total)}".rjust(54)
|
|
103
|
+
output << "\n\n"
|
|
104
|
+
diff = self.incoming_total - self.outgoing_total
|
|
105
|
+
if self.outgoing_total > self.incoming_total
|
|
106
|
+
output << "Outgoings exceed Incomings, DEFICIT of #{to_pounds(diff)}".rjust(54)
|
|
107
|
+
else
|
|
108
|
+
output << "Incomings exceed Outgoings, SURPLUS of #{to_pounds(diff)}".rjust(54)
|
|
109
|
+
end
|
|
110
|
+
output << "\n"
|
|
111
|
+
output << dashes
|
|
112
|
+
output << "\n\n"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def self.farewell
|
|
116
|
+
puts "\n\n"
|
|
117
|
+
puts "*".center(55,'*')
|
|
118
|
+
puts " Banco ".center(55,'*')
|
|
119
|
+
puts " hope your numbers were positive ".center(55,'*')
|
|
120
|
+
puts " code@s33d.co ".center(55,'*')
|
|
121
|
+
puts "*".center(55,'*')
|
|
122
|
+
puts "\n\n\n"
|
|
123
|
+
exit
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def self.hello
|
|
127
|
+
puts "\n\n"
|
|
128
|
+
puts "Banco will summarize your bank statements.".center(55)
|
|
129
|
+
puts "import a .csv file for review".center(55)
|
|
130
|
+
puts "\n\n"
|
|
131
|
+
puts "the .csv file should have :".center(55)
|
|
132
|
+
puts "NO headers".center(55)
|
|
133
|
+
puts "with columns ordered (left to right)".center(55)
|
|
134
|
+
puts "date - description - type - money in - money out".center(55)
|
|
135
|
+
puts "all additional columns will be ignored".center(55)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def self.prompt
|
|
139
|
+
puts "\n\n"
|
|
140
|
+
puts "Enter the name of you .csv file to review".center(54)
|
|
141
|
+
puts "(use 'test.csv' for the test file)".center(54)
|
|
142
|
+
puts "or 'q' to quit...".center(55)
|
|
143
|
+
puts "\n\n"
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def save_summary_to_file(to_file="#{self.name}_summary.txt")
|
|
147
|
+
File.open(to_file, "w") do |file|
|
|
148
|
+
t = Time.now
|
|
149
|
+
file.puts t.strftime("\n\nprinted : %d %b %y at %I:%M%P")
|
|
150
|
+
file.puts "summarized by Banco from #{self.csv_file_name}"
|
|
151
|
+
file.puts "\n"
|
|
152
|
+
file.puts self.money_out_summary
|
|
153
|
+
file.puts "\n"
|
|
154
|
+
file.puts self.money_in_summary
|
|
155
|
+
file.puts "\n"
|
|
156
|
+
file.puts self.bottom_line
|
|
157
|
+
file.puts "\n"
|
|
158
|
+
file.puts "code@s33d.co".rjust(54)
|
|
159
|
+
end
|
|
160
|
+
puts "\n\nfile saved as #{self.name}_summary.txt\n\n"
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def save_transactions_to_file(to_file="#{self.name}_transactions.txt")
|
|
164
|
+
File.open(to_file, "w") do |file|
|
|
165
|
+
t = Time.now
|
|
166
|
+
file.puts t.strftime("\n\nprinted : %d %b %y at %I:%M%P")
|
|
167
|
+
file.puts "summarized by Banco from #{self.csv_file_name}"
|
|
168
|
+
file.puts "\n"
|
|
169
|
+
file.puts self.transactions_out
|
|
170
|
+
file.puts "\n"
|
|
171
|
+
file.puts self.transactions_in
|
|
172
|
+
file.puts "\n"
|
|
173
|
+
file.puts self.bottom_line
|
|
174
|
+
file.puts "\n"
|
|
175
|
+
file.puts "code@s33d.co".rjust(54)
|
|
176
|
+
end
|
|
177
|
+
puts "\n\nfile saved as #{self.name}_transactions.txt\n\n"
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require 'banco/reader'
|
|
2
|
+
module Banco
|
|
3
|
+
describe Reader do
|
|
4
|
+
before do
|
|
5
|
+
csv_file_name = "test.csv"
|
|
6
|
+
report_name = "test"
|
|
7
|
+
@testreader = Banco::Reader.new(csv_file_name, report_name)
|
|
8
|
+
@testreader.read_in_csv_data
|
|
9
|
+
end
|
|
10
|
+
it "should produce an array for all rows on csv file" do
|
|
11
|
+
expect(@testreader.all_from_csv.length).to eq(10)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require 'banco/reporter'
|
|
2
|
+
require 'banco/reader'
|
|
3
|
+
module Banco
|
|
4
|
+
describe Reporter do
|
|
5
|
+
before do
|
|
6
|
+
csv_file_name = "test.csv"
|
|
7
|
+
report_name = "test"
|
|
8
|
+
@testreader = Banco::Reader.new(csv_file_name, report_name)
|
|
9
|
+
@testreader.read_in_csv_data
|
|
10
|
+
@tester = Banco::Reporter.new('test.csv', 'test', @testreader.all_from_csv)
|
|
11
|
+
@tester.remove_blank_lines
|
|
12
|
+
@tester.split_in_out
|
|
13
|
+
@tester.total_outgoing
|
|
14
|
+
@tester.total_incoming
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should remove transactions with zero values (moneyin / moneyout)" do
|
|
18
|
+
expect(@tester.all_transactions.size).to eq(8)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
it "should produce an array of incoming transactions" do
|
|
23
|
+
expect(@tester.incoming_trans.size).to eq(4)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "should produce an array of outgoing transactions" do
|
|
27
|
+
expect(@tester.outgoing_trans.size).to eq(4)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "should produce a hash of outgoing transactions" do
|
|
31
|
+
expect(@tester.outgoings.size).to eq(2)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "should produce a hash of incoming transactions" do
|
|
35
|
+
expect(@tester.incomings.size).to eq(2)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "should sum incoming transactions by matching description string" do
|
|
39
|
+
expect(@tester.incomings['INCOMING2']).to eq(183.34)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "should sum outgoing transactions by matching description string" do
|
|
43
|
+
expect(@tester.outgoings['OUTGOING2']).to eq(182.68)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "should sum total incoming transactions" do
|
|
47
|
+
expect(@tester.incoming_total).to eq(321.58)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "should sum total outgoing transactions" do
|
|
51
|
+
expect(@tester.outgoing_total).to eq(320.92)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require 'banco/transaction'
|
|
2
|
+
|
|
3
|
+
module Banco
|
|
4
|
+
describe Transaction do
|
|
5
|
+
before do
|
|
6
|
+
@trans1 = Transaction.new("12/01/17","some transaction", "credit", "57.91", "0.00", "1")
|
|
7
|
+
@trans2 = Transaction.new("13/01/17","some other transaction", "debit", "0.00", "57.91",'2')
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# it "Should convert money in values to pence" do
|
|
11
|
+
# expect(@trans1.moneyin).to eq(5791)
|
|
12
|
+
# end
|
|
13
|
+
|
|
14
|
+
# it "Should convert money out values to pence" do
|
|
15
|
+
# expect(@trans2.moneyout).to eq(5791)
|
|
16
|
+
# end
|
|
17
|
+
|
|
18
|
+
it "Should have a description string of 22 characters (upcase)" do
|
|
19
|
+
expect(@trans2.description).to eq("SOME OTHER TRANSACTION")
|
|
20
|
+
expect(@trans1.description).to eq("SOME TRANSACTION ")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "Should have a type string upcased and 8 characters long" do
|
|
24
|
+
expect(@trans2.type).to eq("DEBIT ")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "Should have a date string" do
|
|
28
|
+
expect(@trans1.date).to eq("12/01/17")
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "Should have a row number" do
|
|
32
|
+
expect(@trans2.csv_row_count).to eq("2")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "should have a to_s of all date description type" do
|
|
36
|
+
expect(@trans1.to_s).to eq("12/01/17 CREDIT SOME TRANSACTION ")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "convert empty strings in money columns to integers" do
|
|
40
|
+
expect(@trans1.moneyout).to eq(0)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "convert empty strings in money columns to integers" do
|
|
44
|
+
expect(@trans2.moneyin).to eq(0)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: banco
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- s33d
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2017-11-14 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: rspec
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '2.8'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '2.8'
|
|
27
|
+
description: "Welcome to Banco !\n\nBanco has been developed to summarize statements
|
|
28
|
+
downloaded from your bank. \nInstall as a Rubygem, navigate to the directory your
|
|
29
|
+
.csv files are in and execute from the command line with 'banco'.\n\nBanco will
|
|
30
|
+
only accept comma seperated value files (.csv) and will produce a summary for the
|
|
31
|
+
period uploaded from the file. \n\nRemove the header line from your downloaded bank
|
|
32
|
+
statement and Banco will total the incoming & outgoing transactions for the period.
|
|
33
|
+
Reporting the bottom line aswell as summing up the values for similar transactions.
|
|
34
|
+
This is achieved by matching the description name, currently set at the first 9
|
|
35
|
+
characters of the string, you can change this to be more or less exact.\n\nHope
|
|
36
|
+
your numbers are positive !\ncode@s33d.co\nhttps://github.com/s33dco/banco"
|
|
37
|
+
email: code@s33d.co
|
|
38
|
+
executables:
|
|
39
|
+
- banco
|
|
40
|
+
extensions: []
|
|
41
|
+
extra_rdoc_files: []
|
|
42
|
+
files:
|
|
43
|
+
- LICENSE
|
|
44
|
+
- README
|
|
45
|
+
- bin/banco
|
|
46
|
+
- lib/banco/get_file.rb
|
|
47
|
+
- lib/banco/reader.rb
|
|
48
|
+
- lib/banco/reporter.rb
|
|
49
|
+
- lib/banco/transaction.rb
|
|
50
|
+
- lib/banco/viewable.rb
|
|
51
|
+
- spec/banco/reader_spec.rb
|
|
52
|
+
- spec/banco/reporter_spec.rb
|
|
53
|
+
- spec/banco/transaction_spec.rb
|
|
54
|
+
homepage: https://github.com/s33dco/banco
|
|
55
|
+
licenses:
|
|
56
|
+
- MIT
|
|
57
|
+
metadata: {}
|
|
58
|
+
post_install_message: Thanks for installing, hope your numbers are positive!
|
|
59
|
+
rdoc_options: []
|
|
60
|
+
require_paths:
|
|
61
|
+
- lib
|
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
63
|
+
requirements:
|
|
64
|
+
- - ">="
|
|
65
|
+
- !ruby/object:Gem::Version
|
|
66
|
+
version: '1.9'
|
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
68
|
+
requirements:
|
|
69
|
+
- - ">="
|
|
70
|
+
- !ruby/object:Gem::Version
|
|
71
|
+
version: '0'
|
|
72
|
+
requirements: []
|
|
73
|
+
rubyforge_project:
|
|
74
|
+
rubygems_version: 2.6.12
|
|
75
|
+
signing_key:
|
|
76
|
+
specification_version: 4
|
|
77
|
+
summary: Make your bank's .csv file statement more readable
|
|
78
|
+
test_files:
|
|
79
|
+
- spec/banco/reader_spec.rb
|
|
80
|
+
- spec/banco/reporter_spec.rb
|
|
81
|
+
- spec/banco/transaction_spec.rb
|