rock_books 0.6.1 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +8 -10
  3. data/RELEASE_NOTES.md +57 -10
  4. data/assets/fonts/JetBrainsMono-Medium.ttf +0 -0
  5. data/lib/rock_books/cmd_line/command_line_interface.rb +15 -24
  6. data/lib/rock_books/cmd_line/main.rb +1 -9
  7. data/lib/rock_books/documents/book_set.rb +5 -2
  8. data/lib/rock_books/documents/chart_of_accounts.rb +29 -12
  9. data/lib/rock_books/documents/journal.rb +3 -8
  10. data/lib/rock_books/documents/journal_entry.rb +7 -2
  11. data/lib/rock_books/documents/journal_entry_builder.rb +4 -0
  12. data/lib/rock_books/helpers/book_set_loader.rb +3 -3
  13. data/lib/rock_books/reports/balance_sheet.rb +9 -43
  14. data/lib/rock_books/reports/book_set_reporter.rb +138 -106
  15. data/lib/rock_books/reports/data/bs_is_data.rb +61 -0
  16. data/lib/rock_books/reports/data/bs_is_section_data.rb +30 -0
  17. data/lib/rock_books/reports/data/journal_data.rb +38 -0
  18. data/lib/rock_books/reports/data/multidoc_txn_by_account_data.rb +40 -0
  19. data/lib/rock_books/reports/data/multidoc_txn_report_data.rb +39 -0
  20. data/lib/rock_books/reports/data/receipts_report_data.rb +47 -0
  21. data/lib/rock_books/reports/data/tx_one_account_data.rb +37 -0
  22. data/lib/rock_books/reports/helpers/erb_helper.rb +21 -0
  23. data/lib/rock_books/reports/helpers/receipts_hyperlink_converter.rb +59 -0
  24. data/lib/rock_books/reports/helpers/text_report_helper.rb +144 -0
  25. data/lib/rock_books/reports/income_statement.rb +9 -47
  26. data/lib/rock_books/reports/index_html_page.rb +27 -0
  27. data/lib/rock_books/reports/journal_report.rb +82 -0
  28. data/lib/rock_books/reports/multidoc_txn_by_account_report.rb +32 -0
  29. data/lib/rock_books/reports/multidoc_txn_report.rb +25 -0
  30. data/lib/rock_books/reports/receipts_report.rb +6 -55
  31. data/lib/rock_books/reports/templates/html/index.html.erb +158 -0
  32. data/lib/rock_books/reports/templates/html/report_page.html.erb +25 -0
  33. data/lib/rock_books/reports/templates/text/_receipt_section.txt.erb +17 -0
  34. data/lib/rock_books/reports/templates/text/_totals.txt.erb +8 -0
  35. data/lib/rock_books/reports/templates/text/balance_sheet.txt.erb +23 -0
  36. data/lib/rock_books/reports/templates/text/income_statement.txt.erb +23 -0
  37. data/lib/rock_books/reports/templates/text/journal.txt.erb +23 -0
  38. data/lib/rock_books/reports/templates/text/multidoc_txn_by_account_report.txt.erb +31 -0
  39. data/lib/rock_books/reports/templates/text/multidoc_txn_report.txt.erb +25 -0
  40. data/lib/rock_books/reports/templates/text/receipts_report.txt.erb +16 -0
  41. data/lib/rock_books/reports/templates/text/tx_one_account.txt.erb +21 -0
  42. data/lib/rock_books/reports/tx_one_account.rb +10 -45
  43. data/lib/rock_books/types/account.rb +13 -1
  44. data/lib/rock_books/types/account_type.rb +18 -7
  45. data/lib/rock_books/version.rb +2 -1
  46. data/manual.md +13 -16
  47. data/rock_books.gemspec +2 -0
  48. metadata +57 -10
  49. data/lib/rock_books/helpers/html_helper.rb +0 -29
  50. data/lib/rock_books/reports/index.html.erb +0 -156
  51. data/lib/rock_books/reports/multidoc_transaction_report.rb +0 -66
  52. data/lib/rock_books/reports/receipts.html.erb +0 -54
  53. data/lib/rock_books/reports/reporter.rb +0 -118
  54. data/lib/rock_books/reports/transaction_report.rb +0 -105
  55. data/lib/rock_books/reports/tx_by_account.rb +0 -82
