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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +107 -0
- data/Rakefile +2 -0
- data/bin/vfwcash +5 -0
- data/lib/models/audit.rb +228 -0
- data/lib/models/balance.rb +95 -0
- data/lib/models/between.rb +100 -0
- data/lib/models/cash_account.rb +69 -0
- data/lib/models/gcash.rb +189 -0
- data/lib/models/ledger.rb +109 -0
- data/lib/models/register.rb +54 -0
- data/lib/models/split.rb +26 -0
- data/lib/models/split_ledger.rb +69 -0
- data/lib/models/sqlite_base.rb +10 -0
- data/lib/models/summary.rb +98 -0
- data/lib/models/tran.rb +12 -0
- data/lib/templates/vfw-gray.png +0 -0
- data/lib/templates/vfwcash.gnucash +0 -0
- data/lib/templates/vfwcash.yml +95 -0
- data/lib/vfwcash/api.rb +48 -0
- data/lib/vfwcash/cli.rb +195 -0
- data/lib/vfwcash/controller.rb +83 -0
- data/lib/vfwcash/version.rb +3 -0
- data/lib/vfwcash.rb +90 -0
- data/pdf_examples/audit_201507.pdf +2826 -0
- data/pdf_examples/balance_201508.pdf +2283 -0
- data/pdf_examples/controllers/checkbooks_controller.rb +99 -0
- data/pdf_examples/ledger_201504.pdf +5758 -0
- data/pdf_examples/ledger_summary.pdf +5719 -0
- data/pdf_examples/register_201508.pdf +1157 -0
- data/pdf_examples/split_201508.pdf +4930 -0
- data/pdf_examples/views/checkbooks/balance.html.slim +53 -0
- data/pdf_examples/views/checkbooks/between.html.slim +53 -0
- data/pdf_examples/views/checkbooks/index.html.slim +57 -0
- data/pdf_examples/views/checkbooks/ledger.html.slim +58 -0
- data/pdf_examples/views/checkbooks/register.html.slim +44 -0
- data/pdf_examples/views/checkbooks/split.html.slim +45 -0
- data/pdf_examples/views/checkbooks/summary.html.slim +56 -0
- data/vfwcash.gemspec +31 -0
- metadata +198 -0
data/lib/models/gcash.rb
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
require "yaml/store"
|
2
|
+
|
3
|
+
module Vfwcash
|
4
|
+
|
5
|
+
class Gcash
|
6
|
+
# gcash is the primary interface to the GNUCash database
|
7
|
+
# The initializer sets attributes based on data in the db and from the config file
|
8
|
+
# that is common to all reports.
|
9
|
+
|
10
|
+
# API calls provide informtion needed for specific reports.
|
11
|
+
|
12
|
+
attr_accessor :balances, :checking, :savings, :checking_funds,:savings_funds,
|
13
|
+
:dates, :bmonth, :checking_acct, :savings_acct, :tmonths, :config
|
14
|
+
|
15
|
+
def initialize(config)
|
16
|
+
@config = config
|
17
|
+
@checking_acct = @config[:checking_acct]
|
18
|
+
@savings_acct = @config[:savings_acct]
|
19
|
+
@checking_funds = CashAccount.find_by(name:@checking_acct).children.pluck(:name)
|
20
|
+
@savings_funds = CashAccount.find_by(name:@savings_acct).children.pluck(:name)
|
21
|
+
@dates = Vfwcash.transaction_range
|
22
|
+
set_tmonths
|
23
|
+
end
|
24
|
+
# COMMON Methods
|
25
|
+
def set_tmonths
|
26
|
+
@tmonths = []
|
27
|
+
first = @dates.first
|
28
|
+
last = @dates.last
|
29
|
+
curr = first
|
30
|
+
while curr < last do
|
31
|
+
@tmonths << "#{curr.year}#{curr.month.to_s.rjust(2,'0')}"
|
32
|
+
curr += 1.month
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_fund_balances(bdate,edate)
|
37
|
+
@balances = {}
|
38
|
+
@balances[:checking] = {bbalance:0,diff:0,debits:0,credits:0,ebalance:0}
|
39
|
+
@balances[:savings] = {bbalance:0,diff:0,debits:0,credits:0,ebalance:0}
|
40
|
+
accts = @checking_funds + @savings_funds
|
41
|
+
accts.each do |f|
|
42
|
+
acct = CashAccount.find_by(name:f)
|
43
|
+
@balances[f] = acct.balances_between(bdate,edate)
|
44
|
+
if @checking_funds.include?(f)
|
45
|
+
sum_from_to(@balances[f],@balances[:checking])
|
46
|
+
else
|
47
|
+
sum_from_to(@balances[f],@balances[:savings])
|
48
|
+
end
|
49
|
+
end
|
50
|
+
@checking = @balances[:checking]
|
51
|
+
@savings = @balances[:savings]
|
52
|
+
end
|
53
|
+
|
54
|
+
def sum_from_to(ffund,tfund)
|
55
|
+
ffund.each do |k,v|
|
56
|
+
tfund[k] += v
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def get_all_balances
|
61
|
+
balances = {checking:{},savings:{}}
|
62
|
+
accts = @checking_funds + @savings_funds
|
63
|
+
accts.each do |f|
|
64
|
+
acct = CashAccount.find_by(name:f)
|
65
|
+
balances[f] = {}
|
66
|
+
tmonths.each do |m|
|
67
|
+
bom = Date.parse(m+"01")
|
68
|
+
eom = bom.end_of_month
|
69
|
+
balances[f][m] = get_fund_balances(bom,eom)
|
70
|
+
balances[:checking][m] = @checking
|
71
|
+
balances[:savings][m] = @savings
|
72
|
+
end
|
73
|
+
end
|
74
|
+
@balances = balances
|
75
|
+
@checking = @balances[:checking]
|
76
|
+
@saving = @balances[:savings]
|
77
|
+
end
|
78
|
+
|
79
|
+
# REPORT Specific Methods
|
80
|
+
def between_balance(from,to)
|
81
|
+
between = {}
|
82
|
+
accts = @checking_funds + @savings_funds
|
83
|
+
accts.each do |f|
|
84
|
+
acct = CashAccount.find_by(name:f)
|
85
|
+
between[f] = acct.balances_between(from,to)
|
86
|
+
end
|
87
|
+
between
|
88
|
+
end
|
89
|
+
|
90
|
+
def audit_api(report_date)
|
91
|
+
date = Vfwcash.set_date(report_date)
|
92
|
+
boq = date.beginning_of_quarter
|
93
|
+
eoq = boq.end_of_quarter
|
94
|
+
if eoq.month >= date.month
|
95
|
+
boq = (boq - 1.month).beginning_of_quarter
|
96
|
+
eoq = boq.end_of_quarter
|
97
|
+
end
|
98
|
+
get_fund_balances(boq,eoq)
|
99
|
+
rbalances = @balances
|
100
|
+
rbalances["Cash"] = {bbalance:100000,ebalance:100000,debits:0,credits:0}
|
101
|
+
rbalances[:dates] = {boq:boq,eoq:eoq, report_date:date}
|
102
|
+
rbalances
|
103
|
+
end
|
104
|
+
|
105
|
+
def split_ledger_api(date)
|
106
|
+
response = {rows:split_ledger(date)}
|
107
|
+
response[:balances] = {checking:@checking}
|
108
|
+
response[:month] = @bmonth
|
109
|
+
return response
|
110
|
+
end
|
111
|
+
|
112
|
+
def split_ledger(date)
|
113
|
+
@bmonth = Vfwcash.yyyymm(date)
|
114
|
+
trans = Tran.month_transactions(date)
|
115
|
+
lines = []
|
116
|
+
b = @checking[:bbalance]
|
117
|
+
trans.each do |t|
|
118
|
+
date = Date.parse(t.post_date)
|
119
|
+
line = {date: date.strftime("%m/%d/%Y"),num:t.num,desc:t.description,
|
120
|
+
checking:{db:0,cr:0},details:[],balance:0, memo:nil,r:nil}
|
121
|
+
t.splits.each do |s|
|
122
|
+
details = s.details
|
123
|
+
if details[:name].include?("#{@checking_acct}:")
|
124
|
+
line[:checking][:db] += details[:db]
|
125
|
+
line[:checking][:cr] += details[:cr]
|
126
|
+
b += (details[:db] - details[:cr])
|
127
|
+
line[:balance] = b
|
128
|
+
line[:r] = details[:r]
|
129
|
+
else
|
130
|
+
line[:balance] = b
|
131
|
+
if line[:memo].nil?
|
132
|
+
line[:memo] = details[:name]
|
133
|
+
else
|
134
|
+
line[:memo] = "- Split Transaction -"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
line[:details] << details
|
138
|
+
end
|
139
|
+
lines << line
|
140
|
+
end
|
141
|
+
lines
|
142
|
+
end
|
143
|
+
|
144
|
+
def month_ledger_api(date)
|
145
|
+
response = {rows:month_ledger(date)}
|
146
|
+
fund_bal = {}
|
147
|
+
@checking_funds.each do |f|
|
148
|
+
fund_bal[f] = @balances[f]
|
149
|
+
end
|
150
|
+
response[:balances] = {savings:@savings,checking:@checking,funds:fund_bal}
|
151
|
+
response[:funds] = {savings:@savings_funds,checking:@checking_funds}
|
152
|
+
response[:month] = @bmonth
|
153
|
+
return response
|
154
|
+
end
|
155
|
+
|
156
|
+
def month_ledger(date)
|
157
|
+
@bmonth = Vfwcash.yyyymm(date)
|
158
|
+
trans = Tran.month_transactions(date)
|
159
|
+
lines = []
|
160
|
+
trans.each do |t|
|
161
|
+
date = Date.parse(t.post_date)
|
162
|
+
line = {date: date.strftime("%m/%d/%Y"),num:t.num,r:nil,desc:t.description,checking:{db:0,cr:0}}
|
163
|
+
@checking_funds.each do |f|
|
164
|
+
line[f] = {db:0,cr:0}
|
165
|
+
end
|
166
|
+
line[:savings] = {db:0,cr:0}
|
167
|
+
t.splits.each do |s|
|
168
|
+
details = s.details
|
169
|
+
if details[:name].include?("#{@checking_acct}:")
|
170
|
+
line[details[:fund]][:db] += details[:db]
|
171
|
+
line[details[:fund]][:cr] += details[:cr]
|
172
|
+
line[:checking][:db] += details[:db]
|
173
|
+
line[:checking][:cr] += details[:cr]
|
174
|
+
line[:r] = details[:r]
|
175
|
+
elsif details[:name].include?("#{@savings_acct}:")
|
176
|
+
line[:savings][:db] += details[:db]
|
177
|
+
line[:savings][:cr] += details[:cr]
|
178
|
+
line[:r] = details[:r]
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
lines << line
|
183
|
+
end
|
184
|
+
lines
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
class Pdf::Ledger < Prawn::Document
|
2
|
+
attr_accessor :response, :date, :cwidths
|
3
|
+
|
4
|
+
def initialize(date,cash)
|
5
|
+
super( top_margin: 35, page_layout: :landscape)
|
6
|
+
@date = Vfwcash.set_date(date).beginning_of_month
|
7
|
+
@config = cash.config
|
8
|
+
cash.get_fund_balances(@date,@date.end_of_month)
|
9
|
+
@response = cash.month_ledger_api(@date)
|
10
|
+
|
11
|
+
make_pdf
|
12
|
+
number_pages "#{Date.today} - Page <page> of <total>", { :start_count_at => 0, :page_filter => :all, :at => [bounds.right - 100, 0], :align => :right, :size => 6 }
|
13
|
+
end
|
14
|
+
|
15
|
+
def header
|
16
|
+
arr = ["Date", "Num","R", "Description", {content: "+ Checking -",colspan:2, align: :center}]
|
17
|
+
@cwidths = [36, 22,8,108,32,32]
|
18
|
+
@response[:funds][:checking].each do |f|
|
19
|
+
arr << {content:"+ #{f} -",colspan:2, align: :center}
|
20
|
+
@cwidths << 30
|
21
|
+
@cwidths << 30
|
22
|
+
end
|
23
|
+
arr << {content:"+ Savings -",colspan:2, align: :center}
|
24
|
+
@cwidths << 30
|
25
|
+
@cwidths << 30
|
26
|
+
arr
|
27
|
+
end
|
28
|
+
|
29
|
+
def bbalance_row
|
30
|
+
cntnt = "Beginning balance #{@response[:month]}: "
|
31
|
+
cntnt += "Total Current Assets #{money(@response[:balances][:savings][:bbalance] + @response[:balances][:checking][:bbalance])}"
|
32
|
+
|
33
|
+
arr = [{content: cntnt,colspan:4,font_style: :bold}]
|
34
|
+
arr << {content: money(@response[:balances][:checking][:bbalance]),colspan:2, align: :center,font_style: :bold}
|
35
|
+
@response[:funds][:checking].each do |f|
|
36
|
+
arr << { content: money(@response[:balances][:funds][f][:bbalance]),colspan:2, align: :center,font_style: :bold}
|
37
|
+
end
|
38
|
+
arr << {content: money(@response[:balances][:savings][:bbalance]),colspan:2, align: :center,font_style: :bold}
|
39
|
+
arr
|
40
|
+
end
|
41
|
+
|
42
|
+
def ebalance_row
|
43
|
+
cntnt = "Ending balance #{@response[:month]}: "
|
44
|
+
cntnt += "Total Current Assets #{money(@response[:balances][:savings][:ebalance] + @response[:balances][:checking][:ebalance])}"
|
45
|
+
|
46
|
+
arr = [{content: cntnt,colspan:4,font_style: :bold}]
|
47
|
+
arr << {content: money(@response[:balances][:checking][:ebalance]),colspan:2, align: :center,font_style: :bold}
|
48
|
+
@response[:funds][:checking].each do |f|
|
49
|
+
arr << { content: money(@response[:balances][:funds][f][:ebalance]),colspan:2, align: :center,font_style: :bold}
|
50
|
+
end
|
51
|
+
arr << {content: money(@response[:balances][:savings][:ebalance]),colspan:2, align: :center,font_style: :bold}
|
52
|
+
arr
|
53
|
+
end
|
54
|
+
|
55
|
+
def summary_row
|
56
|
+
cntnt = "Debits/Credits Summary #{@response[:month]}: "
|
57
|
+
arr = [{content: cntnt,colspan:4,font_style: :bold}]
|
58
|
+
arr << {content: money(@response[:balances][:checking][:debits]), align: :right}
|
59
|
+
arr << {content: money(@response[:balances][:checking][:credits]), align: :right}
|
60
|
+
@response[:funds][:checking].each do |f|
|
61
|
+
arr << {content: money(@response[:balances][:funds][f][:debits]), align: :right}
|
62
|
+
arr << {content: money(@response[:balances][:funds][f][:credits]), align: :right}
|
63
|
+
end
|
64
|
+
arr << {content: money(@response[:balances][:savings][:debits]), align: :right}
|
65
|
+
arr << {content: money(@response[:balances][:savings][:credits]), align: :right}
|
66
|
+
arr
|
67
|
+
end
|
68
|
+
|
69
|
+
def make_pdf
|
70
|
+
font_size 6
|
71
|
+
build_table
|
72
|
+
draw_table
|
73
|
+
end
|
74
|
+
|
75
|
+
def build_table
|
76
|
+
@rows = [header]
|
77
|
+
@rows << bbalance_row
|
78
|
+
@response[:rows].each do |r|
|
79
|
+
arr = []
|
80
|
+
r.each do |k,v|
|
81
|
+
if v.class == Hash
|
82
|
+
arr << (v[:db].zero? ? nil :{content: (money(v[:db])), align: :right})
|
83
|
+
arr << (v[:cr].zero? ? nil :{content: (money(v[:cr])), align: :right})
|
84
|
+
else
|
85
|
+
arr << v
|
86
|
+
end
|
87
|
+
end
|
88
|
+
@rows << arr
|
89
|
+
end
|
90
|
+
@rows << summary_row
|
91
|
+
@rows << ebalance_row
|
92
|
+
end
|
93
|
+
|
94
|
+
def draw_table
|
95
|
+
text "#{@config[:post][:post]} General Ledger - #{@date}", style: :bold, align: :center
|
96
|
+
move_down(2)
|
97
|
+
e = make_table @rows,row_colors: ["F8F8F8", "FFFFFF"],:cell_style => {:padding => [1, 2, 2, 1],border_color:"E0E0E0"},
|
98
|
+
:column_widths => @cwidths, header:true do
|
99
|
+
|
100
|
+
row(0).font_style = :bold
|
101
|
+
end
|
102
|
+
e.draw
|
103
|
+
end
|
104
|
+
|
105
|
+
def money(int)
|
106
|
+
Vfwcash.money(int)
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
class Pdf::Register < Prawn::Document
|
2
|
+
attr_accessor :response, :date
|
3
|
+
|
4
|
+
def initialize(date,cash)
|
5
|
+
super( top_margin: 35)
|
6
|
+
@date = Vfwcash.set_date(date).beginning_of_month
|
7
|
+
@config = cash.config
|
8
|
+
cash.get_fund_balances(@date,@date.end_of_month)
|
9
|
+
@response = cash.split_ledger_api(@date)
|
10
|
+
make_pdf
|
11
|
+
number_pages "#{Date.today} - Page <page> of <total>", { :start_count_at => 0, :page_filter => :all, :at => [bounds.right - 100, 0], :align => :right, :size => 6 }
|
12
|
+
end
|
13
|
+
|
14
|
+
def header
|
15
|
+
arr = ["Date", "Num","Description","Account","R","Debits","Credits", "Balance"]
|
16
|
+
end
|
17
|
+
|
18
|
+
def balance_row
|
19
|
+
[{content:'',colspan: 2},"Beginning Balance",nil,nil,nil,nil,{content: money(@response[:balances][:checking][:bbalance]),align: :right}]
|
20
|
+
end
|
21
|
+
|
22
|
+
def make_pdf
|
23
|
+
font_size 7
|
24
|
+
build_table
|
25
|
+
draw_table
|
26
|
+
end
|
27
|
+
|
28
|
+
def build_table
|
29
|
+
@rows = [header]
|
30
|
+
@rows << balance_row
|
31
|
+
@response[:rows].each do |row|
|
32
|
+
arr = [row[:date],row[:num],row[:desc],row[:memo],row[:r]]
|
33
|
+
arr << (row[:checking][:db].zero? ? nil : {content: money(row[:checking][:db]), align: :right})
|
34
|
+
arr << (row[:checking][:cr].zero? ? nil : {content: money(row[:checking][:cr]), align: :right})
|
35
|
+
arr << (row[:balance].zero? ? nil : {content: money(row[:balance]), align: :right})
|
36
|
+
@rows << arr
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def draw_table
|
41
|
+
text "#{@config[:post][:post]} Checkbook Register - #{@date}", style: :bold, align: :center
|
42
|
+
move_down(2)
|
43
|
+
e = make_table @rows,row_colors: ["F8F8F8", "FFFFFF"],:cell_style => {:padding => [1, 2, 2, 1],border_color:"E0E0E0"},
|
44
|
+
:column_widths => [40, 24, 150,110,10,40,40,40,40], header:true do
|
45
|
+
row(0).font_style = :bold
|
46
|
+
end
|
47
|
+
e.draw
|
48
|
+
end
|
49
|
+
|
50
|
+
def money(int)
|
51
|
+
Vfwcash.money(int)
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
data/lib/models/split.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
class Split < SqliteBase
|
2
|
+
self.primary_key = 'guid'
|
3
|
+
belongs_to :tran, foreign_key: 'tx_guid'
|
4
|
+
belongs_to :cash_account, foreign_key: 'account_guid'
|
5
|
+
|
6
|
+
def amount
|
7
|
+
return "#{self.value_num / self.value_denom}.#{self.value_num % self.value_denom}"
|
8
|
+
end
|
9
|
+
|
10
|
+
def details
|
11
|
+
acct = self.cash_account
|
12
|
+
fund = acct.name
|
13
|
+
parent = acct.parent
|
14
|
+
acct_name = parent.present? ? "#{parent.name}:#{acct.name}" : acct.name
|
15
|
+
|
16
|
+
amt = self.value_num
|
17
|
+
if amt.to_f < 0
|
18
|
+
credit = amt * -1
|
19
|
+
debit = 0
|
20
|
+
else
|
21
|
+
credit = 0
|
22
|
+
debit = amt
|
23
|
+
end
|
24
|
+
return {fund:fund,name:acct_name,cr:credit,db:debit, memo:self.memo, r:self.reconcile_state}
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
class Pdf::SplitLedger < Prawn::Document
|
2
|
+
attr_accessor :response, :date
|
3
|
+
|
4
|
+
def initialize(date,cash)
|
5
|
+
super( top_margin: 35)
|
6
|
+
@date = Vfwcash.set_date(date).beginning_of_month
|
7
|
+
@config = cash.config
|
8
|
+
cash.get_fund_balances(@date,@date.end_of_month)
|
9
|
+
@response = cash.split_ledger_api(@date)
|
10
|
+
make_pdf
|
11
|
+
number_pages "#{Date.today} - Page <page> of <total>", { :start_count_at => 0, :page_filter => :all, :at => [bounds.right - 100, 0], :align => :right, :size => 6 }
|
12
|
+
end
|
13
|
+
|
14
|
+
def header
|
15
|
+
arr = ["Date", "Num","Description","Account","R","Debits","Credits", "Balance"]
|
16
|
+
end
|
17
|
+
|
18
|
+
def balance_row
|
19
|
+
[{content:'',colspan: 2},"Beginning Balance",nil,nil,nil,nil,{content: money(@response[:balances][:checking][:bbalance]),align: :right}]
|
20
|
+
end
|
21
|
+
|
22
|
+
def make_pdf
|
23
|
+
font_size 7
|
24
|
+
build_table
|
25
|
+
draw_table
|
26
|
+
end
|
27
|
+
|
28
|
+
def build_table
|
29
|
+
@rows = [header]
|
30
|
+
@rows << balance_row
|
31
|
+
@response[:rows].each do |row|
|
32
|
+
arr = [row[:date],row[:num],row[:desc],nil,nil]
|
33
|
+
arr << (row[:checking][:db].zero? ? nil : {content: money(row[:checking][:db]), align: :right})
|
34
|
+
arr << (row[:checking][:cr].zero? ? nil : {content: money(row[:checking][:cr]), align: :right})
|
35
|
+
arr << (row[:balance].zero? ? nil : {content: money(row[:balance]), align: :right})
|
36
|
+
@rows << arr
|
37
|
+
row[:details].each do |d|
|
38
|
+
arr = [{content:'',colspan: 2},d[:memo], d[:name],d[:r],
|
39
|
+
(d[:db].zero? ? nil : {content: money(d[:db]), align: :right}),
|
40
|
+
(d[:cr].zero? ? nil : {content: money(d[:cr]), align: :right}),
|
41
|
+
nil
|
42
|
+
]
|
43
|
+
@rows << arr
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def draw_table
|
49
|
+
text "#{@config[:post][:post]} Split Ledger - #{@date}", style: :bold, align: :center
|
50
|
+
move_down(2)
|
51
|
+
e = make_table @rows,:cell_style => {:padding => [1, 2, 2, 1],border_color:"E0E0E0"},
|
52
|
+
:column_widths => [40, 24, 150,100,10,40,40,40,40], header:true do
|
53
|
+
row(0).font_style = :bold
|
54
|
+
i = row_length - 1
|
55
|
+
0.upto(i) do |j|
|
56
|
+
if cells[j,0].content.blank?
|
57
|
+
row(j).style(:background_color => 'F8F8F8')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
e.draw
|
62
|
+
end
|
63
|
+
|
64
|
+
def money(int)
|
65
|
+
Vfwcash.money(int)
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
class Pdf::Summary < Prawn::Document
|
2
|
+
attr_accessor :cash, :date, :cwidths
|
3
|
+
|
4
|
+
def initialize(cash)
|
5
|
+
super( top_margin: 35, page_layout: :landscape)
|
6
|
+
@cash = cash
|
7
|
+
@cash.get_all_balances
|
8
|
+
@config = @cash.config
|
9
|
+
make_pdf
|
10
|
+
number_pages "#{Date.today} - Page <page> of <total>", { :start_count_at => 0, :page_filter => :all, :at => [bounds.right - 100, 0], :align => :right, :size => 6 }
|
11
|
+
end
|
12
|
+
|
13
|
+
def header
|
14
|
+
arr = ["General Ledger Summary for #{@cash.dates}", {content: "+ Checking -",colspan:2, align: :center}]
|
15
|
+
@cwidths = [160,32,32]
|
16
|
+
@cash.checking_funds.each do |f|
|
17
|
+
arr << {content:"+ #{f} -",colspan:2, align: :center}
|
18
|
+
@cwidths << 30
|
19
|
+
@cwidths << 30
|
20
|
+
end
|
21
|
+
arr << {content:"+ Savings -",colspan:2, align: :center}
|
22
|
+
@cwidths << 30
|
23
|
+
@cwidths << 30
|
24
|
+
arr
|
25
|
+
end
|
26
|
+
|
27
|
+
def bbalance_row(m)
|
28
|
+
tca = @cash.balances[:savings][m][:bbalance] + @cash.balances[:checking][m][:bbalance]
|
29
|
+
cntnt = " #{m} Beginning Balance (Current Assets #{money(tca)} )"
|
30
|
+
arr = [{content: cntnt,font_style: :bold}]
|
31
|
+
arr << {content: money(@cash.balances[:checking][m][:bbalance]),colspan:2, align: :center,font_style: :bold}
|
32
|
+
@cash.checking_funds.each do |f|
|
33
|
+
arr << { content: money(@cash.balances[f][m][:bbalance]),colspan:2, align: :center,font_style: :bold}
|
34
|
+
end
|
35
|
+
arr << {content: money(@cash.balances[:savings][m][:bbalance]),colspan:2, align: :center,font_style: :bold}
|
36
|
+
arr
|
37
|
+
end
|
38
|
+
|
39
|
+
def ebalance_row(m)
|
40
|
+
tca = @cash.balances[:savings][m][:bbalance] + @cash.balances[:checking][m][:bbalance]
|
41
|
+
cntnt = " #{m} Current Balance (Current Assets #{money(tca)} )"
|
42
|
+
arr = [{content: cntnt,font_style: :bold}]
|
43
|
+
arr << {content: money(@cash.balances[:checking][m][:ebalance]),colspan:2, align: :center,font_style: :bold}
|
44
|
+
@cash.checking_funds.each do |f|
|
45
|
+
arr << { content: money(@cash.balances[f][m][:ebalance]),colspan:2, align: :center,font_style: :bold}
|
46
|
+
end
|
47
|
+
arr << {content: money(@cash.balances[:savings][m][:ebalance]),colspan:2, align: :center,font_style: :bold}
|
48
|
+
arr
|
49
|
+
end
|
50
|
+
|
51
|
+
def summary_row(m)
|
52
|
+
pl = @cash.balances[:savings][m][:diff] + @cash.balances[:checking][m][:diff]
|
53
|
+
cntnt = "Total Debits/Credits (Profit/Loss: #{money(pl)})"
|
54
|
+
arr = [{content: cntnt,font_style: :bold}]
|
55
|
+
arr << {content: money(@cash.balances[:checking][m][:debits]), align: :right}
|
56
|
+
arr << {content: money(@cash.balances[:checking][m][:credits]), align: :right}
|
57
|
+
@cash.checking_funds.each do |f|
|
58
|
+
arr << {content: money(@cash.balances[f][m][:debits]), align: :right}
|
59
|
+
arr << {content: money(@cash.balances[f][m][:credits]), align: :right}
|
60
|
+
end
|
61
|
+
arr << {content: money(@cash.balances[:savings][m][:debits]), align: :right}
|
62
|
+
arr << {content: money(@cash.balances[:savings][m][:credits]), align: :right}
|
63
|
+
arr
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
def make_pdf
|
68
|
+
font_size 6
|
69
|
+
build_table
|
70
|
+
draw_table
|
71
|
+
end
|
72
|
+
|
73
|
+
def build_table
|
74
|
+
@rows = [header]
|
75
|
+
@cash.tmonths.each do |m|
|
76
|
+
@rows << bbalance_row(m)
|
77
|
+
@rows << summary_row(m)
|
78
|
+
end
|
79
|
+
m = @cash.tmonths.last
|
80
|
+
@rows << ebalance_row(m)
|
81
|
+
end
|
82
|
+
|
83
|
+
def draw_table
|
84
|
+
text "#{@config[:post][:post]} General Ledger Summary", style: :bold, align: :center
|
85
|
+
move_down(2)
|
86
|
+
e = make_table @rows,row_colors: ["F8F8F8", "FFFFFF"],:cell_style => {:padding => [1, 2, 2, 1],border_color:"E0E0E0"},
|
87
|
+
:column_widths => @cwidths, header:true do
|
88
|
+
|
89
|
+
row(0).font_style = :bold
|
90
|
+
end
|
91
|
+
e.draw
|
92
|
+
end
|
93
|
+
|
94
|
+
def money(int)
|
95
|
+
Vfwcash.money(int)
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
data/lib/models/tran.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
class Tran < SqliteBase
|
2
|
+
self.table_name = "transactions"
|
3
|
+
self.primary_key = 'guid'
|
4
|
+
|
5
|
+
has_many :splits, foreign_key: 'tx_guid'
|
6
|
+
|
7
|
+
def self.month_transactions(date)
|
8
|
+
month = Vfwcash.yyyymm(date)
|
9
|
+
trans = Tran.where('transactions.post_date BETWEEN ? and ?',month+"00",month+"32").order(:post_date,:num)
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
Binary file
|
Binary file
|
@@ -0,0 +1,95 @@
|
|
1
|
+
---
|
2
|
+
# path to you exported or saved sqlite3 GnuCash database
|
3
|
+
:database: "/Users/salex/Work/vfwcash/config/vfwcash.gnucash"
|
4
|
+
# GnuCash parent account names for Checking and Savings accounts
|
5
|
+
:checking_acct: Checking Account
|
6
|
+
:savings_acct: Savings Account
|
7
|
+
# Balance from bank statement and GnuCash on last Bank Balance reconciliation
|
8
|
+
# GnuCash stores all amounts (money) as integers or Pennies in US Dollars
|
9
|
+
# to be consistent, follow that convention in the config file
|
10
|
+
:checking:
|
11
|
+
:balance: 1783700
|
12
|
+
:outstanding: 20000
|
13
|
+
:date:
|
14
|
+
# The rest of the configuration data is used to format the Trustee' Report of Audit
|
15
|
+
:qm:
|
16
|
+
:name: Steven V Quartermaster
|
17
|
+
:address: 405 Somestreet Hls
|
18
|
+
:city: Sometown AL, 35901
|
19
|
+
:post:
|
20
|
+
:name: Some name
|
21
|
+
:post: VFW Post 66666
|
22
|
+
:numb: 66666
|
23
|
+
:address: 817 somestreet Dr
|
24
|
+
:city: Sometown AL, 35901
|
25
|
+
:department: Alabama
|
26
|
+
# Questions and Answers from the operations section
|
27
|
+
:operations:
|
28
|
+
:a:
|
29
|
+
:ques: a. Have required payroll deductions been made?
|
30
|
+
:answ: 'Yes'
|
31
|
+
:b:
|
32
|
+
:ques: b. Have payments been made to the proper State & Federal agencies this
|
33
|
+
quarter?
|
34
|
+
:answ: 'Yes'
|
35
|
+
:c:
|
36
|
+
:ques: c. Have Sales Taxes been collected and paid?
|
37
|
+
:answ: 'Yes'
|
38
|
+
:d:
|
39
|
+
:ques: d. Are Club employees bonded?
|
40
|
+
:answ: 'Yes'
|
41
|
+
:e:
|
42
|
+
:ques: e. Amount of outstanding bills?
|
43
|
+
:answ: 0
|
44
|
+
:f:
|
45
|
+
:ques: f. Value of Real Estate?
|
46
|
+
:answ: 58850000
|
47
|
+
:g:
|
48
|
+
:ques: g. Amount of Liability Insurance?
|
49
|
+
:answ: 30000000
|
50
|
+
:h:
|
51
|
+
:ques: h. Owed on Mortgages and Loans?
|
52
|
+
:answ: 0
|
53
|
+
:i:
|
54
|
+
:ques: i. Value of Personal Property?
|
55
|
+
:answ: 4680000
|
56
|
+
:j:
|
57
|
+
:ques: j. Amount of Property Insurance?
|
58
|
+
:answ: 31350000
|
59
|
+
# Date Audit report signed or submitted
|
60
|
+
:date: '2015-07-14'
|
61
|
+
:bond:
|
62
|
+
:name: Tallman Insurance Agency
|
63
|
+
:amount: 8000000
|
64
|
+
:to: '2016-09-30'
|
65
|
+
# a cross reference to your fund names in GnuCash
|
66
|
+
:funds:
|
67
|
+
1:
|
68
|
+
:fund: Dues
|
69
|
+
:text: 1. National and Department Dues (Per Capitia Tax)
|
70
|
+
2:
|
71
|
+
:fund: Fee
|
72
|
+
:text: 2. Admission or Application Fees (Department)
|
73
|
+
3:
|
74
|
+
:fund: General
|
75
|
+
:text: 3. Post General Fund
|
76
|
+
4:
|
77
|
+
:fund: Relief
|
78
|
+
:text: 4. Post Relief Fund (Poppy Profits, Donations, etc.)
|
79
|
+
5:
|
80
|
+
:fund: Reserve
|
81
|
+
:text: 5. Post Dues Reserve Fund (See Sec. 218, Manual of Procedure)
|
82
|
+
6:
|
83
|
+
:fund: Building
|
84
|
+
:text: 6. Post Home Building Fund (Including Savings but Not Real Estate)
|
85
|
+
7:
|
86
|
+
:fund: Cash
|
87
|
+
:text: 7. Post Canteen or Club Fund
|
88
|
+
8:
|
89
|
+
:fund: Temporary
|
90
|
+
:text: 8. Temporary Fund
|
91
|
+
9:
|
92
|
+
# Savings is not a real fund, but is computed as sum of all funds that are not
|
93
|
+
# a child of 'Checking Account'. The symbol ':savings' is used to access that sum
|
94
|
+
:fund: :savings
|
95
|
+
:text: 9. Bonds and Investments Not Credited to Funds
|