rock_books 0.6.1 → 0.10.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 (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>