@@ -1,63 +1,25 @@
1
- require_relative '../documents/journal'
2
- require_relative 'report_context'
1
+ require_relative 'helpers/erb_helper'
2
+ require_relative 'helpers/text_report_helper'
3
3
 
4
4
  module RockBooks
5
5
 
6
6
 
7
7
  class IncomeStatement
8
8
 
9
- include Reporter
9
+ include TextReportHelper
10
+ include ErbHelper
10
11
 
11
- attr_accessor :context
12
+ attr_reader :data, :context
12
13
 
13
14
 
14
- def initialize(report_context)
15
+ def initialize(report_context, data)
15
16
  @context = report_context
17
+ @data = data
16
18
  end
17
19
 
18
20
 
19
- def start_date
20
- context.chart_of_accounts.start_date
21
+ def generate
22
+ ErbHelper.render_hashes('text/income_statement.txt.erb', data, template_presentation_context)
21
23
  end
22
-
23
-
24
- def end_date
25
- context.chart_of_accounts.end_date
26
- end
27
-
28
-
29
- def generate_header
30
- lines = [banner_line]
31
- lines << center(context.entity || 'Unspecified Entity')
32
- lines << "#{center("Income Statement -- #{start_date} to #{end_date}")}"
33
- lines << banner_line
34
- lines << ''
35
- lines << ''
36
- lines << ''
37
- lines.join("\n")
38
- end
39
-
40
-
41
- def generate_report
42
- filter = RockBooks::JournalEntryFilters.date_in_range(start_date, end_date)
43
- acct_amounts = Journal.acct_amounts_in_documents(context.journals, filter)
44
- totals = AcctAmount.aggregate_amounts_by_account(acct_amounts)
45
- totals.each { |aa| aa[1] = -aa[1] } # income statement shows credits as positive, debits as negative
46
- output = generate_header
47
-
48
- income_output, income_total = generate_account_type_section('Income', totals, :income, true)
49
- expense_output, expense_total = generate_account_type_section('Expenses', totals, :expense, false)
50
-
51
- grand_total = income_total - expense_total
52
-
53
- output << [income_output, expense_output].join("\n\n")
54
- output << "\n#{"%12.2f Net Income" % grand_total}\n============\n"
55
- output
56
- end
57
-
58
- alias_method :to_s, :generate_report
59
- alias_method :call, :generate_report
60
-
61
-
62
24
  end
63
25
  end
