rock_books 0.1.2 → 0.1.3

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 (218) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +1 -0
  3. data/README.md +3 -13
  4. data/RELEASE_NOTES.md +15 -1
  5. data/lib/rock_books/cmd_line/command_line_interface.rb +19 -9
  6. data/lib/rock_books/cmd_line/main.rb +9 -2
  7. data/lib/rock_books/documents/book_set.rb +20 -5
  8. data/lib/rock_books/documents/chart_of_accounts.rb +19 -4
  9. data/lib/rock_books/documents/journal.rb +29 -7
  10. data/lib/rock_books/documents/journal_entry_builder.rb +23 -14
  11. data/lib/rock_books/errors/account_not_found_error.rb +9 -8
  12. data/lib/rock_books/errors/incorrect_sequence_error.rb +21 -0
  13. data/lib/rock_books/errors/transaction_not_balanced_error.rb +21 -0
  14. data/lib/rock_books/filters/journal_entry_filters.rb +6 -1
  15. data/lib/rock_books/helpers/book_set_loader.rb +2 -2
  16. data/lib/rock_books/helpers/parse_helper.rb +1 -1
  17. data/lib/rock_books/reports/tx_by_account.rb +1 -1
  18. data/lib/rock_books/reports/tx_one_account.rb +1 -1
  19. data/lib/rock_books/types/acct_amount.rb +4 -4
  20. data/lib/rock_books/types/journal_entry_context.rb +14 -0
  21. data/lib/rock_books/version.rb +1 -1
  22. data/sample_data/minimal/rockbooks-inputs/{2017-xyz-chart-of-accounts.rbt → 2017-xyz-chart-of-accounts.txt} +62 -62
  23. data/sample_data/minimal/rockbooks-inputs/{2017-xyz-checking-journal.rbt → 2017-xyz-checking-journal.txt} +17 -17
  24. data/sample_data/minimal/rockbooks-inputs/{2017-xyz-general-journal.rbt → 2017-xyz-general-journal.txt} +14 -14
  25. data/sample_data/minimal/rockbooks-inputs/{2017-xyz-visa-journal.rbt → 2017-xyz-visa-journal.txt} +27 -23
  26. data/sample_data/minimal/rockbooks-reports/{all_txns_by_acct.html → html/all_txns_by_acct.html} +63 -51
  27. data/sample_data/minimal/rockbooks-reports/{all_txns_by_amount.html → html/all_txns_by_amount.html} +13 -8
  28. data/sample_data/minimal/rockbooks-reports/{all_txns_by_date.html → html/all_txns_by_date.html} +13 -8
  29. data/sample_data/minimal/rockbooks-reports/{balance_sheet.html → html/balance_sheet.html} +6 -6
  30. data/sample_data/minimal/rockbooks-reports/{ck.hsbc.html → html/ck.hsbc.disb.html} +2 -2
  31. data/sample_data/minimal/rockbooks-reports/{general.html → html/general.html} +2 -2
  32. data/sample_data/minimal/rockbooks-reports/{hsbc_visa.html → html/hsbc_visa.html} +8 -4
  33. data/sample_data/minimal/rockbooks-reports/{income_statement.html → html/income_statement.html} +5 -5
  34. data/sample_data/minimal/rockbooks-reports/{receipts.html → html/receipts.html} +3 -2
  35. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_accts.rec.html +2 -2
  36. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_bank.fees.html +2 -2
  37. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_books.refs.html +2 -2
  38. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_cc.hsbc.visa.html +12 -6
  39. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_cc.proc.html +2 -2
  40. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_ck.hsbc.html +5 -5
  41. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_conf.fees.html +2 -2
  42. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_cowork.fees.html +11 -5
  43. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_govt.fees.html +2 -2
  44. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_inet.fees.html +2 -2
  45. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_insurance.html +2 -2
  46. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_int.exp.html +2 -2
  47. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_loan.to.sh.html +2 -2
  48. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_meals.ent.html +2 -2
  49. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_misc.exp.html +2 -2
  50. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_mktng.exp.html +2 -2
  51. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_own.equity.html +3 -3
  52. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_paypal.html +2 -2
  53. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_prof.fees.html +2 -2
  54. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_repair.maint.html +2 -2
  55. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_ret.earn.html +2 -2
  56. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_ship.exp.html +2 -2
  57. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_sls.cons.html +3 -3
  58. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_supplies.html +2 -2
  59. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_sw.exp.html +2 -2
  60. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_tr.airfare.html +2 -2
  61. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_tr.autorent.html +2 -2
  62. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_tr.gas.etc.html +2 -2
  63. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_tr.govt.html +2 -2
  64. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_tr.lodging.html +2 -2
  65. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_tr.m.e.html +2 -2
  66. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_tr.m.i.html +2 -2
  67. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_tr.mileage.html +2 -2
  68. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_tr.misc.html +2 -2
  69. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_tr.parking.html +2 -2
  70. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_tr.perdiem.mi.html +2 -2
  71. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_tr.taxi.html +2 -2
  72. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_tr.trainfare.html +2 -2
  73. data/sample_data/minimal/rockbooks-reports/{single-account → html/single-account}/acct_tr.unclass.html +2 -2
  74. data/sample_data/minimal/rockbooks-reports/pdf/all_txns_by_acct.pdf +0 -0
  75. data/sample_data/minimal/rockbooks-reports/pdf/all_txns_by_amount.pdf +0 -0
  76. data/sample_data/minimal/rockbooks-reports/pdf/all_txns_by_date.pdf +0 -0
  77. data/sample_data/minimal/rockbooks-reports/pdf/balance_sheet.pdf +0 -0
  78. data/sample_data/minimal/rockbooks-reports/pdf/ck.hsbc.disb.pdf +0 -0
  79. data/sample_data/minimal/rockbooks-reports/pdf/general.pdf +0 -0
  80. data/sample_data/minimal/rockbooks-reports/pdf/hsbc_visa.pdf +0 -0
  81. data/sample_data/minimal/rockbooks-reports/pdf/income_statement.pdf +0 -0
  82. data/sample_data/minimal/rockbooks-reports/pdf/receipts.pdf +0 -0
  83. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_accts.rec.pdf +0 -0
  84. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_bank.fees.pdf +0 -0
  85. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_books.refs.pdf +0 -0
  86. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_cc.hsbc.visa.pdf +0 -0
  87. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_cc.proc.pdf +0 -0
  88. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_ck.hsbc.pdf +0 -0
  89. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_conf.fees.pdf +0 -0
  90. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_cowork.fees.pdf +0 -0
  91. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_govt.fees.pdf +0 -0
  92. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_inet.fees.pdf +0 -0
  93. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_insurance.pdf +0 -0
  94. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_int.exp.pdf +0 -0
  95. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_loan.to.sh.pdf +0 -0
  96. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_meals.ent.pdf +0 -0
  97. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_misc.exp.pdf +0 -0
  98. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_mktng.exp.pdf +0 -0
  99. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_own.equity.pdf +0 -0
  100. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_paypal.pdf +0 -0
  101. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_prof.fees.pdf +0 -0
  102. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_repair.maint.pdf +0 -0
  103. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_ret.earn.pdf +0 -0
  104. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_ship.exp.pdf +0 -0
  105. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_sls.cons.pdf +0 -0
  106. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_supplies.pdf +0 -0
  107. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_sw.exp.pdf +0 -0
  108. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_tr.airfare.pdf +0 -0
  109. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_tr.autorent.pdf +0 -0
  110. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_tr.gas.etc.pdf +0 -0
  111. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_tr.govt.pdf +0 -0
  112. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_tr.lodging.pdf +0 -0
  113. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_tr.m.e.pdf +0 -0
  114. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_tr.m.i.pdf +0 -0
  115. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_tr.mileage.pdf +0 -0
  116. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_tr.misc.pdf +0 -0
  117. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_tr.parking.pdf +0 -0
  118. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_tr.perdiem.mi.pdf +0 -0
  119. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_tr.taxi.pdf +0 -0
  120. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_tr.trainfare.pdf +0 -0
  121. data/sample_data/minimal/rockbooks-reports/pdf/single-account/acct_tr.unclass.pdf +0 -0
  122. data/sample_data/minimal/rockbooks-reports/{all_txns_by_acct.txt → txt/all_txns_by_acct.txt} +61 -49
  123. data/sample_data/minimal/rockbooks-reports/{all_txns_by_amount.txt → txt/all_txns_by_amount.txt} +11 -6
  124. data/sample_data/minimal/rockbooks-reports/{all_txns_by_date.txt → txt/all_txns_by_date.txt} +11 -6
  125. data/sample_data/minimal/rockbooks-reports/{balance_sheet.txt → txt/balance_sheet.txt} +4 -4
  126. data/sample_data/minimal/rockbooks-reports/{ck.hsbc.txt → txt/ck.hsbc.disb.txt} +0 -0
  127. data/sample_data/minimal/rockbooks-reports/{general.txt → txt/general.txt} +0 -0
  128. data/sample_data/minimal/rockbooks-reports/{hsbc_visa.txt → txt/hsbc_visa.txt} +6 -2
  129. data/sample_data/minimal/rockbooks-reports/{income_statement.txt → txt/income_statement.txt} +3 -3
  130. data/sample_data/minimal/rockbooks-reports/{receipts.txt → txt/receipts.txt} +1 -0
  131. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_accts.rec.txt +0 -0
  132. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_bank.fees.txt +0 -0
  133. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_books.refs.txt +0 -0
  134. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_cc.hsbc.visa.txt +10 -4
  135. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_cc.proc.txt +0 -0
  136. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_ck.hsbc.txt +3 -3
  137. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_conf.fees.txt +0 -0
  138. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_cowork.fees.txt +9 -3
  139. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_govt.fees.txt +0 -0
  140. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_inet.fees.txt +0 -0
  141. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_insurance.txt +0 -0
  142. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_int.exp.txt +0 -0
  143. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_loan.to.sh.txt +0 -0
  144. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_meals.ent.txt +0 -0
  145. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_misc.exp.txt +0 -0
  146. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_mktng.exp.txt +0 -0
  147. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_own.equity.txt +1 -1
  148. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_paypal.txt +0 -0
  149. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_prof.fees.txt +0 -0
  150. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_repair.maint.txt +0 -0
  151. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_ret.earn.txt +0 -0
  152. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_ship.exp.txt +0 -0
  153. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_sls.cons.txt +1 -1
  154. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_supplies.txt +0 -0
  155. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_sw.exp.txt +0 -0
  156. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_tr.airfare.txt +0 -0
  157. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_tr.autorent.txt +0 -0
  158. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_tr.gas.etc.txt +0 -0
  159. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_tr.govt.txt +0 -0
  160. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_tr.lodging.txt +0 -0
  161. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_tr.m.e.txt +0 -0
  162. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_tr.m.i.txt +0 -0
  163. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_tr.mileage.txt +0 -0
  164. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_tr.misc.txt +0 -0
  165. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_tr.parking.txt +0 -0
  166. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_tr.perdiem.mi.txt +0 -0
  167. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_tr.taxi.txt +0 -0
  168. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_tr.trainfare.txt +0 -0
  169. data/sample_data/minimal/rockbooks-reports/{single-account → txt/single-account}/acct_tr.unclass.txt +0 -0
  170. metadata +155 -151
  171. data/sample_data/minimal/rockbooks-reports/all_txns_by_acct.pdf +0 -0
  172. data/sample_data/minimal/rockbooks-reports/all_txns_by_amount.pdf +0 -0
  173. data/sample_data/minimal/rockbooks-reports/all_txns_by_date.pdf +0 -0
  174. data/sample_data/minimal/rockbooks-reports/balance_sheet.pdf +0 -0
  175. data/sample_data/minimal/rockbooks-reports/ck.hsbc.pdf +0 -0
  176. data/sample_data/minimal/rockbooks-reports/general.pdf +0 -0
  177. data/sample_data/minimal/rockbooks-reports/hsbc_visa.pdf +0 -0
  178. data/sample_data/minimal/rockbooks-reports/income_statement.pdf +0 -0
  179. data/sample_data/minimal/rockbooks-reports/receipts.pdf +0 -0
  180. data/sample_data/minimal/rockbooks-reports/single-account/acct_accts.rec.pdf +0 -0
  181. data/sample_data/minimal/rockbooks-reports/single-account/acct_bank.fees.pdf +0 -0
  182. data/sample_data/minimal/rockbooks-reports/single-account/acct_books.refs.pdf +0 -0
  183. data/sample_data/minimal/rockbooks-reports/single-account/acct_cc.hsbc.visa.pdf +0 -0
  184. data/sample_data/minimal/rockbooks-reports/single-account/acct_cc.proc.pdf +0 -0
  185. data/sample_data/minimal/rockbooks-reports/single-account/acct_ck.hsbc.pdf +0 -0
  186. data/sample_data/minimal/rockbooks-reports/single-account/acct_conf.fees.pdf +0 -0
  187. data/sample_data/minimal/rockbooks-reports/single-account/acct_cowork.fees.pdf +0 -0
  188. data/sample_data/minimal/rockbooks-reports/single-account/acct_govt.fees.pdf +0 -0
  189. data/sample_data/minimal/rockbooks-reports/single-account/acct_inet.fees.pdf +0 -0
  190. data/sample_data/minimal/rockbooks-reports/single-account/acct_insurance.pdf +0 -0
  191. data/sample_data/minimal/rockbooks-reports/single-account/acct_int.exp.pdf +0 -0
  192. data/sample_data/minimal/rockbooks-reports/single-account/acct_loan.to.sh.pdf +0 -0
  193. data/sample_data/minimal/rockbooks-reports/single-account/acct_meals.ent.pdf +0 -0
  194. data/sample_data/minimal/rockbooks-reports/single-account/acct_misc.exp.pdf +0 -0
  195. data/sample_data/minimal/rockbooks-reports/single-account/acct_mktng.exp.pdf +0 -0
  196. data/sample_data/minimal/rockbooks-reports/single-account/acct_own.equity.pdf +0 -0
  197. data/sample_data/minimal/rockbooks-reports/single-account/acct_paypal.pdf +0 -0
  198. data/sample_data/minimal/rockbooks-reports/single-account/acct_prof.fees.pdf +0 -0
  199. data/sample_data/minimal/rockbooks-reports/single-account/acct_repair.maint.pdf +0 -0
  200. data/sample_data/minimal/rockbooks-reports/single-account/acct_ret.earn.pdf +0 -0
  201. data/sample_data/minimal/rockbooks-reports/single-account/acct_ship.exp.pdf +0 -0
  202. data/sample_data/minimal/rockbooks-reports/single-account/acct_sls.cons.pdf +0 -0
  203. data/sample_data/minimal/rockbooks-reports/single-account/acct_supplies.pdf +0 -0
  204. data/sample_data/minimal/rockbooks-reports/single-account/acct_sw.exp.pdf +0 -0
  205. data/sample_data/minimal/rockbooks-reports/single-account/acct_tr.airfare.pdf +0 -0
  206. data/sample_data/minimal/rockbooks-reports/single-account/acct_tr.autorent.pdf +0 -0
  207. data/sample_data/minimal/rockbooks-reports/single-account/acct_tr.gas.etc.pdf +0 -0
  208. data/sample_data/minimal/rockbooks-reports/single-account/acct_tr.govt.pdf +0 -0
  209. data/sample_data/minimal/rockbooks-reports/single-account/acct_tr.lodging.pdf +0 -0
  210. data/sample_data/minimal/rockbooks-reports/single-account/acct_tr.m.e.pdf +0 -0
  211. data/sample_data/minimal/rockbooks-reports/single-account/acct_tr.m.i.pdf +0 -0
  212. data/sample_data/minimal/rockbooks-reports/single-account/acct_tr.mileage.pdf +0 -0
  213. data/sample_data/minimal/rockbooks-reports/single-account/acct_tr.misc.pdf +0 -0
  214. data/sample_data/minimal/rockbooks-reports/single-account/acct_tr.parking.pdf +0 -0
  215. data/sample_data/minimal/rockbooks-reports/single-account/acct_tr.perdiem.mi.pdf +0 -0
  216. data/sample_data/minimal/rockbooks-reports/single-account/acct_tr.taxi.pdf +0 -0
  217. data/sample_data/minimal/rockbooks-reports/single-account/acct_tr.trainfare.pdf +0 -0
  218. data/sample_data/minimal/rockbooks-reports/single-account/acct_tr.unclass.pdf +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cb5e28caf47f966b9793cef3f45eafde78895029034d25256864c1035f16e3a5
