simple-ynab 0.0.3 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/simple-ynab +113 -27
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 01d194396c8cdff4df84b40021ac98a64a572f69
|
4
|
+
data.tar.gz: 06ea74ea4e20eccd2924b295f866f8c695505fc0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 754c93c1147dcea2fa632c8eedb534094a555ce9b00bbbfd2d820c4f102a2a84cc12d87f56ba879c0c5119a80f3ec2dcdb6f5d4e2e724838fd1e004e84e34ba4
|
7
|
+
data.tar.gz: 9fca07efdd7b2db2737093f4236ba47b5940e54fefeb19e7ecad00fad059e00ae8e8be36550dfda0c61056fda17bbad35539b8f535fe236594fb4a86d0aa6447
|
data/bin/simple-ynab
CHANGED
@@ -1,49 +1,135 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
# Converts the CSV generated by Simple Bank into a CSV understandable by YNAB
|
3
4
|
require 'csv'
|
5
|
+
require 'slop'
|
6
|
+
require 'colorize'
|
7
|
+
require 'Date'
|
4
8
|
|
9
|
+
opts = Slop.parse(:banner => 'simple-ynab', :help => true ) do
|
10
|
+
on 'd', 'days=', 'Strips all rows before x days ago, e.g -d 30 ', :argument => true
|
11
|
+
on 'y', 'ynab_date', 'Converts date to MM/DD/YYYY. SEE README.md FOR WARNINGS!!!', :argument => false
|
12
|
+
on 'p', 'pending', 'Include pending transactions', :argument => false
|
13
|
+
on 'v', 'verbose', 'Print debug information', :argument => false
|
14
|
+
on 'x', 'very_verbose', 'Prints an uncomfortable amount of debugging information to terminal, does not replace -v', :argument => false
|
15
|
+
end
|
5
16
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
@newcsv = []
|
10
|
-
puts ""
|
11
|
-
|
17
|
+
# Which column headers in the Simple CSV match up with the columns headers needed by YNAB
|
18
|
+
simple_keywords = ["Date", "Description", "Category", "Memo", "Amount"]
|
19
|
+
ynab_keywords = ["Date", "Payee", "Category", "Memo", "Amount"]
|
12
20
|
|
13
|
-
|
21
|
+
##### Get the csv file from args
|
14
22
|
ARGV.each do |argument|
|
15
|
-
|
23
|
+
@csvfile = ARGV[0]
|
16
24
|
end
|
17
25
|
|
26
|
+
Kernel.trap('INT') { Kernel.exit } #Exit cleanly with ctrl+c
|
27
|
+
|
18
28
|
if ARGV.empty?
|
19
|
-
|
20
|
-
|
29
|
+
print "No file detected, enter file name: "
|
30
|
+
@csvfile = gets
|
21
31
|
end
|
22
32
|
|
33
|
+
|
23
34
|
# Import csv
|
24
|
-
|
25
|
-
|
35
|
+
if opts.verbose? then puts "Importing CSV".magenta end
|
36
|
+
simplecsv = CSV.read(@csvfile) #http://bit.ly/1mSlqfA
|
37
|
+
if opts.verbose? then puts "Headers are: #{simplecsv[0]}".blue end
|
26
38
|
|
27
|
-
# Rename the Simple csv headers to match the ynab csv headers
|
28
|
-
indicies = @simple_keywords.map{ |column| csv.headers.index(column)}
|
29
39
|
|
30
|
-
#
|
31
|
-
|
40
|
+
# Get the 'simple' header indicies
|
41
|
+
simple_headers = simple_keywords.map{ |column| simplecsv[0].index(column)}
|
42
|
+
if opts.verbose? then puts "Simple_headers indexes are #{simple_headers}".blue end
|
32
43
|
|
33
44
|
|
34
|
-
|
35
|
-
|
45
|
+
# Create a new array that omits the CSV rows when the value in the 'Pending' column = true
|
46
|
+
if opts.verbose? then puts "Removing pending transactions".magenta end
|
47
|
+
if opts.pending? then puts "User chose to include pending transactions".blue end
|
48
|
+
no_pending_array = Array.new()
|
49
|
+
pending = simplecsv[0].find_index('Pending') # Column number that contains 'Pending'
|
50
|
+
simplecsv.each do |row|
|
51
|
+
# If -p (Pending) option is not provided, Only push rows with 'false' in the pending column.
|
52
|
+
# Make sure header (row 0) gets included too.
|
53
|
+
if opts.pending? or row[pending].to_s.casecmp('false') == 0 or row[pending].to_s.casecmp('Pending') == 0
|
54
|
+
no_pending_array.push(row)
|
55
|
+
else
|
56
|
+
if opts.verbose? then puts "Removing pending transaction #{row}".yellow end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
# Create a new array that only includes the YNAB columns
|
62
|
+
ynab_array = Array.new()
|
63
|
+
no_pending_array.each do |row| #Itterate over every row in new 'pending free' array
|
64
|
+
newrow = Array.new() #Create a temporary array
|
65
|
+
simple_headers.each do | desired_index | #Itterate over each of the columsn we want e.g. [0, 7, 9, 16, 3]
|
66
|
+
newrow.push(row[desired_index]) #Add the new value to the temporary array
|
67
|
+
end
|
68
|
+
ynab_array.push(newrow) #Add each row to the new YNAB array
|
69
|
+
end
|
36
70
|
|
37
71
|
|
38
|
-
#
|
39
|
-
|
40
|
-
|
41
|
-
|
72
|
+
# Replace the headers with the YNAB headers
|
73
|
+
if opts.verbose?
|
74
|
+
puts "Replacing csv headers with ynab headers".magenta
|
75
|
+
puts "Simple column headers #{ynab_array[0]}".blue
|
42
76
|
end
|
77
|
+
ynab_array[0] = ynab_keywords
|
78
|
+
if opts.verbose? then puts "YNAB column headers are #{ynab_array[0]}".blue end
|
79
|
+
|
80
|
+
|
81
|
+
# Only include dates within the specified range
|
82
|
+
ynab_array_less_dates = Array.new()
|
83
|
+
ynab_array_less_dates[0] = ynab_array[0] # Copy the header to new array
|
84
|
+
days_ago = Date.today() - opts[:days].to_i
|
85
|
+
date_column = ynab_array[0].find_index('Date') #Find the index of colum that contains 'Date' data (usually [0])
|
86
|
+
ynab_array.each do | row |
|
87
|
+
if opts.days? # User specified number of days to copy from CSV
|
88
|
+
if row[date_column] =~ /\d/ and Date.parse(row[date_column]) >= days_ago #Only apply to rows that contain dates, skip rows without nummbers (e.g. header row)
|
89
|
+
if opts.very_verbose? then puts "Transaction was less than #{opts[:days].to_i} days ago: #{row}".light_green end
|
90
|
+
ynab_array_less_dates.push(row) # Only push rows less than x number of days old
|
91
|
+
else
|
92
|
+
if opts.very_verbose? then puts "Transaction was more than #{opts[:days].to_i} days ago: #{row}".yellow end
|
93
|
+
end
|
94
|
+
else
|
95
|
+
ynab_array_less_dates.push(row) # Push all rows
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
# Change the dates from YYYY-MM-DD to MM-DD-YYYY, saves 1 click when importing in YNAB
|
101
|
+
# Has side affect of sometimes causing YNAB to fail to match previously imported transactions
|
102
|
+
if opts.ynab_date?
|
103
|
+
puts "WARNING: YNAB may fail to match transactions previously imported with different date formats".red
|
104
|
+
puts "Converting dates to MM/DD/YYYY".red
|
105
|
+
if opts.verbose? then puts "Changing simple dates to ynab dates".magenta end
|
106
|
+
if ynab_array_less_dates[0].any?{|s| s.casecmp('date')==0}
|
107
|
+
date_column = ynab_array_less_dates[0].find_index('Date') #Find the index of colum that contains 'Date' data (usually [0])
|
108
|
+
else
|
109
|
+
puts "Unable to find word 'Date' in csv header. #{ynab_array_less_dates[0]}".red
|
110
|
+
exit
|
111
|
+
end
|
112
|
+
if opts.verbose? then puts "The date column in ynab_array_less_dates is #{date_column}: #{ynab_array_less_dates[0][date_column]}".blue end
|
113
|
+
ynab_array_less_dates.each do |row|
|
114
|
+
if row[date_column] =~ /\d/ #Only apply to rows that contain dates, skip rows without nummbers (e.g. header row)
|
115
|
+
row[date_column] = Date.parse(row[date_column]).strftime(format='%m/%d/%Y').to_s
|
116
|
+
else
|
117
|
+
if opts.verbose? then puts "Not changing date syntax on header row #{row}".blue end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
# Save to file
|
124
|
+
if opts.verbose? then puts "Saving to CSV file".magenta end
|
125
|
+
|
126
|
+
filename = File.basename(@csvfile,".*")
|
127
|
+
pathname = File.join( File.dirname(@csvfile), "#{filename}.simple.csv" )
|
128
|
+
puts ""
|
129
|
+
puts "Saving to new file: #{pathname}".green
|
43
130
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
end
|
131
|
+
CSV.open(pathname,'w') do |csv|
|
132
|
+
ynab_array_less_dates.each do | row |
|
133
|
+
csv << row
|
134
|
+
end
|
49
135
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simple-ynab
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Spencer Owen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-11-10 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Converts simple bank csv to ynab csv
|
14
14
|
email: owenspencer@gmail.com
|
@@ -18,7 +18,7 @@ extensions: []
|
|
18
18
|
extra_rdoc_files: []
|
19
19
|
files:
|
20
20
|
- bin/simple-ynab
|
21
|
-
homepage:
|
21
|
+
homepage: https://github.com/spuder/simple-ynab
|
22
22
|
licenses:
|
23
23
|
- MIT
|
24
24
|
metadata: {}
|
@@ -43,3 +43,4 @@ signing_key:
|
|
43
43
|
specification_version: 4
|
44
44
|
summary: Converts csv from simple format to ynab format
|
45
45
|
test_files: []
|
46
|
+
has_rdoc:
|