@@ -0,0 +1,27 @@
1
+ require_relative 'report_context'
2
+
3
+
4
+ module RockBooks
5
+ class IndexHtmlPage
6
+
7
+ include TextReportHelper
8
+
9
+ attr_reader :context, :data
10
+
11
+ def initialize(report_context, metadata, run_options)
12
+ @context = report_context
13
+ @data = {
14
+ metadata: metadata,
15
+ journals: context.journals,
16
+ chart_of_accounts: context.chart_of_accounts,
17
+ run_options: run_options,
18
+ }
19
+ end
20
+
21
+ def generate
22
+ webized_generate_message_lines = template_presentation_context[:generated].split("\n")
23
+ presentation_context = template_presentation_context.merge( { generated: webized_generate_message_lines})
24
+ ErbHelper.render_hashes('html/index.html.erb', data, presentation_context)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,82 @@
1
+ require_relative 'data/journal_data'
2
+ require_relative 'helpers/erb_helper'
3
+ require_relative 'helpers/text_report_helper'
4
+
5
+ module RockBooks
6
+
7
+ class JournalReport
8
+
9
+ include TextReportHelper
10
+ include ErbHelper
11
+
12
+ attr_accessor :context, :report_data
13
+
14
+
15
+ def initialize(report_data, report_context, filter = nil)
16
+ @report_data = report_data
17
+ @context = report_context
18
+ end
19
+
20
+
21
+ def generate
22
+ presentation_context = template_presentation_context.merge(fn_format_entry: method(:format_entry))
23
+ ErbHelper.render_hashes('text/journal.txt.erb', report_data, presentation_context)
24
+ end
25
+
26
+
27
+ private def format_date_and_account_amount(date, acct_amount)
28
+ "#{date} #{format_acct_amount(acct_amount)}\n"
29
+ end
30
+
31
+
32
+ private def format_entry_first_acct_amount(entry)
33
+ format_date_and_account_amount(entry.date, entry.acct_amounts.first)
34
+ end
35
+
36
+
37
+ private def format_entry_last_acct_amount(entry)
38
+ format_date_and_account_amount(entry.date, entry.acct_amounts.last)
39
+ end
40
+
41
+
42
+ # Formats an entry like this, with entry description added on additional line(s) if it exists:
43
+ # 2018-05-21 $120.00 701 Office Supplies
44
+ private def format_entry_no_split(entry)
45
+ output = format_entry_last_acct_amount(entry)
46
+
47
+ if entry.description && entry.description.length > 0
48
+ output += entry.description
49
+ end
50
+ output
51
+ end
52
+
53
+
54
+ # Formats an entry like this, with entry description added on additional line(s) if it exists::
55
+ # 2018-05-21 $120.00 95.00 701 Office Supplies
56
+ # 25.00 751 Gift to Customer
57
+ private def format_entry_with_split(entry)
58
+ output = StringIO.new
59
+ output << format_entry_first_acct_amount(entry)
60
+ indent = ' ' * 12
61
+
62
+ entry.acct_amounts[1..-1].each do |acct_amount|
63
+ output << indent << format_acct_amount(acct_amount) << "\n"
64
+ end
65
+
66
+ if entry.description && entry.description.length > 0
67
+ output << entry.description
68
+ end
69
+
70
+ output.string
71
+ end
72
+
73
+
74
+ private def format_entry(entry)
75
+ if entry.acct_amounts.size > 2
76
+ format_entry_with_split(entry)
77
+ else
78
+ format_entry_no_split(entry)
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,32 @@
1
+ require_relative '../documents/chart_of_accounts'
2
+ require_relative 'helpers/erb_helper'
3
+ require_relative 'helpers/text_report_helper'
4
+ require_relative 'report_context'
5
+ require_relative 'data/multidoc_txn_by_account_data'
6
+
7
+ module RockBooks
8
+
9
+ class MultidocTransactionByAccountReport
10
+
11
+ include TextReportHelper
12
+ include ErbHelper
13
+
14
+ attr_reader :context, :data
15
+
16
+
17
+ def initialize(data, report_context)
18
+ @data = data
19
+ @context = report_context
20
+ end
21
+
22
+ def account_total_line(account_code, account_total)
23
+ account_name = context.chart_of_accounts.name_for_code(account_code)
24
+ sprintf("%.2f Total for account: %s - %s", account_total, account_code, account_name)
25
+ end
26
+
27
+ def generate
28
+ presentation_context = template_presentation_context.merge({ fn_account_total_line: method(:account_total_line) })
29
+ ErbHelper.render_hashes('text/multidoc_txn_by_account_report.txt.erb', data, presentation_context)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,25 @@
1
+ require_relative 'data/multidoc_txn_report_data'
2
+ require_relative '../documents/journal'
3
+ require_relative 'helpers/erb_helper'
4
+ require_relative 'helpers/text_report_helper'
5
+ require_relative 'report_context'
6
+
7
+ module RockBooks
8
+
9
+ class MultidocTransactionReport
10
+
11
+ include TextReportHelper
12
+ include ErbHelper
13
+
14
+ attr_reader :context, :data
15
+
16
+ def initialize(report_data, report_context)
17
+ @data = report_data
18
+ @context = report_context
19
+ end
20
+
21
+ def generate
22
+ ErbHelper.render_hashes('text/multidoc_txn_report.txt.erb', data, template_presentation_context)
23
+ end
24
+ end
25
+ end
@@ -4,67 +4,18 @@ require_relative 'report_context'
4
4
  module RockBooks
5
5
  class ReceiptsReport