4
- data.tar.gz: 3c5c3d288454789332a4395c57ee362d933e5d141294a22951ef38401556606a
3
+ metadata.gz: 748869c04031f76ba911a05c45f954290f0d364c5cb4cd08c725238398542075
4
+ data.tar.gz: a926e2ec2498a2312b5e765ac8511f8f62ffbbcafc016c03752b4c1934cf4eb8
5
5
  SHA512:
6
- metadata.gz: f8e890585583e9331567371567cd483ea9ac4d8a11999bfaf443094fd896e04343ef2cbbdddf26a1a823cf98301254d9c1a66338a53abab8fd3a4c322066919d
7
- data.tar.gz: 39d6ed81e515fc38db7f8b116388cb8e0cf5025e8f2d9adcc307cb0fb03e4bdc6dc40b0477d6adab6857753c7418dcf9c32967dc1fac63d541ae4a92157b602f
6
+ metadata.gz: 40f17cf379eddd8a675c2aa427f4faf32471e6d95252a5f77a12727f0949efc5e46947cc9e11a08e0d7d00d4cbb1a42f6219d0b4a880c0fcdba53eccf736d47c
7
+ data.tar.gz: 47eaf0e7d59c26efe53718a965cd09bfd00ba72385e634a3928d096a6909be67354a474e1cb927aa4b57fe1f7f77a0f82794682b755c30f073c7dc7d8f1b4f66
data/.gitattributes ADDED
@@ -0,0 +1 @@
1
+ sample_data/minimal/rockbooks-reports/* linguist-vendored
data/README.md CHANGED
@@ -19,8 +19,7 @@ the double entry bookkeeping paradigm pretty well.
19
19
  * document - a RockBooks logical document such as a chart of accounts, a journal, etc.,
20
20
  usually containing information parsed from a data file
21
21
 
22
- * data file - a RockBooks data file, which is a text file, which
23
- by convention has the extension `.rbt`
22
+ * data file - a RockBooks data file, which is a text file with the extension `.txt`
24
23
 
25
24
 
26
25
  ## Data File Format
@@ -181,19 +180,10 @@ Or install it yourself as:
181
180
 
182
181
  $ gem install rock_books
183
182
 
184
- ## Usage
185
-
186
- TODO: Write usage instructions here
187
-
188
- ## Development
189
-
190
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
191
-
192
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
193
-
194
183
  ## Contributing
195
184
 
196
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/rock_books.
185
+ Bug reports and pull requests are welcome on GitHub at [https://github.com/keithrbennett/rock_books](https://github.com/keithrbennett/rock_books).
186
+
197
187
 
198
188
  ## License
199
189
 
data/RELEASE_NOTES.md CHANGED
@@ -1,6 +1,20 @@
1
+ ## v0.1.3
2
+
3
+ * Report output now goes to separate txt, html, and pdf subdirectories.
4
+ * Add vendor.yml to exclude generated report files from language reporting.
5
+ * Use .gitattributes instead of vendor.yml to specify vendored code.
6
+ * Add == methods to ChartOfAccounts and Journal classes.
7
+ * Rename input files from .rbt to .txt.
8
+ * Convert sample input files to DOS line endings.
9
+ * Add validation that transaction is balanced.
10
+ * Fix so that requesting help shows correct help text, and that passing no args on cmd line triggers help.
11
+ * Implement more helpful error messages, with document short name, line number, and line text.
12
+ * Add JournalEntryContext and TransactionNotBalancedError classes.
13
+ * Add 'from_string' methods to Journal and ChartOfAccounts.
14
+
1
15
  ## v0.1.2
2
16
 
3
- Improve error emssage when the needed directories do not exist.
17
+ * Improve error message when the needed directories do not exist.
4
18
 
5
19
  ## v0.1.1
6
20
 
@@ -24,7 +24,7 @@ class CommandLineInterface
24
24
  class BadCommandError < RuntimeError; end
25
25
 
26
26
 
27
- # Enable use of some BookSet methods in shell with long and short names aaa, ae:
27
+ # Enable use of some BookSet methods in shell with long and short aliases:
28
28
 
29
29
  def_delegator :book_set, :all_acct_amounts
30
30
  def_delegator :book_set, :all_acct_amounts, :aaa
@@ -56,6 +56,7 @@ w[rite_reports] - write all reports to the output directory (see -o op
56
56
  c[hart_of_accounts] - chart of accounts
57
57
  h[elp] - prints this help
58
58
  jo[urnals] - list of the journals' short names
59
+ proj[ect_page] - open the RockBooks Github project page in a browser
59
60
  rel[oad_data] - reload data from input files
60
61
  q[uit] - exits this program (interactive shell mode only) (see also 'x')
61
62
  x[it] - exits this program (interactive shell mode only) (see also 'q')
@@ -79,18 +80,22 @@ When in interactive shell mode:
79
80
 
80
81
  def validate_run_options(options)
81
82
 
83
+ return if options.suppress_command_line_validation
84
+
82
85
  validate_input_dir = -> do
83
86
  File.directory?(options.input_dir) ? nil : "Input directory '#{options.input_dir}' does not exist. "
84
87
  end
85
88
 
86
89
  validate_output_dir = -> do
87
- dir = options.output_dir
88
- subdir = File.join(dir, SINGLE_ACCT_SUBDIR)
89
90
 
90
- # We need to create the reports directory and its single-account subdirectory.
91
- # We can accomplish both by creating just the subdirectory.
92
- FileUtils.mkdir_p(subdir) ? nil : \
93
- "Output directory '#{dir}' and/or #{subdir} does not exist and could not be created. "
91
+ # We need to create the reports directory if it does not already exist.
92
+ # mkdir_p silently returns if the directory already exists.
93
+ begin
94
+ FileUtils.mkdir_p(options.output_dir)
95
+ nil
96
+ rescue Errno::EACCES => error
97
+ "Output directory '#{options.output_dir}' does not exist and could not be created. "
98
+ end
94
99
  end
95
100
 
96
101
  validate_receipts_dir = -> do
@@ -273,9 +278,14 @@ When in interactive shell mode:
273
278
  end
274
279
 
275
280
  os = OpenStruct.new(book_set.all_reports($filter))
276
- def os.keys; to_h.keys.map(&:to_s); end # add hash methods for convenience
281
+
282
+ # add hash methods for convenience
283
+ def os.keys; to_h.keys.map(&:to_s); end
277
284
  def os.values; to_h.values; end
278
- def os.at(index); self.public_send(keys[index]); end # to access as array, e.g. `a.at(1)`
285
+
286
+ # to access as array, e.g. `a.at(1)`
287
+ def os.at(index); self.public_send(keys[index]); end
288
+
279
289
  os
280
290
  end
281
291
 
@@ -39,6 +39,11 @@ class Main
39
39
 
40
40
  OptionParser.new do |parser|
41
41
 
42
+ parser.on("-h", "--help", "Show help") do |_help_requested|
43
+ ARGV << 'h' # pass on the request to the command processor
44
+ options.suppress_command_line_validation = true
45
+ end
46
+
42
47
  parser.on('-i', '--input_dir DIR',
43
48
  "Input directory containing source data files, default: '#{DEFAULT_INPUT_DIR}'") do |v|
44
49
  options.input_dir = File.expand_path(v)
@@ -80,10 +85,9 @@ class Main
80
85
  end
81
86
 
82
87
 
83
- # Arg is a directory containing 'chart_of_accounts.rbd' and '*journal*.rbd' for input,
84
- # and reports (*.rpt) will be output to this directory as well.
85
88
  def call
86
89
  begin
90
+ ARGV << '-h' if ARGV.empty?
87
91
  run_options = parse_command_line
88
92
  CommandLineInterface.new(run_options).call
89
93
  rescue => error
@@ -91,7 +95,10 @@ class Main
91
95
  <<~HEREDOC
92
96
  #{error.backtrace.join("\n")}
93
97
 
98
+ #{'-' * 79}
94
99
  #{error}
100
+ #{'-' * 79}
101
+
95
102
  HEREDOC
96
103
 
97
104
  if run_options.say
@@ -63,13 +63,28 @@ module RockBooks
63
63
 
64
64
  def all_reports_to_files(directory = '.', filter = nil)
65
65
  reports = all_reports(filter)
66
+
67
+ # "./pdf/short_name.pdf" or "./pdf/single_account/short_name.pdf"
68
+ build_filespec = ->(short_name, file_format) do
69
+ fragments = [directory, file_format, "#{short_name}.#{file_format}"]
70
+ is_acct_report = /^acct_/.match(short_name)
71
+ if is_acct_report
72
+ fragments.insert(2, SINGLE_ACCT_SUBDIR)
73
+ end
74
+ File.join(*fragments)
75
+ end
76
+
66
77
  reports.each do |short_name, report_text|
67
- report_directory = /^acct_/.match(short_name) ? File.join(directory, SINGLE_ACCT_SUBDIR) : directory
68
- txt_filespec = File.join(report_directory, "#{short_name}.txt")
69
- html_filespec = File.join(report_directory, "#{short_name}.html")
70
- pdf_filespec = File.join(report_directory, "#{short_name}.pdf")
78
+ txt_filespec = build_filespec.(short_name, 'txt')
79
+ html_filespec = build_filespec.(short_name, 'html')
80
+ pdf_filespec = build_filespec.(short_name, 'pdf')
81
+
82
+ FileUtils.mkdir_p(File.dirname(txt_filespec))
83
+ FileUtils.mkdir_p(File.dirname(html_filespec))
84
+ FileUtils.mkdir_p(File.dirname(pdf_filespec))
85
+
71
86
  File.write(txt_filespec, report_text)
72
- run_command("textutil -convert html -font 'Menlo Regular' #{txt_filespec} -output #{html_filespec}")
87
+ run_command("textutil -convert html -font 'Menlo Regular' -fontsize 10 #{txt_filespec} -output #{html_filespec}")
73
88
  run_command("cupsfilter #{html_filespec} > #{pdf_filespec}")
74
89
  puts "Created reports in txt, html, and pdf for #{"%-20s" % short_name} at #{File.dirname(txt_filespec)}.\n\n\n"
75
90
  end
@@ -9,14 +9,18 @@ class ChartOfAccounts
9
9
 
10
10
 
11
11
  def self.from_file(file)
12
- self.new(File.read(file))
12
+ self.new(File.readlines(file).map(&:chomp))
13
13
  end
14
14
 
15
15
 
16
- def initialize(input_string)
16
+ def self.from_string(string)
17
+ self.new(string.split("\n"))
18
+ end
19
+
20
+
21
+ def initialize(input_lines)
17
22
  @accounts = []
18
- lines = input_string.split("\n")
19
- lines.each { |line| parse_line(line) }
23
+ input_lines.each { |line| parse_line(line) }
20
24
  end
21
25
 
22
26
 
@@ -49,10 +53,12 @@ class ChartOfAccounts
49
53
  end
50
54
  end
51
55
 
56
+
52
57
  def accounts_of_type(type)
53
58
  accounts.select { |account| account.type == type }
54
59
  end
55
60
 
61
+
56
62
  def account_codes_of_type(type)
57
63
  accounts_of_type(type).map(&:code)
58
64
  end
@@ -88,6 +94,7 @@ class ChartOfAccounts
88
94
  found ? found.type : nil
89
95
  end
90
96
 
97
+
91
98
  def name_for_code(code)
92
99
  found = account_for_code(code)
93
100
  found ? found.name : nil
@@ -109,5 +116,13 @@ class ChartOfAccounts
109
116
  raise "Unexpected type #{type} for code #{code}."
110
117
  end
111
118
  end
119
+
120
+
121
+ def ==(other)
122
+ doc_type == other.doc_type && \
123
+ title == other.title && \
124
+ accounts == other.accounts && \
125
+ entity == other.entity
126
+ end
112
127
  end
113
128
  end
@@ -4,6 +4,7 @@ require 'yaml'
4
4
 
5
5
  require_relative '../errors/account_not_found_error'
6
6
  require_relative '../types/acct_amount'
7
+ require_relative '../types/journal_entry_context'
7
8
  require_relative 'journal_entry'
8
9
  require_relative 'journal_entry_builder'
9
10
  require_relative '../reports/reporter'
@@ -18,7 +19,12 @@ module RockBooks
18
19
  class Journal
19
20
 
20
21
  def self.from_file(chart_of_accounts, file)
21
- self.new(chart_of_accounts, File.read(file))
22
+ self.new(chart_of_accounts, File.readlines(file).map(&:chomp))
23
+ end
24
+
25
+
26
+ def self.from_string(chart_of_accounts, string)
27
+ self.new(chart_of_accounts, string.split("\n"))
22
28
  end
23
29
 
24
30
 
@@ -61,18 +67,21 @@ class Journal
61
67
  attr_reader :short_name, :account_code, :chart_of_accounts, :date_prefix, :debit_or_credit, :doc_type, :title, :entries
62
68
 
63
69
  # short_name is a name that will appear on reports identifying the journal from which a transaction comes
64
- def initialize(chart_of_accounts, input_string, short_name = nil)
70
+ def initialize(chart_of_accounts, input_lines, short_name = nil)
65
71
  @chart_of_accounts = chart_of_accounts
66
72
  @short_name = short_name
67
73
  @entries = []
68
74
  @date_prefix = ''
69
75
  @title = ''
70
- lines = input_string.split("\n")
71
- lines.each { |line| parse_line(line) }
76
+ input_lines.each_with_index do |line, linenum|
77
+ context = JournalEntryContext.new(self, linenum + 1, line)
78
+ parse_line(context)
79
+ end
72
80
  end
73
81
 
74
82
 
75
- def parse_line(line)
83
+ def parse_line(journal_entry_context)
84
+ line = journal_entry_context.line
76
85
  case line.strip
77
86
  when /^@doc_type:/
78
87
  @doc_type = line.split(/^@doc_type:/).last.strip
@@ -80,7 +89,7 @@ class Journal
80
89
  @account_code = line.split(/^@account_code:/).last.strip
81
90
 
82
91
  unless chart_of_accounts.include?(@account_code)
83
- raise AccountNotFoundError.new(@account_code)
92
+ raise AccountNotFoundError.new(@account_code, journal_entry_context)
84
93
  end
85
94
 
86
95
  # if debit or credit has not yet been specified, inherit the setting from the account:
@@ -102,7 +111,7 @@ class Journal
102
111
  when /^#/
103
112
  # ignore comment line
104
113
  when /^\d/ # a date/acct/amount line starting with a number
105
- entries << JournalEntryBuilder.new(line, self).build
114
+ entries << JournalEntryBuilder.new(journal_entry_context).build
106
115
  else # Text line(s) to be attached to the most recently parsed transaction
107
116
  unless entries.last
108
117
  raise Error.new("Entry for this description cannot be found: #{line}")
@@ -157,5 +166,18 @@ class Journal
157
166
 
158
167
  def to_json; to_h.to_json; end
159
168
  def to_yaml; to_h.to_yaml; end
169
+
170
+
171
+ def ==(other)
172
+ # excluding date_prefix from this test intentionally because it does not
173
+ # affect the parsed data.
174
+ short_name == other.short_name && \
175
+ account_code == other.account_code && \
176
+ chart_of_accounts == other.chart_of_accounts && \
177
+ debit_or_credit == other.debit_or_credit && \
178
+ doc_type == other.doc_type && \
179
+ title == other.title && \
180
+ entries == other.entries
181
+ end
160
182
  end
161
183
  end
@@ -1,23 +1,24 @@
1
+ require_relative '../errors/incorrect_sequence_error'
2
+ require_relative '../errors/transaction_not_balanced_error'
1
3
  require_relative '../types/acct_amount'
4
+ require_relative '../types/journal_entry_context'
2
5
  require_relative 'chart_of_accounts'
3
6
  require_relative 'journal'
4
7
 
5
8
  module RockBooks
6
- class JournalEntryBuilder < Struct.new(:line, :journal)
9
+ class JournalEntryBuilder < Struct.new(:journal_entry_context)
7
10
 
8
- def acct_amounts_from_tokens(tokens, date, chart_of_accounts)
11
+ def journal; journal_entry_context.journal; end
12
+ def linenum; journal_entry_context.linenum; end
13
+ def line; journal_entry_context.line; end
14
+ def chart_of_accounts; journal_entry_context.chart_of_accounts; end
15
+
16
+
17
+ def acct_amounts_from_tokens(tokens, date)
9
18
  acct_amounts = []
10
19
 
11
20
  tokens[0..-1].each_slice(2).each do |(account_code, amount)|
12
- begin
13
- acct_amount = AcctAmount.create_with_chart_validation(date, account_code, amount, chart_of_accounts)
14
- rescue AccountNotFoundError => error
15
- error.document_name = journal.short_name
16
- error.line = line
17
- raise
18
- end
19
-
20
- acct_amounts << acct_amount
21
+ acct_amounts << AcctAmount.create_with_chart_validation(date, account_code, amount, journal_entry_context)
21
22
  end
22
23
 
23
24
  acct_amounts
@@ -26,7 +27,7 @@ class JournalEntryBuilder < Struct.new(:line, :journal)
26
27
 
27
28
  def validate_acct_amount_token_array_size(tokens)
28
29
  if tokens.size.odd?
29
- raise Error.new("Incorrect sequence of account codes and amounts: #{tokens}")
30
+ raise IncorrectSequenceError.new(tokens, journal_entry_context)
30
31
  end
31
32
  end
32
33
 
@@ -118,7 +119,15 @@ class JournalEntryBuilder < Struct.new(:line, :journal)
118
119
  convert_signs_for_debit_credit(tokens)
119
120
  end
120
121
 
121
- acct_amounts_from_tokens(tokens, date, journal.chart_of_accounts)
122
+ acct_amounts_from_tokens(tokens, date)
123
+ end
124
+
125
+
126
+ def validate_transaction_is_balanced(acct_amounts)
127
+ sum = acct_amounts.map(&:amount).sum.round(4)
128
+ unless sum == 0.0
129
+ raise TransactionNotBalancedError.new(sum, journal_entry_context)
130
+ end
122
131
  end
123
132
 
124
133
 
@@ -141,8 +150,8 @@ class JournalEntryBuilder < Struct.new(:line, :journal)
141
150
  end
142
151
 
143
152
  acct_amounts = build_acct_amount_array(date, acct_amount_tokens)
153
+ validate_transaction_is_balanced(acct_amounts)
144
154
  JournalEntry.new(date, acct_amounts, journal.short_name)
145
155
  end
146
-
147
156
  end
148
157
  end
@@ -1,20 +1,21 @@
1
+ require_relative '../types/journal_entry_context'
2
+
3
+
1
4
  module RockBooks
2
5
  class AccountNotFoundError < RuntimeError
3
6
 
4
- attr_accessor :bad_account_code, :document_name, :line
7
+ attr_accessor :code, :journal_entry_context
5
8
 
6
- def initialize(bad_account_code, document_name = nil, line = nil)
7
- self.bad_account_code = bad_account_code
9
+ def initialize(code, journal_entry_context)
10
+ self.code = code
11
+ self.journal_entry_context = journal_entry_context
8
12
  super(to_s)
9
13
  end
10
14
 
11
15
 
12
16
  def to_s
13
- s = "Account code not found in chart of accounts: #{bad_account_code}"
14
- if document_name && line
15
- s << ", document: #{document_name}, line: #{line}"
16
- end
17
- s
17
+ ctx = journal_entry_context
18
+ "Account code '#{code}' in journal '#{ctx.journal.short_name}', line ##{ctx.linenum} not found in chart of accounts. Line: '#{ctx.line}'"
18
19
  end
19
20
  end
20
21
  end
@@ -0,0 +1,21 @@
1
+ require_relative '../types/journal_entry_context'
2
+
3
+
4
+ module RockBooks
5
+ class IncorrectSequenceError < RuntimeError
6
+
7
+ attr_accessor :tokens, :journal_entry_context
8
+
9
+ def initialize(tokens, journal_entry_context)
10
+ self.tokens = tokens
11
+ self.journal_entry_context = journal_entry_context
12
+ super(to_s)
13
+ end
14
+
15
+
16
+ def to_s
17
+ ctx = journal_entry_context
18
+ "Incorrect token sequence in journal '#{ctx.journal.short_name}', line ##{ctx.linenum}: #{tokens.inspect}"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ require_relative '../errors/transaction_not_balanced_error'
2
+
3
+ module RockBooks
4
+
5
+ class TransactionNotBalancedError < RuntimeError
6
+
7
+ attr_reader :discrepancy, :journal_entry_context
8
+
9
+ def initialize(discrepancy, journal_entry_context)
10
+ @discrepancy = discrepancy
11
+ @journal_entry_context = journal_entry_context
12
+ super(to_s)
13
+ end
14
+
15
+ def to_s
16
+ amount_string = "%0.2f" % discrepancy
17
+ "Transaction not balanced; discrepancy is #{amount_string}. Context: #{journal_entry_context}"
18
+ end
19
+ end
20
+
21
+ end
@@ -6,6 +6,11 @@ module JournalEntryFilters
6
6
  module_function
7
7
 
8
8
 
9
+ def filter(entries, entry_filter)
10
+ entries.select { |entry| entry_filter.(entry) }
11
+ end
12
+
13
+
9
14
  # Dates can be provided as a Ruby Date object, or as a string that will be converted to date (yyyy-mm-dd).
10
15
  def to_date(string_or_date_object)
11
16
  if string_or_date_object.is_a?(String)
@@ -40,7 +45,7 @@ module JournalEntryFilters
40
45
  end
41
46
 
42
47
 
43
- def account_code_filter(account_code)
48
+ def account_code(account_code)
44
49
  ->(entry) do
45
50
  entry.acct_amounts.map(&:code).detect { |code| code == account_code }
46
51
  end
@@ -8,7 +8,7 @@ module RockBooks
8
8
  module_function
9
9
 
10
10
  def get_files_with_types(directory)
11
- files = Dir[File.join(directory, '*.rbt')]
11
+ files = Dir[File.join(directory, '*.txt')]
12
12
  files.each_with_object({}) do |filespec, files_with_types|
13
13
  files_with_types[filespec] = ParseHelper.find_document_type_in_file(filespec)
14
14
  end
@@ -40,7 +40,7 @@ module RockBooks
40
40
  end
41
41
 
42
42
 
43
- # Uses all *.rbt files in the specified directory; uses @doc_type to determine which
43
+ # Uses all *.txt files in the specified directory; uses @doc_type to determine which
44
44
  # is the chart of accounts and which are journals.
45
45
  # To exclude a file, make the extension other than .rdt.
46
46
  def load(run_options)
@@ -16,7 +16,7 @@ module RockBooks
16
16
 
17
17
 
18
18
  def find_document_type_in_file(filespec)
19
- find_document_type(File.readlines(filespec))
19
+ find_document_type(File.readlines(filespec).map(&:chomp))
20
20
  end
21
21
  end
22
22
  end
@@ -31,7 +31,7 @@ class TxByAccount
31
31
 
32
32
  def account_header(account, account_total)
33
33
  total_string = "%.2f" % account_total
34
- title = "Total: #{total_string} -- #{account_code_name_type_string(account)})"
34
+ title = "Total: #{total_string} -- #{account_code_name_type_string(account)}"
35
35
 
36
36
  <<~HEREDOC
37
37
  #{banner_line}
@@ -41,7 +41,7 @@ module RockBooks
41
41
 
42
42
 
43
43
  def generate_report
44
- entries = Journal.entries_in_documents(context.journals, JournalEntryFilters.account_code_filter(account_code))
44
+ entries = Journal.entries_in_documents(context.journals, JournalEntryFilters.account_code(account_code))
45
45
  account_total = JournalEntry.total_for_code(entries, account_code)
46
46
  output = generate_header(account_total)
47
47
 
@@ -2,13 +2,13 @@ module RockBooks
2
2
 
3
3
  # This class represents an account code and an amount.
4
4
  # Journal entries will have multiple instances of these.
5
- class AcctAmount < Struct.new(:date, :code, :amount)
5
+ class AcctAmount < Struct.new(:date, :code, :amount, :journal_entry_context)
6
6
 
7
7
 
8
8
  # Same as constructor except it raises an error if the account code is not in the chart of accounts.
9
- def self.create_with_chart_validation(date, code, amount, chart_of_accounts)
10
- unless chart_of_accounts.include?(code)
11
- raise AccountNotFoundError.new(code)
9
+ def self.create_with_chart_validation(date, code, amount, journal_entry_context)
10
+ unless journal_entry_context.chart_of_accounts.include?(code)
11
+ raise AccountNotFoundError.new(code, journal_entry_context)
12
12
  end
13
13
  self.new(date, code, amount)
14
14
  end
@@ -0,0 +1,14 @@
1
+ module RockBooks
2
+
3
+ class JournalEntryContext < Struct.new(:journal, :linenum, :line)
4
+
5
+ def chart_of_accounts
6
+ journal.chart_of_accounts
7
+ end
8
+
9
+ def to_s
10
+ "Journal '#{journal.short_name}', line ##{linenum}, text: #{line}"
11
+ end
12
+ end
13
+
14
+ end
@@ -1,3 +1,3 @@
1
1
  module RockBooks
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end