vfwcash 0.3.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.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +107 -0
  6. data/Rakefile +2 -0
  7. data/bin/vfwcash +5 -0
  8. data/lib/models/audit.rb +228 -0
  9. data/lib/models/balance.rb +95 -0
  10. data/lib/models/between.rb +100 -0
  11. data/lib/models/cash_account.rb +69 -0
  12. data/lib/models/gcash.rb +189 -0
  13. data/lib/models/ledger.rb +109 -0
  14. data/lib/models/register.rb +54 -0
  15. data/lib/models/split.rb +26 -0
  16. data/lib/models/split_ledger.rb +69 -0
  17. data/lib/models/sqlite_base.rb +10 -0
  18. data/lib/models/summary.rb +98 -0
  19. data/lib/models/tran.rb +12 -0
  20. data/lib/templates/vfw-gray.png +0 -0
  21. data/lib/templates/vfwcash.gnucash +0 -0
  22. data/lib/templates/vfwcash.yml +95 -0
  23. data/lib/vfwcash/api.rb +48 -0
  24. data/lib/vfwcash/cli.rb +195 -0
  25. data/lib/vfwcash/controller.rb +83 -0
  26. data/lib/vfwcash/version.rb +3 -0
  27. data/lib/vfwcash.rb +90 -0
  28. data/pdf_examples/audit_201507.pdf +2826 -0
  29. data/pdf_examples/balance_201508.pdf +2283 -0
  30. data/pdf_examples/controllers/checkbooks_controller.rb +99 -0
  31. data/pdf_examples/ledger_201504.pdf +5758 -0
  32. data/pdf_examples/ledger_summary.pdf +5719 -0
  33. data/pdf_examples/register_201508.pdf +1157 -0
  34. data/pdf_examples/split_201508.pdf +4930 -0
  35. data/pdf_examples/views/checkbooks/balance.html.slim +53 -0
  36. data/pdf_examples/views/checkbooks/between.html.slim +53 -0
  37. data/pdf_examples/views/checkbooks/index.html.slim +57 -0
  38. data/pdf_examples/views/checkbooks/ledger.html.slim +58 -0
  39. data/pdf_examples/views/checkbooks/register.html.slim +44 -0
  40. data/pdf_examples/views/checkbooks/split.html.slim +45 -0
  41. data/pdf_examples/views/checkbooks/summary.html.slim +56 -0
  42. data/vfwcash.gemspec +31 -0
  43. metadata +198 -0