6
6
 
7
- include Reporter
7
+ include TextReportHelper
8
8
 
9
- attr_reader :context, :missing, :existing, :unused
9
+ attr_reader :context, :data
10
10
 
11
-
12
- def initialize(report_context, missing, existing, unused)
11
+ def initialize(report_context, data)
13
12
  @context = report_context
14
- @missing = missing
15
- @existing = existing
16
- @unused = unused
17
- end
18
-
19
-
20
- def generate_header
21
- lines = [banner_line]
22
- lines << center(context.entity || 'Unspecified Entity')
23
- lines << "#{center("Receipts Report")}"
24
- lines << banner_line
25
- lines.join("\n")
26
- end
27
-
28
-
29
- def receipt_info_line(info)
30
- "%-16.16s %s\n" % [info[:journal], info[:receipt]]
31
- end
32
-
33
-
34
- def column_headings
35
- format_string = "%-16.16s %s\n"
36
- (format_string % ['Journal', 'Receipt Filespec']) << (format_string % %w(------- ----------------)) << "\n"
37
- end
38
-
39
-
40
- def report_one_section(name, list)
41
- output = ''
42
- output << "\n\n\n#{name} Receipts:\n\n" << column_headings
43
- if list.empty?
44
- output << "[None]\n\n\n"
45
- else
46
- list.each { |receipt| output << receipt_info_line(receipt) }
47
- end
48
- output
13
+ @data = data
49
14
  end
50
15
 
51
16
 
52
- def generate_report
53
- output = generate_header
54
- output << report_one_section('Missing', missing)
55
-
56
- output << "\n\n\nUnused Receipts:\n\n"
57
- if unused.empty?
58
- output << "[None]\n\n\n"
59
- else
60
- unused.each { |filespec| output << filespec << "\n" }
61
- end
62
-
63
- output << report_one_section('Existing', existing)
64
- output
17
+ def generate
18
+ ErbHelper.render_hashes('text/receipts_report.txt.erb', data, template_presentation_context)
65
19
  end
66
-
67
- alias_method :to_s, :generate_report
68
- alias_method :call, :generate_report
69
20
  end
70
21
  end
