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.
- rustfava/__init__.py +30 -0
- rustfava/_ctx_globals_class.py +55 -0
- rustfava/api_models.py +36 -0
- rustfava/application.py +534 -0
- rustfava/beans/__init__.py +6 -0
- rustfava/beans/abc.py +327 -0
- rustfava/beans/account.py +79 -0
- rustfava/beans/create.py +377 -0
- rustfava/beans/flags.py +20 -0
- rustfava/beans/funcs.py +38 -0
- rustfava/beans/helpers.py +52 -0
- rustfava/beans/ingest.py +75 -0
- rustfava/beans/load.py +31 -0
- rustfava/beans/prices.py +151 -0
- rustfava/beans/protocols.py +82 -0
- rustfava/beans/str.py +454 -0
- rustfava/beans/types.py +63 -0
- rustfava/cli.py +187 -0
- rustfava/context.py +13 -0
- rustfava/core/__init__.py +729 -0
- rustfava/core/accounts.py +161 -0
- rustfava/core/attributes.py +145 -0
- rustfava/core/budgets.py +207 -0
- rustfava/core/charts.py +301 -0
- rustfava/core/commodities.py +37 -0
- rustfava/core/conversion.py +229 -0
- rustfava/core/documents.py +87 -0
- rustfava/core/extensions.py +132 -0
- rustfava/core/fava_options.py +255 -0
- rustfava/core/file.py +542 -0
- rustfava/core/filters.py +484 -0
- rustfava/core/group_entries.py +97 -0
- rustfava/core/ingest.py +509 -0
- rustfava/core/inventory.py +167 -0
- rustfava/core/misc.py +105 -0
- rustfava/core/module_base.py +18 -0
- rustfava/core/number.py +106 -0
- rustfava/core/query.py +180 -0
- rustfava/core/query_shell.py +301 -0
- rustfava/core/tree.py +265 -0
- rustfava/core/watcher.py +219 -0
- rustfava/ext/__init__.py +232 -0
- rustfava/ext/auto_commit.py +61 -0
- rustfava/ext/portfolio_list/PortfolioList.js +34 -0
- rustfava/ext/portfolio_list/__init__.py +29 -0
- rustfava/ext/portfolio_list/templates/PortfolioList.html +15 -0
- rustfava/ext/rustfava_ext_test/RustfavaExtTest.js +42 -0
- rustfava/ext/rustfava_ext_test/__init__.py +207 -0
- rustfava/ext/rustfava_ext_test/templates/RustfavaExtTest.html +45 -0
- rustfava/ext/rustfava_ext_test/templates/RustfavaExtTestInclude.html +1 -0
- rustfava/help/__init__.py +15 -0
- rustfava/help/_index.md +29 -0
- rustfava/help/beancount_syntax.md +156 -0
- rustfava/help/budgets.md +31 -0
- rustfava/help/conversion.md +29 -0
- rustfava/help/extensions.md +111 -0
- rustfava/help/features.md +179 -0
- rustfava/help/filters.md +103 -0
- rustfava/help/import.md +27 -0
- rustfava/help/options.md +289 -0
- rustfava/helpers.py +30 -0
- rustfava/internal_api.py +221 -0
- rustfava/json_api.py +952 -0
- rustfava/plugins/__init__.py +3 -0
- rustfava/plugins/link_documents.py +107 -0
- rustfava/plugins/tag_discovered_documents.py +44 -0
- rustfava/py.typed +0 -0
- rustfava/rustledger/__init__.py +31 -0
- rustfava/rustledger/constants.py +76 -0
- rustfava/rustledger/engine.py +485 -0
- rustfava/rustledger/loader.py +273 -0
- rustfava/rustledger/options.py +202 -0
- rustfava/rustledger/query.py +331 -0
- rustfava/rustledger/types.py +830 -0
- rustfava/serialisation.py +220 -0
- rustfava/static/app.css +2988 -0
- rustfava/static/app.css.map +7 -0
- rustfava/static/app.js +12854 -0
- rustfava/static/app.js.map +7 -0
- rustfava/static/beancount-JFV44ZVZ.css +5 -0
- rustfava/static/beancount-JFV44ZVZ.css.map +7 -0
- rustfava/static/beancount-VTTKRGSK.js +4642 -0
- rustfava/static/beancount-VTTKRGSK.js.map +7 -0
- rustfava/static/bql-MGFRUMBP.js +333 -0
- rustfava/static/bql-MGFRUMBP.js.map +7 -0
- rustfava/static/chunk-E7ZF4ASL.js +23061 -0
- rustfava/static/chunk-E7ZF4ASL.js.map +7 -0
- rustfava/static/chunk-V24TLQHT.js +12673 -0
- rustfava/static/chunk-V24TLQHT.js.map +7 -0
- rustfava/static/favicon.ico +0 -0
- rustfava/static/fira-mono-cyrillic-400-normal-BLAGXRCE.woff2 +0 -0
- rustfava/static/fira-mono-cyrillic-500-normal-EN7JUAAW.woff2 +0 -0
- rustfava/static/fira-mono-cyrillic-ext-400-normal-EX7VARTS.woff2 +0 -0
- rustfava/static/fira-mono-cyrillic-ext-500-normal-ZDPTUPRR.woff2 +0 -0
- rustfava/static/fira-mono-greek-400-normal-COGHKMOA.woff2 +0 -0
- rustfava/static/fira-mono-greek-500-normal-4EN2PKZT.woff2 +0 -0
- rustfava/static/fira-mono-greek-ext-400-normal-DYEQIJH7.woff2 +0 -0
- rustfava/static/fira-mono-greek-ext-500-normal-SG73CVKQ.woff2 +0 -0
- rustfava/static/fira-mono-latin-400-normal-NA3VLV7E.woff2 +0 -0
- rustfava/static/fira-mono-latin-500-normal-YC77GFWD.woff2 +0 -0
- rustfava/static/fira-mono-latin-ext-400-normal-DIKTZ5PW.woff2 +0 -0
- rustfava/static/fira-mono-latin-ext-500-normal-ZWY4UO4V.woff2 +0 -0
- rustfava/static/fira-mono-symbols2-400-normal-UITXT77Q.woff2 +0 -0
- rustfava/static/fira-mono-symbols2-500-normal-VWPC2EFN.woff2 +0 -0
- rustfava/static/fira-sans-cyrillic-400-normal-KLQMBCA6.woff2 +0 -0
- rustfava/static/fira-sans-cyrillic-500-normal-NFG7UD6J.woff2 +0 -0
- rustfava/static/fira-sans-cyrillic-ext-400-normal-GWO44OPC.woff2 +0 -0
- rustfava/static/fira-sans-cyrillic-ext-500-normal-SP47E5SC.woff2 +0 -0
- rustfava/static/fira-sans-greek-400-normal-UMQBTLC3.woff2 +0 -0
- rustfava/static/fira-sans-greek-500-normal-4ZKHN4FQ.woff2 +0 -0
- rustfava/static/fira-sans-greek-ext-400-normal-O2DVJAJZ.woff2 +0 -0
- rustfava/static/fira-sans-greek-ext-500-normal-SK6GNWGO.woff2 +0 -0
- rustfava/static/fira-sans-latin-400-normal-OYYTPMAV.woff2 +0 -0
- rustfava/static/fira-sans-latin-500-normal-SMQPZW5A.woff2 +0 -0
- rustfava/static/fira-sans-latin-ext-400-normal-OAUP3WK5.woff2 +0 -0
- rustfava/static/fira-sans-latin-ext-500-normal-LY3YDR5Y.woff2 +0 -0
- rustfava/static/fira-sans-vietnamese-400-normal-OBMQ72MR.woff2 +0 -0
- rustfava/static/fira-sans-vietnamese-500-normal-Y4NZR5EU.woff2 +0 -0
- rustfava/static/source-code-pro-cyrillic-400-normal-TO22V6M3.woff2 +0 -0
- rustfava/static/source-code-pro-cyrillic-500-normal-OGBWWWYW.woff2 +0 -0
- rustfava/static/source-code-pro-cyrillic-ext-400-normal-XH44UCIA.woff2 +0 -0
- rustfava/static/source-code-pro-cyrillic-ext-500-normal-3Z6MMVM6.woff2 +0 -0
- rustfava/static/source-code-pro-greek-400-normal-OUXXUQWK.woff2 +0 -0
- rustfava/static/source-code-pro-greek-500-normal-JA2Z5UXO.woff2 +0 -0
- rustfava/static/source-code-pro-greek-ext-400-normal-WCDKMX7U.woff2 +0 -0
- rustfava/static/source-code-pro-greek-ext-500-normal-ZHVI4VKW.woff2 +0 -0
- rustfava/static/source-code-pro-latin-400-normal-QOGTXED5.woff2 +0 -0
- rustfava/static/source-code-pro-latin-500-normal-X57QEOLQ.woff2 +0 -0
- rustfava/static/source-code-pro-latin-ext-400-normal-QXC74NBF.woff2 +0 -0
- rustfava/static/source-code-pro-latin-ext-500-normal-QGOY7MTT.woff2 +0 -0
- rustfava/static/source-code-pro-vietnamese-400-normal-NPDCDTBA.woff2 +0 -0
- rustfava/static/source-code-pro-vietnamese-500-normal-M6PJKTR5.woff2 +0 -0
- rustfava/static/tree-sitter-beancount-MLXFQBZ5.wasm +0 -0
- rustfava/static/web-tree-sitter-RNOQ6E74.wasm +0 -0
- rustfava/template_filters.py +64 -0
- rustfava/templates/_journal_table.html +156 -0
- rustfava/templates/_layout.html +26 -0
- rustfava/templates/_query_table.html +88 -0
- rustfava/templates/beancount_file +18 -0
- rustfava/templates/help.html +23 -0
- rustfava/templates/macros/_account_macros.html +5 -0
- rustfava/templates/macros/_commodity_macros.html +13 -0
- rustfava/translations/bg/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/bg/LC_MESSAGES/messages.po +618 -0
- rustfava/translations/ca/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/ca/LC_MESSAGES/messages.po +618 -0
- rustfava/translations/de/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/de/LC_MESSAGES/messages.po +618 -0
- rustfava/translations/es/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/es/LC_MESSAGES/messages.po +619 -0
- rustfava/translations/fa/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/fa/LC_MESSAGES/messages.po +618 -0
- rustfava/translations/fr/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/fr/LC_MESSAGES/messages.po +618 -0
- rustfava/translations/ja/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/ja/LC_MESSAGES/messages.po +618 -0
- rustfava/translations/nl/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/nl/LC_MESSAGES/messages.po +617 -0
- rustfava/translations/pt/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/pt/LC_MESSAGES/messages.po +617 -0
- rustfava/translations/pt_BR/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/pt_BR/LC_MESSAGES/messages.po +618 -0
- rustfava/translations/ru/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/ru/LC_MESSAGES/messages.po +617 -0
- rustfava/translations/sk/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/sk/LC_MESSAGES/messages.po +623 -0
- rustfava/translations/sv/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/sv/LC_MESSAGES/messages.po +618 -0
- rustfava/translations/uk/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/uk/LC_MESSAGES/messages.po +618 -0
- rustfava/translations/zh/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/zh/LC_MESSAGES/messages.po +618 -0
- rustfava/translations/zh_Hant_TW/LC_MESSAGES/messages.mo +0 -0
- rustfava/translations/zh_Hant_TW/LC_MESSAGES/messages.po +618 -0
- rustfava/util/__init__.py +157 -0
- rustfava/util/date.py +576 -0
- rustfava/util/excel.py +118 -0
- rustfava/util/ranking.py +79 -0
- rustfava/util/sets.py +18 -0
- rustfava/util/unreachable.py +20 -0
- rustfava-0.1.0.dist-info/METADATA +102 -0
- rustfava-0.1.0.dist-info/RECORD +187 -0
- rustfava-0.1.0.dist-info/WHEEL +5 -0
- rustfava-0.1.0.dist-info/entry_points.txt +2 -0
- rustfava-0.1.0.dist-info/licenses/AUTHORS +11 -0
- rustfava-0.1.0.dist-info/licenses/LICENSE +21 -0
- rustfava-0.1.0.dist-info/top_level.txt +1 -0
rustfava/help/options.md
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
# Options
|
|
2
|
+
|
|
3
|
+
To customize some of rustfava's behaviour, you can add custom entries like the
|
|
4
|
+
following to your Beancount file.
|
|
5
|
+
|
|
6
|
+
<pre><textarea is="beancount-textarea">
|
|
7
|
+
2016-06-14 custom "fava-option" "default-file"
|
|
8
|
+
2016-04-14 custom "fava-option" "auto-reload" "true"
|
|
9
|
+
2016-04-14 custom "fava-option" "currency-column" "100"</textarea></pre>
|
|
10
|
+
|
|
11
|
+
Below is a list of all possible options for rustfava.
|
|
12
|
+
|
|
13
|
+
______________________________________________________________________
|
|
14
|
+
|
|
15
|
+
## `language`
|
|
16
|
+
|
|
17
|
+
Default: Not set
|
|
18
|
+
|
|
19
|
+
If this setting is not specified, rustfava will try to guess the language from your
|
|
20
|
+
browser settings. Rustfava currently ships translations into the following
|
|
21
|
+
languages:
|
|
22
|
+
|
|
23
|
+
- Bulgarian (`bg`)
|
|
24
|
+
- Catalan (`ca`)
|
|
25
|
+
- Chinese (`zh_CN` and `zh_TW`)
|
|
26
|
+
- Dutch (`nl`)
|
|
27
|
+
- English (`en`)
|
|
28
|
+
- French (`fr`)
|
|
29
|
+
- German (`de`)
|
|
30
|
+
- Japanese (`ja`)
|
|
31
|
+
- Persian (`fa`)
|
|
32
|
+
- Portuguese (`pt` and `pt_BR`)
|
|
33
|
+
- Russian (`ru`)
|
|
34
|
+
- Slovak (`sk`)
|
|
35
|
+
- Spanish (`es`)
|
|
36
|
+
- Swedish (`sv`)
|
|
37
|
+
- Ukrainian (`uk`)
|
|
38
|
+
|
|
39
|
+
______________________________________________________________________
|
|
40
|
+
|
|
41
|
+
## `locale`
|
|
42
|
+
|
|
43
|
+
Default: Not set or `en` if the Beancount `render_commas` option is set.
|
|
44
|
+
|
|
45
|
+
This sets the locale that is used to render out numbers. For example, with the
|
|
46
|
+
locale `en_IN` the number `1111111.33` will be rendered `11,11,111.33`,
|
|
47
|
+
`1,111,111.33` with locale `en`, or `1.111.111,33` with locale `de`.
|
|
48
|
+
|
|
49
|
+
______________________________________________________________________
|
|
50
|
+
|
|
51
|
+
## `default-file`
|
|
52
|
+
|
|
53
|
+
Use this option to specify a default file for the editor to open. This option
|
|
54
|
+
may optionally take a value of a filename to be the default. If you don't
|
|
55
|
+
provide a filename, the file this custom option is in is used.
|
|
56
|
+
|
|
57
|
+
______________________________________________________________________
|
|
58
|
+
|
|
59
|
+
## `default-page`
|
|
60
|
+
|
|
61
|
+
Default: `income_statement/`
|
|
62
|
+
|
|
63
|
+
Use this option to specify the page to be redirected to when visiting rustfava. If
|
|
64
|
+
this option is not specified, you are taken to the income statement. You may
|
|
65
|
+
also use this option to set filters. For example, a `default-page` of
|
|
66
|
+
`balance_sheet/?time=year-2+-+year` would result in you being redirected to a
|
|
67
|
+
balance sheet reporting the current year and the two previous years.
|
|
68
|
+
|
|
69
|
+
Note that the supplied path is relative. It is probably easiest to navigate to
|
|
70
|
+
the URL in your browser and copy the portion of the URL after the 'title' of
|
|
71
|
+
your beancount file into this option.
|
|
72
|
+
|
|
73
|
+
______________________________________________________________________
|
|
74
|
+
|
|
75
|
+
## `fiscal-year-end`
|
|
76
|
+
|
|
77
|
+
Default: `12-31`
|
|
78
|
+
|
|
79
|
+
The last day of the fiscal (financial or tax) period for accounting purposes in
|
|
80
|
+
`%m-%d` format. Allows for the use of `FY2018`, `FY2018-Q3`, `fiscal_year` and
|
|
81
|
+
`fiscal_quarter` in the time filter, and `FY2018` as the start date, end date,
|
|
82
|
+
or both dates in a date range in the time filter. Month can be a value larger
|
|
83
|
+
than `12` to have `FY2018` end in 2019 for example.
|
|
84
|
+
|
|
85
|
+
Examples are:
|
|
86
|
+
|
|
87
|
+
- `04-05` - UK
|
|
88
|
+
- `06-30` - Australia / NZ
|
|
89
|
+
- `09-30` - US federal government
|
|
90
|
+
- `15-31` - Japan
|
|
91
|
+
|
|
92
|
+
See [Fiscal Year on WikiPedia](https://en.wikipedia.org/wiki/Fiscal_year) for
|
|
93
|
+
more examples.
|
|
94
|
+
|
|
95
|
+
______________________________________________________________________
|
|
96
|
+
|
|
97
|
+
## `indent`
|
|
98
|
+
|
|
99
|
+
Default: 2.
|
|
100
|
+
|
|
101
|
+
The number spaces for indentation.
|
|
102
|
+
|
|
103
|
+
______________________________________________________________________
|
|
104
|
+
|
|
105
|
+
## `insert-entry`
|
|
106
|
+
|
|
107
|
+
Default: Not set.
|
|
108
|
+
|
|
109
|
+
This option can be used to specify where entries are inserted. The argument to
|
|
110
|
+
this option should be a regular expression matching account names. This option
|
|
111
|
+
can be given multiple times. When adding an entry, the account of the entry (for
|
|
112
|
+
a transaction, the account of the last posting is used) is matched against all
|
|
113
|
+
`insert-entry` options and the entry will be inserted before the datewise latest
|
|
114
|
+
of the matching options before the entry date. If the entry is a Transaction and
|
|
115
|
+
no `insert-entry` option matches the account of the last posting the account of
|
|
116
|
+
the second to last posting and so on will be tried. If no `insert-entry` option
|
|
117
|
+
matches or none is given, the entry will be inserted at the end of the default
|
|
118
|
+
file.
|
|
119
|
+
|
|
120
|
+
______________________________________________________________________
|
|
121
|
+
|
|
122
|
+
## `auto-reload`
|
|
123
|
+
|
|
124
|
+
Default: `false`
|
|
125
|
+
|
|
126
|
+
Set this to `true` to make rustfava automatically reload the page whenever a file
|
|
127
|
+
changes is detected. By default only a notification is shown which you can click
|
|
128
|
+
to reload the page. If the file change is due to user interaction, e.g.,
|
|
129
|
+
uploading a document or adding a transaction, rustfava will always reload the page
|
|
130
|
+
automatically.
|
|
131
|
+
|
|
132
|
+
______________________________________________________________________
|
|
133
|
+
|
|
134
|
+
## `unrealized`
|
|
135
|
+
|
|
136
|
+
Default: `Unrealized`
|
|
137
|
+
|
|
138
|
+
The subaccount of the Equity account to post unrealized gains to if the account
|
|
139
|
+
trees are shown at market value.
|
|
140
|
+
|
|
141
|
+
______________________________________________________________________
|
|
142
|
+
|
|
143
|
+
## `currency-column`
|
|
144
|
+
|
|
145
|
+
Default: `61`
|
|
146
|
+
|
|
147
|
+
This option can be used to configure how posting lines are aligned when saved to
|
|
148
|
+
file or when using 'Align Amounts' in the editor. rustfava tries to align so that
|
|
149
|
+
the currencies all occur in the given column. Also, rustfava will show a vertical
|
|
150
|
+
line before this column in the editor.
|
|
151
|
+
|
|
152
|
+
______________________________________________________________________
|
|
153
|
+
|
|
154
|
+
## `sidebar-show-queries`
|
|
155
|
+
|
|
156
|
+
Default: `5`
|
|
157
|
+
|
|
158
|
+
The maximum number of queries to link to in the sidebar. Set this value to `0`
|
|
159
|
+
to hide the links altogether.
|
|
160
|
+
|
|
161
|
+
______________________________________________________________________
|
|
162
|
+
|
|
163
|
+
## `upcoming-events`
|
|
164
|
+
|
|
165
|
+
Default: `7`
|
|
166
|
+
|
|
167
|
+
Show a notification bubble in the sidebar displaying the number of events less
|
|
168
|
+
than `upcoming-events` days away. Set this value to `0` to disable this feature.
|
|
169
|
+
|
|
170
|
+
______________________________________________________________________
|
|
171
|
+
|
|
172
|
+
## `show-closed-accounts`
|
|
173
|
+
|
|
174
|
+
Default: `false`
|
|
175
|
+
|
|
176
|
+
## `show-accounts-with-zero-transactions`
|
|
177
|
+
|
|
178
|
+
Default: `true`
|
|
179
|
+
|
|
180
|
+
## `show-accounts-with-zero-balance`
|
|
181
|
+
|
|
182
|
+
Default: `true`
|
|
183
|
+
|
|
184
|
+
These three options specify which accounts (not) to show in the account trees,
|
|
185
|
+
like on the income statement. Accounts with a non-zero balance will always be
|
|
186
|
+
shown.
|
|
187
|
+
|
|
188
|
+
______________________________________________________________________
|
|
189
|
+
|
|
190
|
+
## `collapse-pattern`
|
|
191
|
+
|
|
192
|
+
Default: Not set
|
|
193
|
+
|
|
194
|
+
This option is used to specify accounts that will be collapsed in the displayed
|
|
195
|
+
account trees. The argument to this option is a regular expression matching
|
|
196
|
+
account names. This option can be specified multiple times.
|
|
197
|
+
|
|
198
|
+
Collapsing all accounts below a specific depth in the account tree can be
|
|
199
|
+
accomplished by a regex such as: `.*:.*:.*` (this example collapses all accounts
|
|
200
|
+
that are three levels deep).
|
|
201
|
+
|
|
202
|
+
______________________________________________________________________
|
|
203
|
+
|
|
204
|
+
## `use-external-editor`
|
|
205
|
+
|
|
206
|
+
Default: `false`
|
|
207
|
+
|
|
208
|
+
If `true`, instead of using the internal editor, the `beancount://` URL scheme
|
|
209
|
+
is used. See the
|
|
210
|
+
[Beancount urlscheme](https://github.com/aumayr/beancount_urlscheme) project for
|
|
211
|
+
details.
|
|
212
|
+
|
|
213
|
+
______________________________________________________________________
|
|
214
|
+
|
|
215
|
+
## `account-journal-include-children`
|
|
216
|
+
|
|
217
|
+
Default: `true`
|
|
218
|
+
|
|
219
|
+
This determines if the journal in the account report includes entries of
|
|
220
|
+
sub-accounts.
|
|
221
|
+
|
|
222
|
+
______________________________________________________________________
|
|
223
|
+
|
|
224
|
+
## `uptodate-indicator-grey-lookback-days`
|
|
225
|
+
|
|
226
|
+
Default: `60`
|
|
227
|
+
|
|
228
|
+
If there has been no activity in given number of days since the last balance
|
|
229
|
+
entry, then the grey uptodate-indicator is shown.
|
|
230
|
+
|
|
231
|
+
______________________________________________________________________
|
|
232
|
+
|
|
233
|
+
## `import-config`
|
|
234
|
+
|
|
235
|
+
Default: Not set
|
|
236
|
+
|
|
237
|
+
Path to a Beancount import configuration file. See the [Import](./import) help
|
|
238
|
+
page for details.
|
|
239
|
+
|
|
240
|
+
______________________________________________________________________
|
|
241
|
+
|
|
242
|
+
## `import-dirs`
|
|
243
|
+
|
|
244
|
+
Default: Not set
|
|
245
|
+
|
|
246
|
+
Set a directory to be scanned by the Beancount import mechanism. This option can
|
|
247
|
+
be specified multiple times to add multiple directories.
|
|
248
|
+
|
|
249
|
+
______________________________________________________________________
|
|
250
|
+
|
|
251
|
+
## `invert-gains-losses-colors`
|
|
252
|
+
|
|
253
|
+
Default: `false`
|
|
254
|
+
|
|
255
|
+
By default, rustfava uses green for unrealized gains (positive values) and red for
|
|
256
|
+
unrealized losses (negative values) in the Balance Sheet and Trial Balance when
|
|
257
|
+
displaying at market value.
|
|
258
|
+
|
|
259
|
+
Set this to `true` to invert the color scheme, using red for gains and green for
|
|
260
|
+
losses. This is useful for users from regions where the opposite convention is
|
|
261
|
+
used, such as Chinese stock markets where red represents gains and green
|
|
262
|
+
represents losses.
|
|
263
|
+
|
|
264
|
+
______________________________________________________________________
|
|
265
|
+
|
|
266
|
+
## `invert-income-liabilities-equity`
|
|
267
|
+
|
|
268
|
+
Default: False
|
|
269
|
+
|
|
270
|
+
In Beancount the Income, Liabilities and Equity accounts tend to have a negative
|
|
271
|
+
balance (see
|
|
272
|
+
[Types of Accounts](https://beancount.github.io/docs/the_double_entry_counting_method.html#types-of-accounts)).
|
|
273
|
+
|
|
274
|
+
This rustfava option flips the sign of these three accounts in the income statement
|
|
275
|
+
and the balance sheet. This way, the net profit chart will show positive numbers
|
|
276
|
+
if the income is greater than the expenses for a given timespan.
|
|
277
|
+
|
|
278
|
+
Note: To keep consistency with the internal accounting of beancount, the journal
|
|
279
|
+
and the individual account pages are not affected by this configuration option.
|
|
280
|
+
|
|
281
|
+
______________________________________________________________________
|
|
282
|
+
|
|
283
|
+
## `conversion-currencies`
|
|
284
|
+
|
|
285
|
+
Default: Not set
|
|
286
|
+
|
|
287
|
+
When set, the currency conversion select dropdown in all charts will show the
|
|
288
|
+
list of currencies specified in this option. By default, rustfava lists all
|
|
289
|
+
operating currencies and those currencies that match ISO 4217 currency codes.
|
rustfava/helpers.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Exceptions and module base class."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING: # pragma: no cover
|
|
9
|
+
from rustfava.beans.abc import Directive
|
|
10
|
+
from rustfava.beans.abc import Meta
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True, slots=True)
|
|
14
|
+
class BeancountError:
|
|
15
|
+
"""Dataclass for a Beancount-style error."""
|
|
16
|
+
|
|
17
|
+
source: Meta | None
|
|
18
|
+
message: str
|
|
19
|
+
entry: Directive | None
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class RustfavaAPIError(Exception):
|
|
23
|
+
"""Fava's base exception class."""
|
|
24
|
+
|
|
25
|
+
def __init__(self, message: str) -> None:
|
|
26
|
+
super().__init__()
|
|
27
|
+
self.message = message
|
|
28
|
+
|
|
29
|
+
def __str__(self) -> str:
|
|
30
|
+
return self.message
|
rustfava/internal_api.py
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
"""Internal API.
|
|
2
|
+
|
|
3
|
+
This is used to pre-process some data that is used in the templates, allowing
|
|
4
|
+
this part of the functionality to be tested and allowing some end-to-end tests
|
|
5
|
+
for the frontend data validation.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from typing import TYPE_CHECKING
|
|
12
|
+
|
|
13
|
+
from flask import current_app
|
|
14
|
+
from flask import url_for
|
|
15
|
+
from flask_babel import gettext
|
|
16
|
+
|
|
17
|
+
from rustfava.context import g
|
|
18
|
+
from rustfava.util.excel import HAVE_EXCEL
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING: # pragma: no cover
|
|
21
|
+
from collections.abc import Sequence
|
|
22
|
+
from typing import Literal
|
|
23
|
+
|
|
24
|
+
from rustfava.beans.abc import Meta
|
|
25
|
+
from rustfava.beans.abc import Query
|
|
26
|
+
from rustfava.core.accounts import AccountDict
|
|
27
|
+
from rustfava.core.charts import DateAndBalance
|
|
28
|
+
from rustfava.core.charts import DateAndBalanceWithBudget
|
|
29
|
+
from rustfava.core.extensions import ExtensionDetails
|
|
30
|
+
from rustfava.core.fava_options import RustfavaOptions
|
|
31
|
+
from rustfava.core.tree import SerialisedTreeNode
|
|
32
|
+
from rustfava.helpers import BeancountError
|
|
33
|
+
from rustfava.util.date import Interval
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dataclass(frozen=True)
|
|
37
|
+
class SerialisedError:
|
|
38
|
+
"""A Beancount error, as passed to the frontend."""
|
|
39
|
+
|
|
40
|
+
type: str
|
|
41
|
+
source: Meta | None
|
|
42
|
+
message: str
|
|
43
|
+
|
|
44
|
+
@staticmethod
|
|
45
|
+
def from_beancount_error(err: BeancountError) -> SerialisedError:
|
|
46
|
+
"""Get a serialisable error from a Beancount error."""
|
|
47
|
+
source = dict(err.source) if err.source is not None else None
|
|
48
|
+
if source is not None:
|
|
49
|
+
source.pop("__tolerances__", None)
|
|
50
|
+
return SerialisedError(err.__class__.__name__, source, err.message)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@dataclass(frozen=True)
|
|
54
|
+
class LedgerData:
|
|
55
|
+
"""This is used as report-independent data in the frontend."""
|
|
56
|
+
|
|
57
|
+
accounts: Sequence[str]
|
|
58
|
+
account_details: AccountDict
|
|
59
|
+
base_url: str
|
|
60
|
+
currencies: Sequence[str]
|
|
61
|
+
currency_names: dict[str, str]
|
|
62
|
+
errors: Sequence[SerialisedError]
|
|
63
|
+
fava_options: RustfavaOptions
|
|
64
|
+
incognito: bool
|
|
65
|
+
have_excel: bool
|
|
66
|
+
links: Sequence[str]
|
|
67
|
+
options: dict[str, str | Sequence[str]]
|
|
68
|
+
payees: Sequence[str]
|
|
69
|
+
precisions: dict[str, int]
|
|
70
|
+
tags: Sequence[str]
|
|
71
|
+
years: Sequence[str]
|
|
72
|
+
user_queries: Sequence[Query]
|
|
73
|
+
upcoming_events_count: int
|
|
74
|
+
extensions: Sequence[ExtensionDetails]
|
|
75
|
+
sidebar_links: Sequence[tuple[str, str]]
|
|
76
|
+
other_ledgers: Sequence[tuple[str, str]]
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def get_errors() -> list[SerialisedError]:
|
|
80
|
+
"""Serialise errors (do not pass entry as that might fail serialisation."""
|
|
81
|
+
return [SerialisedError.from_beancount_error(e) for e in g.ledger.errors]
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _get_options() -> dict[str, str | Sequence[str]]:
|
|
85
|
+
options = g.ledger.options
|
|
86
|
+
return {
|
|
87
|
+
"documents": options["documents"],
|
|
88
|
+
"filename": options["filename"],
|
|
89
|
+
"include": options["include"],
|
|
90
|
+
"operating_currency": options["operating_currency"],
|
|
91
|
+
"title": options["title"],
|
|
92
|
+
"name_assets": options["name_assets"],
|
|
93
|
+
"name_liabilities": options["name_liabilities"],
|
|
94
|
+
"name_equity": options["name_equity"],
|
|
95
|
+
"name_income": options["name_income"],
|
|
96
|
+
"name_expenses": options["name_expenses"],
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def get_ledger_data() -> LedgerData:
|
|
101
|
+
"""Get the report-independent ledger data."""
|
|
102
|
+
ledger = g.ledger
|
|
103
|
+
all_queries = ledger.all_entries_by_type.Query
|
|
104
|
+
|
|
105
|
+
return LedgerData(
|
|
106
|
+
ledger.attributes.accounts,
|
|
107
|
+
ledger.accounts,
|
|
108
|
+
url_for("index"),
|
|
109
|
+
ledger.attributes.currencies,
|
|
110
|
+
ledger.commodities.names,
|
|
111
|
+
get_errors(),
|
|
112
|
+
ledger.fava_options,
|
|
113
|
+
current_app.config["INCOGNITO"],
|
|
114
|
+
HAVE_EXCEL,
|
|
115
|
+
ledger.attributes.links,
|
|
116
|
+
_get_options(),
|
|
117
|
+
ledger.attributes.payees,
|
|
118
|
+
ledger.format_decimal.precisions,
|
|
119
|
+
ledger.attributes.tags,
|
|
120
|
+
ledger.attributes.years,
|
|
121
|
+
all_queries[: ledger.fava_options.sidebar_show_queries],
|
|
122
|
+
len(ledger.misc.upcoming_events),
|
|
123
|
+
ledger.extensions.extension_details,
|
|
124
|
+
ledger.misc.sidebar_links,
|
|
125
|
+
[
|
|
126
|
+
(ledger.options["title"], url_for("index", bfile=file_slug))
|
|
127
|
+
for (file_slug, ledger) in current_app.config["LEDGERS"].items()
|
|
128
|
+
if file_slug != g.beancount_file_slug
|
|
129
|
+
],
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
@dataclass(frozen=True)
|
|
134
|
+
class BalancesChart:
|
|
135
|
+
"""Data for a balances chart."""
|
|
136
|
+
|
|
137
|
+
label: str
|
|
138
|
+
data: Sequence[DateAndBalance]
|
|
139
|
+
type: Literal["balances"] = "balances"
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
@dataclass(frozen=True)
|
|
143
|
+
class BarChart:
|
|
144
|
+
"""Data for a bar chart."""
|
|
145
|
+
|
|
146
|
+
label: str
|
|
147
|
+
data: Sequence[DateAndBalanceWithBudget]
|
|
148
|
+
type: Literal["bar"] = "bar"
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
@dataclass(frozen=True)
|
|
152
|
+
class HierarchyChart:
|
|
153
|
+
"""Data for a hierarchy chart."""
|
|
154
|
+
|
|
155
|
+
label: str
|
|
156
|
+
data: SerialisedTreeNode
|
|
157
|
+
type: Literal["hierarchy"] = "hierarchy"
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
if TYPE_CHECKING: # pragma: no cover
|
|
161
|
+
ChartData = BalancesChart | BarChart | HierarchyChart
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
class ChartApi:
|
|
165
|
+
"""Functions to generate chart data."""
|
|
166
|
+
|
|
167
|
+
@staticmethod
|
|
168
|
+
def account_balance(account_name: str) -> ChartData:
|
|
169
|
+
"""Generate data for an account balances chart."""
|
|
170
|
+
return BalancesChart(
|
|
171
|
+
gettext("Account Balance"),
|
|
172
|
+
g.ledger.charts.linechart(
|
|
173
|
+
g.filtered,
|
|
174
|
+
account_name,
|
|
175
|
+
g.conv,
|
|
176
|
+
),
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
@staticmethod
|
|
180
|
+
def hierarchy(
|
|
181
|
+
account_name: str,
|
|
182
|
+
*,
|
|
183
|
+
label: str | None = None,
|
|
184
|
+
) -> ChartData:
|
|
185
|
+
"""Generate data for an account hierarchy chart."""
|
|
186
|
+
return HierarchyChart(
|
|
187
|
+
label or account_name,
|
|
188
|
+
g.ledger.charts.hierarchy(
|
|
189
|
+
g.filtered,
|
|
190
|
+
account_name,
|
|
191
|
+
g.conv,
|
|
192
|
+
),
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
@staticmethod
|
|
196
|
+
def interval_totals(
|
|
197
|
+
interval: Interval,
|
|
198
|
+
account_name: str | tuple[str, ...],
|
|
199
|
+
label: str | None = None,
|
|
200
|
+
*,
|
|
201
|
+
invert: bool = False,
|
|
202
|
+
) -> ChartData:
|
|
203
|
+
"""Generate data for an account per interval chart."""
|
|
204
|
+
return BarChart(
|
|
205
|
+
label or str(account_name),
|
|
206
|
+
g.ledger.charts.interval_totals(
|
|
207
|
+
g.filtered,
|
|
208
|
+
interval,
|
|
209
|
+
account_name,
|
|
210
|
+
g.conv,
|
|
211
|
+
invert=invert,
|
|
212
|
+
),
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
@staticmethod
|
|
216
|
+
def net_worth() -> ChartData:
|
|
217
|
+
"""Generate data for net worth chart."""
|
|
218
|
+
return BalancesChart(
|
|
219
|
+
gettext("Net Worth"),
|
|
220
|
+
g.ledger.charts.net_worth(g.filtered, g.interval, g.conv),
|
|
221
|
+
)
|