simple-ynab 0.0.3 → 0.1.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 +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:
|