@@ -0,0 +1,158 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <!-- <%= metadata %> -->
4
+ <head>
5
+
6
+ <meta charset="utf-8">
7
+
8
+ <!--Bootstrap:-->
9
+ <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
10
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
11
+ <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>
12
+
13
+ <style>
14
+ body {
15
+ padding: 36px;
16
+ background-color: #88c1f7;
17
+ color: #01182d;
18
+ max-width: 1024px;
19
+ float: none !important;
20
+ margin: 0 auto !important;
21
+ }
22
+
23
+ .top_heading {
24
+ text-align: center;
25
+ }
26
+
27
+ h2 {
28
+ margin-top: 32px;
29
+ margin-bottom: 12px;
30
+ }
31
+
32
+ .this_page_style {
33
+ background-color: #88c1f7;
34
+ color: #01182d;
35
+ border: 0px;
36
+ }
37
+ </style>
38
+ </head>
39
+
40
+ <body>
41
+
42
+ <h1 class="top_heading"><%= entity %></h1>
43
+ <h1 class="top_heading">Financial Statements, Reports, and Source Data</h1>
44
+ <h1 class="top_heading"><%= accounting_period %></h1>
45
+ <br />
46
+ <br />
47
+ <h4 class="top_heading"><%= generated[0] %></h4>
48
+ <h4 class="top_heading"><%= generated[1] %> (<a href="https://github.com/keithrbennett/rock_books">https://github.com/keithrbennett/rock_books</a>)</h4>
49
+ <h4 class="top_heading">Open Source Software Provided by <a href="https://www.bbs-software.com/">Bennett Business Solutions, Inc.</a></h4>
50
+ <br />
51
+ <br />
52
+
53
+ <h2>Financial Statements</h2>
54
+ <div id="financial-statements">
55
+ <a href='balance_sheet.html' class="btn btn-primary">Balance Sheet</a>
56
+ <a href='income_statement.html' class="btn btn-primary">Income Statement</a>
57
+ </div>
58
+
59
+
60
+ <h2>Supporting Documents</h2>
61
+ <div id="supporting-documents" style="display: inline ">
62
+ <%
63
+ subdir_link = ->(name, caption) do
64
+ link_dir_name = File.join('..', '..', name)
65
+ test_dir_name = name
66
+ if Dir.exist?(test_dir_name)
67
+ %Q{<a href=#{link_dir_name} class="btn btn-primary">#{caption}</a>}
68
+ end
69
+ end
70
+ %>
71
+ <%= subdir_link.('invoices', 'Invoices') %>
72
+ <%= subdir_link.('receipts', 'Receipts') %>
73
+ <%= subdir_link.('statements', 'Statements') %>
74
+ <%= subdir_link.('worksheets', 'Worksheets') %>
75
+ </div>
76
+
77
+
78
+ <h2>All Transactions Reports</h2>
79
+ <div id="all-transactions">
80
+ <a href="all_txns_by_acct.html" class="btn btn-primary">By Account</a>
81
+ <a href="all_txns_by_amount.html" class="btn btn-primary">By Amount</a>
82
+ <a href="all_txns_by_date.html" class="btn btn-primary">By Date</a>
83
+ </div>
84
+
85
+ <% collapsible_heading = ->(caption, href) do %Q{
86
+ <br /><br />
87
+ <div class="collapsible-heading">
88
+ <div class="container-fluid">
89
+ <div class="row">
90
+
91
+ <div class="col-sm2" style="margin-right: 12px;">
92
+ <a class="btn btn-primary" data-toggle="collapse" href="#{href}" role="button" aria-expanded="false" aria-controls="collapseExample">
93
+ +/-
94
+ </a>
95
+ </div>
96
+
97
+ <div class="col-sm10">
98
+ <h2 style="margin: 0px;">#{caption}</h2>
99
+ </div>
100
+ </div>
101
+ </div>
102
+ </div>
103
+ } end %>
104
+
105
+ <%= collapsible_heading.('Journal Reports', '#journal-reports') %>
106
+
107
+ <div class="collapse" id="journal-reports">
108
+ <div class="card card-body this_page_style">
109
+ <ul>
110
+ <% journals.each do |journal|
111
+ filespec = journal.short_name + '.html' %>
112
+ <li><a href="<%= filespec %>" class="this_page_style"><%= journal.title %></a></li>
113
+ <% end %>
114
+ </ul>
115
+ </div>
116
+ </div>
117
+
118
+ <%= collapsible_heading.('Individual Accounts', '#individual-accounts') %>
119
+
120
+ <div class="collapse" id="individual-accounts">
121
+ <div class="card card-body this_page_style">
122
+ <ul>
123
+ <%
124
+ chart_of_accounts.accounts.each do |account|
125
+ filespec = File.join('single-account', "acct_#{account.code}.html")
126
+ caption = "#{account.name} (#{account.code})"
127
+ %>
128
+ <li><a href="<%= filespec %>" class="this_page_style"><%= caption %></a></li>
129
+ <% end %>
130
+ </ul>
131
+ </div>
132
+ </div>
133
+
134
+ <%= collapsible_heading.('Other', '#other') %>
135
+
136
+ <div class="collapse" id="other">
137
+ <div class="card card-body this_page_style">
138
+ <ul>
139
+ <% if run_options.do_receipts %>
140
+ <li><a href="receipts.html" class="this_page_style">Missing and Existing Receipts</a></li>
141
+ <% end %>
142
+ </ul>
143
+ </div>
144
+ </div>
145
+
146
+ <%= collapsible_heading.('Reports in PDF and Text Formats', '#other-formats') %>
147
+
148
+ <div class="collapse" id="other-formats">
149
+ <div class="card card-body this_page_style">
150
+ <ul>
151
+ <li><a href="../pdf" class="this_page_style">PDF Format</a></li>
152
+ <li><a href="../txt" class="this_page_style">Text Format</a></li>
153
+ </ul>
154
+ </div>
155
+ </div>
156
+
157
+ </body>
158
+ </html>