rustfava 0.1.0__py3-none-any.whl

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 (187) hide show
  1. rustfava/__init__.py +30 -0
  2. rustfava/_ctx_globals_class.py +55 -0
  3. rustfava/api_models.py +36 -0
  4. rustfava/application.py +534 -0
  5. rustfava/beans/__init__.py +6 -0
  6. rustfava/beans/abc.py +327 -0
  7. rustfava/beans/account.py +79 -0
  8. rustfava/beans/create.py +377 -0
  9. rustfava/beans/flags.py +20 -0
  10. rustfava/beans/funcs.py +38 -0
  11. rustfava/beans/helpers.py +52 -0
  12. rustfava/beans/ingest.py +75 -0
  13. rustfava/beans/load.py +31 -0
  14. rustfava/beans/prices.py +151 -0
  15. rustfava/beans/protocols.py +82 -0
  16. rustfava/beans/str.py +454 -0
  17. rustfava/beans/types.py +63 -0
  18. rustfava/cli.py +187 -0
  19. rustfava/context.py +13 -0
  20. rustfava/core/__init__.py +729 -0
  21. rustfava/core/accounts.py +161 -0
  22. rustfava/core/attributes.py +145 -0
  23. rustfava/core/budgets.py +207 -0
  24. rustfava/core/charts.py +301 -0
  25. rustfava/core/commodities.py +37 -0
  26. rustfava/core/conversion.py +229 -0
  27. rustfava/core/documents.py +87 -0
  28. rustfava/core/extensions.py +132 -0
  29. rustfava/core/fava_options.py +255 -0
  30. rustfava/core/file.py +542 -0
  31. rustfava/core/filters.py +484 -0
  32. rustfava/core/group_entries.py +97 -0
  33. rustfava/core/ingest.py +509 -0
  34. rustfava/core/inventory.py +167 -0
  35. rustfava/core/misc.py +105 -0
  36. rustfava/core/module_base.py +18 -0
  37. rustfava/core/number.py +106 -0
  38. rustfava/core/query.py +180 -0
  39. rustfava/core/query_shell.py +301 -0
  40. rustfava/core/tree.py +265 -0
  41. rustfava/core/watcher.py +219 -0
  42. rustfava/ext/__init__.py +232 -0
  43. rustfava/ext/auto_commit.py +61 -0
  44. rustfava/ext/portfolio_list/PortfolioList.js +34 -0
  45. rustfava/ext/portfolio_list/__init__.py +29 -0
  46. rustfava/ext/portfolio_list/templates/PortfolioList.html +15 -0
  47. rustfava/ext/rustfava_ext_test/RustfavaExtTest.js +42 -0
  48. rustfava/ext/rustfava_ext_test/__init__.py +207 -0
  49. rustfava/ext/rustfava_ext_test/templates/RustfavaExtTest.html +45 -0
  50. rustfava/ext/rustfava_ext_test/templates/RustfavaExtTestInclude.html +1 -0
  51. rustfava/help/__init__.py +15 -0
  52. rustfava/help/_index.md +29 -0
  53. rustfava/help/beancount_syntax.md +156 -0
  54. rustfava/help/budgets.md +31 -0
  55. rustfava/help/conversion.md +29 -0
  56. rustfava/help/extensions.md +111 -0
  57. rustfava/help/features.md +179 -0
  58. rustfava/help/filters.md +103 -0
  59. rustfava/help/import.md +27 -0
  60. rustfava/help/options.md +289 -0
  61. rustfava/helpers.py +30 -0
  62. rustfava/internal_api.py +221 -0
  63. rustfava/json_api.py +952 -0
  64. rustfava/plugins/__init__.py +3 -0
  65. rustfava/plugins/link_documents.py +107 -0
  66. rustfava/plugins/tag_discovered_documents.py +44 -0
  67. rustfava/py.typed +0 -0
  68. rustfava/rustledger/__init__.py +31 -0
  69. rustfava/rustledger/constants.py +76 -0
  70. rustfava/rustledger/engine.py +485 -0
  71. rustfava/rustledger/loader.py +273 -0
  72. rustfava/rustledger/options.py +202 -0
  73. rustfava/rustledger/query.py +331 -0
  74. rustfava/rustledger/types.py +830 -0
  75. rustfava/serialisation.py +220 -0
  76. rustfava/static/app.css +2988 -0
  77. rustfava/static/app.css.map +7 -0
  78. rustfava/static/app.js +12854 -0
  79. rustfava/static/app.js.map +7 -0
  80. rustfava/static/beancount-JFV44ZVZ.css +5 -0
  81. rustfava/static/beancount-JFV44ZVZ.css.map +7 -0
  82. rustfava/static/beancount-VTTKRGSK.js +4642 -0
  83. rustfava/static/beancount-VTTKRGSK.js.map +7 -0
  84. rustfava/static/bql-MGFRUMBP.js +333 -0
  85. rustfava/static/bql-MGFRUMBP.js.map +7 -0
  86. rustfava/static/chunk-E7ZF4ASL.js +23061 -0
  87. rustfava/static/chunk-E7ZF4ASL.js.map +7 -0
  88. rustfava/static/chunk-V24TLQHT.js +12673 -0
  89. rustfava/static/chunk-V24TLQHT.js.map +7 -0
  90. rustfava/static/favicon.ico +0 -0
  91. rustfava/static/fira-mono-cyrillic-400-normal-BLAGXRCE.woff2 +0 -0
  92. rustfava/static/fira-mono-cyrillic-500-normal-EN7JUAAW.woff2 +0 -0
  93. rustfava/static/fira-mono-cyrillic-ext-400-normal-EX7VARTS.woff2 +0 -0
  94. rustfava/static/fira-mono-cyrillic-ext-500-normal-ZDPTUPRR.woff2 +0 -0
  95. rustfava/static/fira-mono-greek-400-normal-COGHKMOA.woff2 +0 -0
  96. rustfava/static/fira-mono-greek-500-normal-4EN2PKZT.woff2 +0 -0
  97. rustfava/static/fira-mono-greek-ext-400-normal-DYEQIJH7.woff2 +0 -0
  98. rustfava/static/fira-mono-greek-ext-500-normal-SG73CVKQ.woff2 +0 -0
  99. rustfava/static/fira-mono-latin-400-normal-NA3VLV7E.woff2 +0 -0
  100. rustfava/static/fira-mono-latin-500-normal-YC77GFWD.woff2 +0 -0
  101. rustfava/static/fira-mono-latin-ext-400-normal-DIKTZ5PW.woff2 +0 -0
  102. rustfava/static/fira-mono-latin-ext-500-normal-ZWY4UO4V.woff2 +0 -0
  103. rustfava/static/fira-mono-symbols2-400-normal-UITXT77Q.woff2 +0 -0
  104. rustfava/static/fira-mono-symbols2-500-normal-VWPC2EFN.woff2 +0 -0
  105. rustfava/static/fira-sans-cyrillic-400-normal-KLQMBCA6.woff2 +0 -0
  106. rustfava/static/fira-sans-cyrillic-500-normal-NFG7UD6J.woff2 +0 -0
  107. rustfava/static/fira-sans-cyrillic-ext-400-normal-GWO44OPC.woff2 +0 -0
  108. rustfava/static/fira-sans-cyrillic-ext-500-normal-SP47E5SC.woff2 +0 -0
  109. rustfava/static/fira-sans-greek-400-normal-UMQBTLC3.woff2 +0 -0
  110. rustfava/static/fira-sans-greek-500-normal-4ZKHN4FQ.woff2 +0 -0
  111. rustfava/static/fira-sans-greek-ext-400-normal-O2DVJAJZ.woff2 +0 -0
  112. rustfava/static/fira-sans-greek-ext-500-normal-SK6GNWGO.woff2 +0 -0
  113. rustfava/static/fira-sans-latin-400-normal-OYYTPMAV.woff2 +0 -0
  114. rustfava/static/fira-sans-latin-500-normal-SMQPZW5A.woff2 +0 -0
  115. rustfava/static/fira-sans-latin-ext-400-normal-OAUP3WK5.woff2 +0 -0
  116. rustfava/static/fira-sans-latin-ext-500-normal-LY3YDR5Y.woff2 +0 -0
  117. rustfava/static/fira-sans-vietnamese-400-normal-OBMQ72MR.woff2 +0 -0
  118. rustfava/static/fira-sans-vietnamese-500-normal-Y4NZR5EU.woff2 +0 -0
  119. rustfava/static/source-code-pro-cyrillic-400-normal-TO22V6M3.woff2 +0 -0
  120. rustfava/static/source-code-pro-cyrillic-500-normal-OGBWWWYW.woff2 +0 -0
  121. rustfava/static/source-code-pro-cyrillic-ext-400-normal-XH44UCIA.woff2 +0 -0
  122. rustfava/static/source-code-pro-cyrillic-ext-500-normal-3Z6MMVM6.woff2 +0 -0
  123. rustfava/static/source-code-pro-greek-400-normal-OUXXUQWK.woff2 +0 -0
  124. rustfava/static/source-code-pro-greek-500-normal-JA2Z5UXO.woff2 +0 -0
  125. rustfava/static/source-code-pro-greek-ext-400-normal-WCDKMX7U.woff2 +0 -0
  126. rustfava/static/source-code-pro-greek-ext-500-normal-ZHVI4VKW.woff2 +0 -0
  127. rustfava/static/source-code-pro-latin-400-normal-QOGTXED5.woff2 +0 -0
  128. rustfava/static/source-code-pro-latin-500-normal-X57QEOLQ.woff2 +0 -0
  129. rustfava/static/source-code-pro-latin-ext-400-normal-QXC74NBF.woff2 +0 -0
  130. rustfava/static/source-code-pro-latin-ext-500-normal-QGOY7MTT.woff2 +0 -0
  131. rustfava/static/source-code-pro-vietnamese-400-normal-NPDCDTBA.woff2 +0 -0
  132. rustfava/static/source-code-pro-vietnamese-500-normal-M6PJKTR5.woff2 +0 -0
  133. rustfava/static/tree-sitter-beancount-MLXFQBZ5.wasm +0 -0
  134. rustfava/static/web-tree-sitter-RNOQ6E74.wasm +0 -0
  135. rustfava/template_filters.py +64 -0
  136. rustfava/templates/_journal_table.html +156 -0
  137. rustfava/templates/_layout.html +26 -0
  138. rustfava/templates/_query_table.html +88 -0
  139. rustfava/templates/beancount_file +18 -0
  140. rustfava/templates/help.html +23 -0
  141. rustfava/templates/macros/_account_macros.html +5 -0
  142. rustfava/templates/macros/_commodity_macros.html +13 -0
  143. rustfava/translations/bg/LC_MESSAGES/messages.mo +0 -0
  144. rustfava/translations/bg/LC_MESSAGES/messages.po +618 -0
  145. rustfava/translations/ca/LC_MESSAGES/messages.mo +0 -0
  146. rustfava/translations/ca/LC_MESSAGES/messages.po +618 -0
  147. rustfava/translations/de/LC_MESSAGES/messages.mo +0 -0
  148. rustfava/translations/de/LC_MESSAGES/messages.po +618 -0
  149. rustfava/translations/es/LC_MESSAGES/messages.mo +0 -0
  150. rustfava/translations/es/LC_MESSAGES/messages.po +619 -0
  151. rustfava/translations/fa/LC_MESSAGES/messages.mo +0 -0
  152. rustfava/translations/fa/LC_MESSAGES/messages.po +618 -0
  153. rustfava/translations/fr/LC_MESSAGES/messages.mo +0 -0
  154. rustfava/translations/fr/LC_MESSAGES/messages.po +618 -0
  155. rustfava/translations/ja/LC_MESSAGES/messages.mo +0 -0
  156. rustfava/translations/ja/LC_MESSAGES/messages.po +618 -0
  157. rustfava/translations/nl/LC_MESSAGES/messages.mo +0 -0
  158. rustfava/translations/nl/LC_MESSAGES/messages.po +617 -0
  159. rustfava/translations/pt/LC_MESSAGES/messages.mo +0 -0
  160. rustfava/translations/pt/LC_MESSAGES/messages.po +617 -0
  161. rustfava/translations/pt_BR/LC_MESSAGES/messages.mo +0 -0
  162. rustfava/translations/pt_BR/LC_MESSAGES/messages.po +618 -0
  163. rustfava/translations/ru/LC_MESSAGES/messages.mo +0 -0
  164. rustfava/translations/ru/LC_MESSAGES/messages.po +617 -0
  165. rustfava/translations/sk/LC_MESSAGES/messages.mo +0 -0
  166. rustfava/translations/sk/LC_MESSAGES/messages.po +623 -0
  167. rustfava/translations/sv/LC_MESSAGES/messages.mo +0 -0
  168. rustfava/translations/sv/LC_MESSAGES/messages.po +618 -0
  169. rustfava/translations/uk/LC_MESSAGES/messages.mo +0 -0
  170. rustfava/translations/uk/LC_MESSAGES/messages.po +618 -0
  171. rustfava/translations/zh/LC_MESSAGES/messages.mo +0 -0
  172. rustfava/translations/zh/LC_MESSAGES/messages.po +618 -0
  173. rustfava/translations/zh_Hant_TW/LC_MESSAGES/messages.mo +0 -0
  174. rustfava/translations/zh_Hant_TW/LC_MESSAGES/messages.po +618 -0
  175. rustfava/util/__init__.py +157 -0
  176. rustfava/util/date.py +576 -0
  177. rustfava/util/excel.py +118 -0
  178. rustfava/util/ranking.py +79 -0
  179. rustfava/util/sets.py +18 -0
  180. rustfava/util/unreachable.py +20 -0
  181. rustfava-0.1.0.dist-info/METADATA +102 -0
  182. rustfava-0.1.0.dist-info/RECORD +187 -0
  183. rustfava-0.1.0.dist-info/WHEEL +5 -0
  184. rustfava-0.1.0.dist-info/entry_points.txt +2 -0
  185. rustfava-0.1.0.dist-info/licenses/AUTHORS +11 -0
  186. rustfava-0.1.0.dist-info/licenses/LICENSE +21 -0
  187. rustfava-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,29 @@