@@ -0,0 +1,48 @@
1
+
2
+ module Vfwcash
3
+ class Api
4
+ attr_accessor :config, :cash
5
+ def initialize(date=nil)
6
+ @date = date
7
+ require_relative '../models/sqlite_base'
8
+ @config = Vfwcash::Config
9
+ Dir.glob(File.join(LibPath,'models/*')).each do |file|
10
+ require file
11
+ end
12
+ @cash = Gcash.new(@config)
13
+ unless @cash.dates.include?(@date)
14
+ puts "No transactions exist for #{@date.beginning_of_month}"
15
+ exit(0)
16
+ end
17
+ end
18
+
19
+ def between(from,to)
20
+ pdf = Pdf::Between.new(@date,@cash,from,to)
21
+ end
22
+
23
+ def ledger
24
+ pdf = Pdf::Ledger.new(@date,@cash)
25
+ end
26
+
27
+ def summary
28
+ pdf = Pdf::Summary.new(@cash)
29
+ end
30
+
31
+ def register
32
+ pdf = Pdf::Register.new(@date,@cash)
33
+ end
34
+
35
+ def split
36
+ pdf = Pdf::SplitLedger.new(@date,@cash)
37
+ end
38
+
39
+ def audit
40
+ pdf = Pdf::Audit.new(@date,@cash)
41
+ end
42
+
43
+ def balance
44
+ pdf = Pdf::Balance.new(@date,@cash)
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,195 @@
1
+ require 'thor'
2
+ # require 'vfwcash/cli/register'
3
+ require 'chronic'
4
+ require 'active_support'
5
+
6
+
7
+ module Vfwcash
8
+
9
+ class Checkbook < Thor
10
+ map %w[--dates -d] => :__print_date_help
11
+
12
+ desc "--dates, -d", "print date format options"
13
+ def __print_date_help
14
+ puts <<-DATE_HELP
15
+ The DATE parameter is optional on all reports requiring a date and will default to the current date if not present.
16
+
17
+ All dates will be converted to the first of the month requardless of the date entered.
18
+
19
+ Entered dates are parsed using Chronic (https://github.com/mojombo/chronic).
20
+ Chronic provide a wide range options.
21
+
22
+ Probably the easiest option is the yyyy-mm format (again day is optional) but you can do stuff like:
23
+ last-may
24
+ last-October
25
+ 'oct 2014'
26
+ DATE_HELP
27
+ end
28
+
29
+ desc "between date1 date2", "Get balances between two dates"
30
+ long_desc <<-HELLO_WORLD
31
+
32
+ Produces a Fund Balance summary between two dates (beginning balance, debits, credits, ending balance) in a compact format.
33
+
34
+ HELLO_WORLD
35
+
36
+ def between(first, last)
37
+ sdate = get_date(first)
38
+ edate = get_date(last)
39
+ bom = sdate - sdate.day + 1
40
+ Controller.new(bom).between(sdate,edate)
41
+ end
42
+
43
+
44
+ ######### VERSION
45
+ map %w[--version -v] => :__print_version
46
+
47
+ desc "--version, -v", "print the version"
48
+ def __print_version
49
+ puts "Version: #{Vfwcash::VERSION}"
50
+ end
51
+
52
+ ######### INSTALL
53
+ desc "install [--dir --db]", "Install config files and optional test DB in pwd or pwd/--dir"
54
+ long_desc <<-HELLO_WORLD
55
+
56
+ Install will create two directories [config,pdf]in your current working directory.
57
+ The PDF directory will contain copies of the generated PDF reports.
58
+ The config directory will contain a vfwcash.yml file that contains post information,
59
+ path to sqlit3 database
60
+ and other configuration data needed to generate a Trustees' Report of Audit.
61
+
62
+ -- dir='dirname' will create a new directory in the working directory before the copies
63
+
64
+ -- db will copy a GnuCash test sqlite3 database into the config directory
65
+
66
+ HELLO_WORLD
67
+ method_option :dir, type: :string,
68
+ desc: "Create a new directory",
69
+ required: false
70
+ method_option :db, type: :boolean,
71
+ default: false,
72
+ desc: "Copy a Test GnuCash Database to the config directory"
73
+
74
+
75
+ def install
76
+ Vfwcash.install(options)
77
+ end
78
+
79
+ ######### REGISTER
80
+ desc "register [DATE]", "Checkbook register report"
81
+ long_desc <<-HELLO_WORLD
82
+
83
+ Produces a PDF reports of the checkbook register by month. All tranasaction for the month
84
+ are displayed, ordered by date and check number. A running balance is displayed starting with the
85
+ beginning balance. There is one line per transaction. Savings account transactions are displayed
86
+ but the amount is not added to the running balance.
87
+
88
+ The --split option displays the same information, but lines are added for each transaction showing
89
+ the amount of each split by fund or income/expense account
90
+
91
+
92
+ HELLO_WORLD
93
+ def register( date=nil )
94
+ bom = get_date(date)
95
+ Controller.new(bom).register
96
+ end
97
+
98
+ ######### SPLIT
99
+ desc "split [DATE]", "Checkbook split register report"
100
+ long_desc <<-HELLO_WORLD
101
+
102
+ Produces a PDF reports of the checkbook register by month. All tranasaction for the month
103
+ are displayed, ordered by date and check number. A running balance is displayed starting with the
104
+ beginning balance. Savings account transactions are displayed
105
+ but the amount is not added to the running balance.
106
+
107
+ Each transaction will have multiple lines displaying
108
+ the amount of each split by fund or income/expense account
109
+
110
+
111
+ HELLO_WORLD
112
+ def split( date=nil )
113
+ bom = get_date(date)
114
+ Controller.new(bom).split
115
+ end
116
+
117
+ ######### LEDGER
118
+ desc "ledger [DATE]", "General Ledger report by month"
119
+ long_desc <<-HELLO_WORLD
120
+
121
+ Produces a PDF report of the Post's General Ledger formated much like the VFW Ledger book.
122
+
123
+ Each transaction displays tranaction information along with each fund distribution. Balances include
124
+ the beginning balance, total debits(increases) and credits(decreases) and ending balance.
125
+
126
+ HELLO_WORLD
127
+
128
+ option :summary
129
+ def ledger( date=nil )
130
+ bom = get_date(date)
131
+ Controller.new(bom).ledger
132
+ end
133
+
134
+ ######### SUMMARY
135
+ desc "summary [DATE]", "General Ledger Summary Report"
136
+ long_desc <<-HELLO_WORLD
137
+
138
+ Produces a PDF report containing only a monthly summary of Post's General Ledger.
139
+
140
+ The report displays all months in the checkbook but only contains balances, debits and credits sums.
141
+
142
+ HELLO_WORLD
143
+
144
+ option :summary
145
+ def summary( date=nil )
146
+ bom = get_date(date)
147
+ Controller.new(bom).summary
148
+ end
149
+
150
+ ######### Audit
151
+ desc "audit [DATE]", "Trustee Audit Report "
152
+ long_desc <<-HELLO_WORLD
153
+
154
+ Productes a Trustee Audit Report for the ending quarter that ended before
155
+ the date enter. If date is not ended, it will be the last report.
156
+
157
+ HELLO_WORLD
158
+
159
+ def audit( date=nil )
160
+ bom = get_date(date)
161
+ Controller.new(bom).audit
162
+ end
163
+
164
+ ######### Balance
165
+ desc "balance [DATE]", "Monthly Fund Balance Summary "
166
+ long_desc <<-HELLO_WORLD
167
+
168
+ Produces a Monthly Fund Balance summary (beginning balance, debits, credits, ending balance) for only one month in a compact format.
169
+
170
+ HELLO_WORLD
171
+ def balance( date=nil )
172
+ bom = get_date(date)
173
+ Controller.new(bom).balance
174
+ end
175
+
176
+ private
177
+
178
+ def get_date(date)
179
+ if date.nil?
180
+ bom = Date.today
181
+ else
182
+ bom = Chronic.parse(date)
183
+ if bom.nil?
184
+ puts "Invalid date #{date}"
185
+ exit(0)
186
+ else
187
+ bom = bom.to_date
188
+ end
189
+ end
190
+ bom
191
+ end
192
+
193
+
194
+ end
195
+ end
@@ -0,0 +1,83 @@
1
+ require 'active_record'
2
+ require 'sqlite3'
3
+ require "prawn/table"
4
+ require "prawn"
5
+ require 'yaml'
6
+
7
+ module Vfwcash
8
+ class Controller
9
+ attr_accessor :config, :cash
10
+ def initialize(date)
11
+ require_relative '../models/sqlite_base'
12
+ @config = Vfwcash::Config
13
+ @date = date
14
+ Dir.glob(File.join(LibPath,'models/*')).each do |file|
15
+ require file
16
+ end
17
+ @cash = Gcash.new(@config)
18
+ unless @cash.dates.include?(@date)
19
+ puts "No transactions exist for #{@date.beginning_of_month}"
20
+ exit(0)
21
+ end
22
+ end
23
+
24
+ def between(from,to)
25
+ pdf = Pdf::Between.new(@date,@cash,from,to)
26
+ filename = "#{PWD}/pdf/between_#{from}_#{to}.pdf"
27
+ pdf.render_file(filename)
28
+ open_pdf(filename)
29
+ end
30
+
31
+ def ledger
32
+ pdf = Pdf::Ledger.new(@date,@cash)
33
+ filename = "#{PWD}/pdf/ledger_#{Vfwcash.yyyymm(@date)}.pdf"
34
+ pdf.render_file(filename)
35
+ open_pdf(filename)
36
+ end
37
+
38
+ def summary
39
+ pdf = Pdf::Summary.new(@cash)
40
+ filename = "#{PWD}/pdf/ledger_summary.pdf"
41
+ pdf.render_file(filename)
42
+ open_pdf(filename)
43
+ end
44
+
45
+
46
+ def register
47
+ pdf = Pdf::Register.new(@date,@cash)
48
+ filename = "#{PWD}/pdf/register_#{Vfwcash.yyyymm(@date)}.pdf"
49
+ pdf.render_file(filename)
50
+ open_pdf(filename)
51
+ end
52
+
53
+ def split
54
+ pdf = Pdf::SplitLedger.new(@date,@cash)
55
+ filename = "#{PWD}/pdf/split_#{Vfwcash.yyyymm(@date)}.pdf"
56
+ pdf.render_file(filename)
57
+ open_pdf(filename)
58
+ end
59
+
60
+ def audit
61
+ pdf = Pdf::Audit.new(@date,@cash)
62
+ filename = "#{PWD}/pdf/audit_#{Vfwcash.yyyymm(@date.beginning_of_quarter)}.pdf"
63
+ pdf.render_file(filename)
64
+ open_pdf(filename)
65
+ end
66
+
67
+ def balance
68
+ pdf = Pdf::Balance.new(@date,@cash)
69
+ filename = "#{PWD}/pdf/balance_#{Vfwcash.yyyymm(@date)}.pdf"
70
+ pdf.render_file(filename)
71
+ open_pdf(filename)
72
+ end
73
+
74
+ def open_pdf(filename)
75
+ if Gem::Platform.local.os == 'darwin'
76
+ `open #{filename}`
77
+ else
78
+ `start #{filename}`
79
+ end
80
+ end
81
+
82
+ end
83
+ end
@@ -0,0 +1,3 @@
1
+ module Vfwcash
2
+ VERSION = "0.3.0"
3
+ end
data/lib/vfwcash.rb ADDED
@@ -0,0 +1,90 @@
1
+ require "vfwcash/version"
2
+ require 'vfwcash/cli'
3
+ require 'vfwcash/controller'
4
+ require 'vfwcash/api'
5
+
6
+ module Vfwcash
7
+ # Define constants to define where your are and location of config file
8
+ LibPath = File.expand_path(File.dirname(__FILE__))
9
+ PWD = Dir.pwd
10
+ Config = YAML.load_file(File.join(PWD,'config/vfwcash.yml'))
11
+
12
+ def self.yyyymm(date=nil)
13
+ date = Vfwcash.set_date(date)
14
+ yyyymm = date.strftime('%Y%m') # "#{date.year}#{date.month.to_s.rjust(2,'0')}"
15
+ end
16
+
17
+ def self.transaction_range
18
+ t = Tran.order(:post_date)
19
+ first = Date.parse(t.first.post_date).beginning_of_month
20
+ last = Date.parse(t.last.post_date).end_of_month
21
+ first..last
22
+ end
23
+
24
+ def self.set_date(date=nil)
25
+ if date.nil? || date == ""
26
+ date = Date.today
27
+ elsif date.class == Date
28
+ else
29
+ if date.length == 6
30
+ date += '01'
31
+ end
32
+ date = Date.parse(date)
33
+ end
34
+ date
35
+ end
36
+
37
+ def self.money(int)
38
+ dollars = int / 100
39
+ cents = (int % 100) / 100.0
40
+ amt = dollars + cents
41
+ set_zero = sprintf('%.2f',amt) # now have a string to 2 decimals
42
+ set_zero.gsub(/(\d)(?=(\d{3})+(?!\d))/, "\\1,") # add commas
43
+ end
44
+
45
+ def self.valid_root?
46
+ unless Dir.exist?(PWD+'/config') && Dir.exist?(PWD+'/pdf') && File.exist?(PWD+"/config/"+"vfwcash.yml")
47
+ puts "Error: vfwcash must be run from a diectory containing valid configuration files"
48
+ exit(0)
49
+ end
50
+ end
51
+
52
+ def self.install(options)
53
+ wd = PWD
54
+ ok = true
55
+ if options['dir'].present?
56
+ unless Dir.exist?(wd+options['dir'])
57
+ Dir.mkdir(wd+'/'+options['dir'])
58
+ puts "Created a new directory in #{wd}"
59
+ ok = false
60
+ Dir.chdir(wd+'/'+options['dir'])
61
+ wd = Dir.pwd
62
+ end
63
+ end
64
+ unless Dir.exist?(wd+'/config')
65
+ Dir.mkdir(wd+'/config')
66
+ puts "Created config directory in #{wd}"
67
+ ok = false
68
+ end
69
+ unless Dir.exist?(wd+'/pdf')
70
+ Dir.mkdir(wd+'/pdf')
71
+ puts "Created pdf directory in #{wd}"
72
+ ok = false
73
+ end
74
+ unless File.exist?(wd+"/config/"+"vfwcash.yml")
75
+ FileUtils.cp((LibPath+"/templates/vfwcash.yml"),(wd+"/config/"+"vfwcash.yml"))
76
+ puts "Created vfwcash.yml file in config directory, must be edited for your post."
77
+ ok = false
78
+ end
79
+ if options['db']
80
+ unless File.exist?(wd+"/config/"+"vfwcash.gnucash")
81
+ FileUtils.cp((LibPath+"/templates/vfwcash.gnucash"),(wd+"/config/"+"vfwcash.gnucash"))
82
+ puts "Created vfwcash.gnucash db in config directory."
83
+ ok = false
84
+ end
85
+ end
86
+
87
+ puts "No installation required" if ok
88
+ puts "Installation complete. Edit your vfwcash.yml file to set your post information." if !ok
89
+ end
90
+ end