1
+ # Conversion
2
+
3
+ In most reports in rustfava, a conversion can be selected with the select dropdown
4
+ at the top of the chart. These conversions will use the prices defined in the
5
+ Beancount file, so these should defined manually or by some plugin (using
6
+ `beancount.plugins.implicit_prices` is recommend to get prices for all costs in
7
+ the Beancount file).
8
+
9
+ - "At Cost" - Show all inventories at cost, e.g., a position of
10
+ `10 STOCK {4 USD}` would be converted to `40 USD`.
11
+ - "At Market Value" - Show all inventories at their current market value, that
12
+ is, convert to the cost currency at the current price. E.g., a position of
13
+ `10 STOCK {4 USD}` would be converted to `50 USD` if the current price of
14
+ `STOCK` is `5 USD`.
15
+ - "Units" - The plain units of all positions, e.g., `10 STOCK` for a position of
16
+ `10 STOCK {4 USD}`.
17
+ - "Converted to X" - Convert to the currency `X`, e.g., a position of
18
+ `10 STOCK {4 USD}` would be converted to `20 X` if the current price of
19
+ `STOCK` is `2 X`. For positions with a price, a conversion via the cost
20
+ currency is attempted if no direct price exists, so the example position would
21
+ also successfully be converted if no price for `STOCK` in `X` exists but both
22
+ a price of `STOCK` in `USD` and a price of `X` in `USD` exists.
23
+ - "Converted to X,Y" - It is also possible to chain conversions to currencies by
24
+ selecting multiple conversions in the dropdown. These conversions are done in
25
+ sequence, a position of `10 STOCK {4 USD}` would first be converted to `X` and
26
+ then this amount in `X` would be converted to `Y`.
27
+
28
+ None of the conversions will silently drop amounts, so if a conversion is not
29
+ possible, the un-converted units are shown.
@@ -0,0 +1,111 @@
1
+ # Extensions
2
+
3
+ Rustfava supports extensions. Extensions allow you to register hooks and generate
4
+ your own report pages.
5
+
6
+ If you use this extension system and need it to do more or need other hooks,
7
+ please open an issue on [GitHub](https://github.com/rustledger/rustfava/issues).
8
+
9
+ A rustfava extension is simply a Python module which contains a class that inherits
10
+ from `RustfavaExtensionBase` from `rustfava.ext`. Invoking an extension is done via the
11
+ `fava-extension` option in the beancount file. Check out `rustfava.ext.auto_commit`
12
+ for an example.
13
+
14
+ Extensions may also contain a report - this is detected when the extension's
15
+ class has a `report_title` attribute. The template for the report should be in a
16
+ `templates` subdirectory with a report matching the class's name. For example,
17
+ check out `rustfava.ext.portfolio_list` which has its template located at
18
+ `rustfava/ext/portfolio_list/templates/PortfolioList.html`.
19
+
20
+ Finally, extensions may contain a Javascript module to be loaded in the
21
+ frontend. The module should be in a Javascript file matching the class's name
22
+ and the extension should have its `has_js_module` attribute set to `True`. The
23
+ module can define functions to be called when different events happen. Take a
24
+ look at `rustfava/ext/portfolio_list/PortfolioList.js` for an example. Currently,
25
+ the following events/functions can be specified:
26
+
27
+ - `init`: is called when a rustfava report is first opened
28
+ - `onPageLoad`: Is called when any page in rustfava is loaded (so on first open and
29
+ on any further navigation).
30
+ - `onExtensionPageLoad`: Is called when the extension report is loaded.
31
+
32
+ The whole extension system should be considered unstable and it might change
33
+ drastically.
34
+
35
+ ## Rustfava Extension Setup Options
36
+
37
+ ______________________________________________________________________
38
+
39
+ ## `fava-extension`
40
+
41
+ A Python module to load as extension. The path of the Beancount file is searched
42
+ in addition to anything on the Python path. Single python files will also be
43
+ searched - so for example a `my_extension.py` could be used by giving
44
+ `my_extension`. Note that Python has a global namespace for currently loaded
45
+ modules, so try avoiding simple names that might coincide with some Python
46
+ library (as well as running rustfava on two files that have different extensions of
47
+ the same name).
48
+
49
+ Extensions allow for an optional configuration options string, whose structure
50
+ is specified by the individual extension.
51
+
52
+ <pre><textarea is="beancount-textarea">
53
+ 2010-01-01 custom "fava-extension" "extension-name"
54
+ 2010-01-01 custom "fava-extension" "extension-with-options" "{'option': 'config_value'}"</textarea></pre>
55
+
56
+ ______________________________________________________________________
57
+
58
+ ## Hooks
59
+
60
+ Below is a list of all current hooks.
61
+
62
+ ### `after_load_file()`
63
+
64
+ Called after a ledger file has been loaded. Use the `self.ledger` object to
65
+ access the ledger data.
66
+
67
+ ______________________________________________________________________
68
+
69
+ ### `before_request()`
70
+
71
+ Called when starting to process a request. Use Flask’s `request` object to
72
+ access the request being processed (`from flask import request`).
73
+
74
+ ______________________________________________________________________
75
+
76
+ ### `after_write_source(path: str, source: str)`
77
+
78
+ Called after the string `source` has been written to the Beancount file at
79
+ `path`.
80
+
81
+ ______________________________________________________________________
82
+
83
+ ### `after_insert_metadata(entry: Directive, key: str, value: str)`
84
+
85
+ Called after metadata (`key: value`) has been added to an `entry`.
86
+
87
+ ______________________________________________________________________
88
+
89
+ ### `after_insert_entry(entry: Directive)`
90
+
91
+ Called after an `entry` has been inserted.
92
+
93
+ ______________________________________________________________________
94
+
95
+ ### `after_entry_modified(entry: Directive, new_lines: str)`
96
+
97
+ Called after an `entry` has been modified, e.g., via the context popup.
98
+
99
+ ______________________________________________________________________
100
+
101
+ ### `after_delete_entry(entry: Directive)`
102
+
103
+ Called after an `entry` has been deleted, e.g., via the context popup.
104
+
105
+ ______________________________________________________________________
106
+
107
+ ## Extension attributes
108
+
109
+ ### `report_title`
110
+
111
+ Optional attribute to set extension report title used in the sidebar.
@@ -0,0 +1,179 @@
1
+ # rustfava's features
2
+
3
+ This is an overview of some of the more advanced features that rustfava has to
4
+ offer.
5
+
6
+ ## Editor
7
+
8
+ The [editor](../editor) provides a convenient way to edit the source file. If
9
+ you want to use a file different from the main file to be opened by default, use
10
+ the [`default-file`](./options#default-file) option. If you have
11
+ [`insert-entry`](./options#insert-entry) options set, the cursor will by default
12
+ jump to the (date-wise) latest one in the opened file.
13
+
14
+ The editor supports auto-completion for various entities, e.g., account names,
15
+ payees, and tags. Trailing whitespace is highlighted in red. The Tab key in the
16
+ editor can be used for indentation - to escape this keyboard trap, press Escape
17
+ and then Tab directly after it.
18
+
19
+ ## Queries
20
+
21
+ On the [Query](../query/) report you can execute queries using the Beancount
22
+ Query Language (BQL). Rustfava uses rustledger's built-in query engine. For an
23
+ explanation of how BQL queries work, see the
24
+ [Beancount Query Language Reference](http://furius.ca/beancount/doc/query).
25
+
26
+ Rustfava displays charts for BQL queries - if they have exactly two columns like the
27
+ following example with the first being a date or string and the second an
28
+ inventory, then a line chart or treemap chart is shown on the query page.
29
+
30
+ ```
31
+ SELECT
32
+ payee,
33
+ SUM(COST(position)) AS balance
34
+ WHERE
35
+ account ~ 'Expenses'
36
+ GROUP BY payee, account
37
+ ```
38
+
39
+ Rustfava supports downloading the result of these queries in various file formats.
40
+ By default, only exporting to `csv` is supported. For support of `xlsx` and
41
+ `ods`, install rustfava with the `excel` feature:
42
+
43
+ ```
44
+ uv pip install rustfava[excel]
45
+ ```
46
+
47
+ ## Adding Transactions
48
+
49
+ By clicking the `+` button or using the `n` keyboard shortcut you can open a
50
+ form to insert a transaction to your Beancount file. The position that
51
+ transactions are inserted at can be specified in a flexible way using the
52
+ [`insert-entry`](./options#insert-entry) option. If you want to set a bookmark
53
+ to this form, adding `#add-transaction` to any URL in rustfava will open it on load.
54
+ Tags and links can be added in the form by adding them (separated by spaces) to
55
+ the narration field, e.g., `narration #tag ^somelink`.
56
+
57
+ ## Up-to-date indicators
58
+
59
+ Rustfava offers colored indicators that can help you keep your accounts up-to-date.
60
+ They are shown next to accounts that have the metadata
61
+ `fava-uptodate-indication: TRUE` set on their Open directive. The colors have
62
+ the following meaning:
63
+
64
+ - green: The last entry for this account is a balance check that passed.
65
+ - red: The last entry is a balance check that failed.
66
+ - yellow: The last entry is not a balance check.
67
+
68
+ In addition, a grey dot will be shown if the account has not been updated in a
69
+ while, as configured by the `uptodate-indicator-grey-lookback-days` option.
70
+
71
+ ## Displaying only relevant accounts
72
+
73
+ To help display only the most relevant subset of accounts when managing a large
74
+ number or a deep hierarchy of accounts, Rustfava offers the following options:
75
+
76
+ - `show-closed-accounts`
77
+ - `show-accounts-with-zero-balance`
78
+ - `show-accounts-with-zero-transactions`
79
+ - `collapse-pattern`
80
+
81
+ ## Opening an external editor
82
+
83
+ Rustfava can open up your source file in your favorite editor directly from the web
84
+ interface using the `use-external-editor` configuration variable through the
85
+ `beancount://` URL handler. See the
86
+ [Beancount urlscheme](https://github.com/aumayr/beancount_urlscheme) project for
87
+ pre-configured URL handlers for macOS and Cygwin.
88
+
89
+ ## Multiple Beancount files
90
+
91
+ When you start rustfava specifying multiple Beancount files, you can click the
92
+ Beancount file name on the top left to switch between the files.
93
+
94
+ ## Custom links in the sidebar
95
+
96
+ If you regularly use certain views in rustfava with different filters, you can put
97
+ links to them in the sidebar. Custom links can be put in the Beancount file,
98
+ utilizing the `custom` directive:
99
+
100
+ ```
101
+ 2016-05-04 custom "fava-sidebar-link" "Income 2014" "../income_statement?time=2014"
102
+ ```
103
+
104
+ `"fava-sidebar-link"` specifies that this directive is for a custom sidebar
105
+ link, followed by the title to display in the sidebar (`"Income 2014"` in this
106
+ example), and finally the URL to link to. The URL can be relative, like in the
107
+ example above, or absolute, even linking to an external site.
108
+
109
+ Two frequently used custom links are for showing all Documents and all Notes
110
+ found in the journal:
111
+
112
+ - For all Documents: `/<slug>/journal/?show=document`
113
+ - For all Notes: `/<slug>/journal/?show=note`
114
+
115
+ There is a special URL handler `/jump` which can be used to jump to the current
116
+ page with given URL parameters. For example, `/jump?time=month` will show the
117
+ current page but change the time filter to the current month.
118
+
119
+ ## Language
120
+
121
+ You can change the language of the interface by specifying the
122
+ [`language`](./options#language) option. If no option is specified, rustfava tries
123
+ to guess the language from your browser settings.
124
+
125
+ ## Documents upload
126
+
127
+ One or more documents can be uploaded by drag and drop on account names or
128
+ Journal rows.
129
+
130
+ ### Uploading documents
131
+
132
+ To store a document in a specific account, just drag and drop the file on the
133
+ account name in a tree-table.
134
+
135
+ While still dragging, the background-color of the account name will switch to
136
+ blue, indicating that you can drop a file there.
137
+
138
+ Once dropped, a popup will be shown where you can rename the file before
139
+ storing. If the filename does not already start with a date (`YYYY-MM-DD`), the
140
+ current date will be added as a prefix automatically.
141
+
142
+ The file will be then stored in your Beancount documents folder, in a sub-folder
143
+ named after the account. You can set the path to the Beancount documents folder
144
+ by specifying the `option "documents" "/Users/test/invoices"`-option (absolute
145
+ or relative to your Beancount file) in your Beancount file.
146
+
147
+ Beancount will automatically discover files in your `"documents"`-folders and
148
+ generate Document entries for them.
149
+
150
+ When enabling the `tag_discovered_documents`-plugin, these Document entries will
151
+ be tagged with `#discovered` and can be filtered in the Journal:
152
+
153
+ ```
154
+ plugin "rustfava.plugins.tag_discovered_documents"
155
+ ```
156
+
157
+ ### Uploading statements
158
+
159
+ When dropping a file on a transaction (or one of its postings) in the Journal,
160
+ the file will be uploaded as described above, and a `document`-metadata-entry
161
+ inserted for the transaction in your Beancount file.
162
+
163
+ When dropped on the description the subfolder corresponds to the account of the
164
+ first posting.
165
+
166
+ **Note**: Uploading statements modifies your Beancount file!
167
+
168
+ When enabling the `link_documents`-plugin, the Document entries created by
169
+ Beancount (see above) will be tagged with `#linked`, linked to the corresponding
170
+ transaction and can be filtered in the Journal:
171
+
172
+ ```
173
+ plugin "rustfava.plugins.link_documents"
174
+ ```
175
+
176
+ ### Exporting
177
+
178
+ The entries that are currently shown in rustfava, with filters applied, can be
179
+ downloaded in Beancount format by clicking the ⬇ (Export) button in the sidebar.
@@ -0,0 +1,103 @@
1
+ # Filters
2
+
3
+ With the text inputs at the top right of the page, you can filter the entries
4
+ that are displayed in rustfava's reports. If you use multiple filters, the entries
5
+ matching all of them will be selected.
6
+
7
+ ## Time
8
+
9
+ Filter entries by their date. You can specify dates and intervals like years,
10
+ quarters, months, weeks, and days (for example `2015`, `2012-Q1`, `2010-10`,
11
+ `2016-W12`, or `2015-06-12`). You can specify a range of dates like
12
+ `2010 - 2012-10` which will display all entries between the start of 2010 and
13
+ the end of October 2012.
14
+
15
+ To refer to dates relative to the current day, you can use the variables `year`,
16
+ `quarter`, `month`, `week`, and `day`. These will be substituted with the
17
+ current date expressed in the respective format, and support addition and
18
+ subtraction. For example you can write `year - day` for all entries in the
19
+ current year up to today, or `year-1 - year` for all entries of the last and
20
+ current year. To prevent subtraction, use parentheses: `(month)-10` refers to
21
+ the 10th of this month, whereas `month-10` would be 10 months ago.
22
+
23
+ ### Summarisation of previous balances and conversions
24
+
25
+ When setting a time filter, rustfava does not just filter to the transactions in the
26
+ interval but also summarises transactions in the following ways (using
27
+ Beancount's "clamp" summarisation):
28
+
29
+ - All balances for the Income and Expenses accounts previous to the filtered
30
+ period are transferred to the `account_previous_earnings` ("retained
31
+ earnings") account and all of the other transactions before begin date are
32
+ summarised against the `account_previous_balances` account (usually "opening
33
+ balances"). So the Income and Expenses start with a balance of zero whereas
34
+ Assets and Liabilities accounts start with their accumulated balance.
35
+ - All the entries after the end date are removed.
36
+ - A conversion entry is added to the `account_current_conversions` account for
37
+ the changes occurring within the filtered period.
38
+
39
+ ### ISO 8601 Week dates
40
+
41
+ The week-based calendar follows
42
+ [ISO 8601 week-numbering system](https://en.wikipedia.org/wiki/ISO_week_date)
43
+ with each week starting on Mondays and the first week of the ISO week-based year
44
+ being the first week that has the majority of its days in January. Equivalently,
45
+ it is also the week to containing January 4th.
46
+
47
+ Some examples where the ISO week-based calendar differs from the Gregorian
48
+ calendar:
49
+
50
+ - Week 1 of 2025 starts on Monday 30 December 2024 and ends on Sunday 5 January
51
+ 2025\. As a result, 30 December 2024 belongs to the year 2025 of the ISO
52
+ week-based calendar, despite being in the year 2024 of the Gregorian calendar.
53
+ - Week 53 of 2020 ends on Sunday 3 January 2021. As a result, 3 January 2021
54
+ belongs to the year 2020 of the ISO week-based calendar, despite being in the
55
+ year 2021 of the Gregorian calendar.
56
+
57
+ Most years of ISO week-based calendars have 52 weeks, but as there are slightly
58
+ more than 52 weeks in a year, some years contain a 53rd week.
59
+
60
+ ## Account
61
+
62
+ Filter entries by account, matching any entry this account is part of. The
63
+ filter can be an account name, either the full account name or a component of
64
+ the account name, or a regular expression matching the account name, e.g.
65
+ `.*Company.*` to filter for all that contain `Company`.
66
+
67
+ ## Filter by tag, link, payee and other metadata
68
+
69
+ This final filter allows you to filter entries by various attributes.
70
+
71
+ - Filter by `#tag` or `^link`.
72
+ - Filter by amount, such as `= 100.20` or `>= 100` (comparing the absolute of
73
+ the units).
74
+ - Filter by any entry attribute, such as payee `payee:"restaurant"` or narration
75
+ `narration:'Dinner with Joe'`. The argument is a regular expression which
76
+ needs to be quoted (with `'` or `"`) if it contains spaces or special
77
+ characters. If the argument is not a valid regular expression, rustfava will look
78
+ for an exact match instead.
79
+ - Search in payee and narration if no specific entry attribute is given, e.g.
80
+ `"Cash withdrawal"`. For Note directives, the comment will be searched.
81
+ - Filter for entries having certain metadata values: `document:"\.pdf$"`. Note
82
+ that if the entry has an attribute of the same name as the metadata key, the
83
+ filter will apply to the entry attribute, not the metadata value.
84
+ - Exclude entries that match a filter by prepending a `-` to it, e.g. `-#tag` or
85
+ `-(^link #tag)`.
86
+ - To match entries by posting attributes, you can use `any()` and `all()`, e.g.,
87
+ `any(id:'12', account:"Cash$")` for all entries that have at least one posting
88
+ with metadata `id: 12` or account ending in `Cash`, or
89
+ `all(-account:"^Expenses:Food")` to exclude all transactions having a posting
90
+ to the Expenses:Food account. To match by amount, you can use comparison
91
+ operators, e.g. `any(units > 80)` to filter for all entries where one posting
92
+ has a units with an absolute amount greater than 80.
93
+
94
+ These filters can be combined by separating them by spaces to match all entries
95
+ satisfying all given filters or by commas to match all entries satisfying at
96
+ least one of the given filters. In other words, a space acts like an "and" and a
97
+ comma like an "or". As usual, the logical "and" has a higher grouping power than
98
+ "or" and you can use parentheses to group filters.
99
+
100
+ When given regular expressions, Rustfava checks for a match anywhere in the
101
+ corresponding attribute. Matching is always case-insensitive. To find out more
102
+ about the specific syntax rustfava uses, refer to
103
+ [Python's Regular Expression Syntax](https://docs.python.org/3/library/re.html?highlight=match#regular-expression-syntax).
@@ -0,0 +1,27 @@
1
+ # Import
2
+
3
+ Rustfava can use Beancount's import system to semi-automatically import entries into
4
+ your ledger. See [Importing External Data in Beancount](http://furius.ca/beancount/doc/ingest)
5
+ for more information on how to write importers.
6
+
7
+ **Note**: Import functionality requires the beancount compatibility package.
8
+ Install it with: `uv pip install rustfava[beancount-compat]`
9
+
10
+ You can override the hooks that should be run for your importers by specifying a
11
+ variable `HOOKS` with a list of hooks to apply to the list of
12
+ `(filename: str, entries: list[Directive])` tuples. If you want to use
13
+ beangulp-style hooks that take lists of
14
+ `(filename: str, entries: list[Directive], account: str, importer: Importer)`-tuples,
15
+ you can annotate them with the appropriate Python types which rustfava will detect
16
+ and call with these 4-tuples.
17
+
18
+ Set the `import-config` option to point to your import config and set
19
+ `import-dirs` to the directories that contain the files that you want to import.
20
+ And if you wish to save new entries elsewhere than main file - use
21
+ `insert-entry` option.
22
+
23
+ Rustfava currently only supports entries of type `Transaction`, `Balance`, and
24
+ `Note`. Set the special metadata key `__source__` to display the corresponding
25
+ text (CSV-row, XML-fragment, etc.) for the entry in the list of entries to
26
+ import. Note that this metadata (and all other metadata keys starting with an
27
+ underscore) will be stripped before saving the entry to file.