hledger-forecast 1.5.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +17 -17
- data/README.md +7 -171
- data/example.journal +14 -14
- data/hledger-forecast.gemspec +1 -1
- data/lib/hledger_forecast/calculator.rb +5 -1
- data/lib/hledger_forecast/cli.rb +5 -18
- data/lib/hledger_forecast/generator.rb +52 -35
- data/lib/hledger_forecast/settings.rb +42 -27
- data/lib/hledger_forecast/summarizer.rb +28 -62
- data/lib/hledger_forecast/summarizer_formatter.rb +4 -4
- data/lib/hledger_forecast/transactions/default.rb +28 -57
- data/lib/hledger_forecast/transactions/trackers.rb +34 -40
- data/lib/hledger_forecast/utilities.rb +14 -0
- data/lib/hledger_forecast/version.rb +1 -1
- data/lib/hledger_forecast.rb +1 -2
- data/spec/cli_spec.rb +3 -12
- data/spec/computed_amounts_spec.rb +11 -22
- data/spec/custom_spec.rb +15 -35
- data/spec/half-yearly_spec.rb +6 -13
- data/spec/monthly_end_date_spec.rb +8 -18
- data/spec/monthly_end_date_transaction_spec.rb +20 -45
- data/spec/monthly_spec.rb +11 -28
- data/spec/once_spec.rb +6 -13
- data/spec/quarterly_spec.rb +5 -12
- data/spec/summarizer_spec.rb +11 -42
- data/spec/track_spec.rb +19 -49
- data/spec/verbose_output_spec.rb +3 -3
- data/spec/yearly_spec.rb +5 -12
- metadata +4 -13
- data/example.yml +0 -98
- data/lib/hledger_forecast/csv_parser.rb +0 -106
- data/spec/csv_and_yml_comparison_spec.rb +0 -32
- data/spec/csv_parser_spec.rb +0 -110
- data/spec/modifier_spec.rb +0 -102
- data/spec/stubs/forecast.yml +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6e94131797e8e2c866fa33adc9862c8b5d87dbbc2fa42609c0ea6fc5368a1675
|
4
|
+
data.tar.gz: dc2c4850cff76e74607481997975055e67973b6ea0058ee0193cfabaf888fd1a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9911b761e32f9b4e744fc8fd735d2d889dcde25933a7c514438cfcd79ccc2cff6269624aef20ba00c83a96e62c04c1d7c6179b685a738d3eb0df05d41b0bef59
|
7
|
+
data.tar.gz: 2a9fb8fc081ffe7b470ef23a649e3f1155c14556a452ef8adbf62efe4d23fd4df7ea6c06eec02fa069554db3e9bf1e2d368daa460db511423c5c9c990a39d92b
|
data/.rubocop.yml
CHANGED
@@ -4,20 +4,20 @@ AllCops:
|
|
4
4
|
Layout/LineLength:
|
5
5
|
Max: 120
|
6
6
|
|
7
|
-
Style/StringLiterals:
|
8
|
-
|
9
|
-
|
10
|
-
Style/RedundantReturn:
|
11
|
-
|
12
|
-
|
13
|
-
Metrics/ClassLength:
|
14
|
-
|
15
|
-
|
16
|
-
Metrics/MethodLength:
|
17
|
-
|
18
|
-
|
19
|
-
Metrics/AbcSize:
|
20
|
-
|
21
|
-
|
22
|
-
Style/NumericPredicate:
|
23
|
-
|
7
|
+
# Style/StringLiterals:
|
8
|
+
# Enabled: false
|
9
|
+
#
|
10
|
+
# Style/RedundantReturn:
|
11
|
+
# Enabled: false
|
12
|
+
#
|
13
|
+
# Metrics/ClassLength:
|
14
|
+
# Enabled: False
|
15
|
+
#
|
16
|
+
# Metrics/MethodLength:
|
17
|
+
# Enabled: False
|
18
|
+
#
|
19
|
+
# Metrics/AbcSize:
|
20
|
+
# Enabled: False
|
21
|
+
#
|
22
|
+
# Style/NumericPredicate:
|
23
|
+
# Enabled: False
|
data/README.md
CHANGED
@@ -11,13 +11,13 @@
|
|
11
11
|
<a href="https://github.com/olimorris/hledger-forecast/actions/workflows/test.yml"><img src="https://img.shields.io/github/actions/workflow/status/olimorris/hledger-forecast/test.yml?branch=main&label=tests&style=for-the-badge"></a>
|
12
12
|
</p>
|
13
13
|
|
14
|
-
**"Improved", you say?** Using a _CSV_
|
14
|
+
**"Improved", you say?** Using a _CSV_ file, forecasts can be quickly generated into a _journal_ file ready to be fed into [hledger](https://github.com/simonmichael/hledger). **A 16 line [CSV file](https://github.com/olimorris/hledger-forecast/blob/main/example.csv) can generate a 46 line hledger [forecast file](https://github.com/olimorris/hledger-forecast/blob/main/example.journal)!**
|
15
15
|
|
16
16
|
Forecasts can also be constrained between dates, inflated by modifiers, tracked until they appear in your bank statements and summarized into your own daily/weekly/monthly/yearly personal forecast income and expenditure statement.
|
17
17
|
|
18
18
|
## :sparkles: Features
|
19
19
|
|
20
|
-
- :rocket: Uses a simple CSV
|
20
|
+
- :rocket: Uses a simple CSV file to generate forecasts which can be used with hledger
|
21
21
|
- :calendar: Can smartly track forecasts against your bank statement
|
22
22
|
- :dollar: Can automatically apply modifiers such as inflation/deflation to forecasts
|
23
23
|
- :mag: Enables the use of maths in your forecasts (for amounts and dates)
|
@@ -62,13 +62,13 @@ The available options are:
|
|
62
62
|
|
63
63
|
### Generate command
|
64
64
|
|
65
|
-
The `hledger-forecast generate` command will generate a forecast _from_ a `CSV`
|
65
|
+
The `hledger-forecast generate` command will generate a forecast _from_ a `CSV` file _to_ a journal file. You can see the output of this command in the [example.journal](https://github.com/olimorris/hledger-forecast/blob/main/example.journal) file.
|
66
66
|
|
67
67
|
The available options are:
|
68
68
|
|
69
69
|
Usage: hledger-forecast generate [options]
|
70
70
|
|
71
|
-
-f, --forecast FILE The path to the FORECAST CSV
|
71
|
+
-f, --forecast FILE The path to the FORECAST CSV file to generate from
|
72
72
|
-o, --output-file FILE The path to the OUTPUT file to create
|
73
73
|
-t, --transaction FILE The path to the TRANSACTION journal file
|
74
74
|
-v, --verbose Don't group transactions by type in the output file
|
@@ -78,7 +78,7 @@ The available options are:
|
|
78
78
|
|
79
79
|
> **Note**: For the tracking of transactions you need to include the `-t` flag
|
80
80
|
|
81
|
-
Running the command with no options will assume a `forecast.
|
81
|
+
Running the command with no options will assume a `forecast.csv` file exists.
|
82
82
|
|
83
83
|
### Using with hledger
|
84
84
|
|
@@ -100,7 +100,7 @@ The available options are:
|
|
100
100
|
|
101
101
|
Usage: hledger-forecast summarize [options]
|
102
102
|
|
103
|
-
-f, --forecast FILE The path to the FORECAST CSV
|
103
|
+
-f, --forecast FILE The path to the FORECAST CSV file to summarize
|
104
104
|
-r, --roll-up PERIOD The period to roll-up your forecasts into. One of:
|
105
105
|
[yearly], [half-yearly], [quarterly], [monthly], [weekly], [daily]
|
106
106
|
-v, --verbose Show additional information in the summary
|
@@ -138,7 +138,7 @@ The _CSV_ file _should_ contain a header row with the following columns:
|
|
138
138
|
- `summary_exclude` - (boolean) _(optional)_ - Exclude the transaction from the summarizer?
|
139
139
|
- `track` - (boolean) _(optional)_ - Track the transaction against your confirmed transactions?
|
140
140
|
|
141
|
-
###
|
141
|
+
### Example forecast
|
142
142
|
|
143
143
|
Putting it together, we end up with a CSV file like:
|
144
144
|
|
@@ -198,157 +198,6 @@ settings,show_symbol,true,,,,,,,,
|
|
198
198
|
settings,thousands_separator,true,,,,,,,,
|
199
199
|
```
|
200
200
|
|
201
|
-
### An example YML forecast
|
202
|
-
|
203
|
-
> **Note**: The app uses `yml` in place of `yaml` by default
|
204
|
-
|
205
|
-
Taking the _CSV_ example above and applying it to a _YML_ file:
|
206
|
-
|
207
|
-
```yml
|
208
|
-
monthly:
|
209
|
-
- account: "Assets:Bank"
|
210
|
-
from: "2023-03-01"
|
211
|
-
transactions:
|
212
|
-
- amount: -3500
|
213
|
-
category: "Income:Salary"
|
214
|
-
description: Salary
|
215
|
-
- amount: 2000
|
216
|
-
category: "Expenses:Mortgage"
|
217
|
-
description: Mortgage
|
218
|
-
to: "2025-01-01"
|
219
|
-
- amount: 175
|
220
|
-
category: "Expenses:Bills"
|
221
|
-
description: Bills
|
222
|
-
- amount: 500
|
223
|
-
category: "Expenses:Food"
|
224
|
-
description: Food
|
225
|
-
- amount: "=5000/24"
|
226
|
-
category: "Expenses:House"
|
227
|
-
description: New Kitchen
|
228
|
-
- amount: 125
|
229
|
-
category: "Expenses:Holiday"
|
230
|
-
description: Holiday
|
231
|
-
to: "=12"
|
232
|
-
- account: "Assets:Bank"
|
233
|
-
from: "2023-03-01"
|
234
|
-
to: "2025-01-01"
|
235
|
-
transactions:
|
236
|
-
- amount: 300
|
237
|
-
category: "Assets:Savings"
|
238
|
-
description: "Rainy day fund"
|
239
|
-
- account: "Assets:Pension"
|
240
|
-
from: "2024-01-01"
|
241
|
-
transactions:
|
242
|
-
- amount: -500
|
243
|
-
category: "Income:Pension"
|
244
|
-
description: Pension draw down
|
245
|
-
|
246
|
-
quarterly:
|
247
|
-
- account: "Assets:Bank"
|
248
|
-
from: "2023-04-01"
|
249
|
-
transactions:
|
250
|
-
- amount: -1000.00
|
251
|
-
category: "Income:Bonus"
|
252
|
-
description: Quarterly bonus
|
253
|
-
|
254
|
-
half-yearly:
|
255
|
-
- account: "Assets:Bank"
|
256
|
-
from: "2023-04-01"
|
257
|
-
transactions:
|
258
|
-
- amount: 500
|
259
|
-
category: "Expenses:Holiday"
|
260
|
-
description: Top up holiday funds
|
261
|
-
|
262
|
-
yearly:
|
263
|
-
- account: "Assets:Bank"
|
264
|
-
from: "2023-04-01"
|
265
|
-
transactions:
|
266
|
-
- amount: -2000.00
|
267
|
-
category: "Income:Bonus"
|
268
|
-
description: Annual Bonus
|
269
|
-
|
270
|
-
once:
|
271
|
-
- account: "Assets:Bank"
|
272
|
-
from: "2023-03-05"
|
273
|
-
transactions:
|
274
|
-
- amount: -3000
|
275
|
-
category: "Expenses:Shopping"
|
276
|
-
description: Refund for that damn laptop
|
277
|
-
summary_exclude: true
|
278
|
-
track: true
|
279
|
-
|
280
|
-
custom:
|
281
|
-
- account: "Assets:Bank"
|
282
|
-
from: "2023-03-01"
|
283
|
-
transactions:
|
284
|
-
- amount: 80
|
285
|
-
category: "Expenses:Personal Care"
|
286
|
-
description: Hair and beauty
|
287
|
-
frequency: "every 2 weeks"
|
288
|
-
roll-up: 26
|
289
|
-
- amount: 30
|
290
|
-
category: "Expenses:General Expenses"
|
291
|
-
description: Misc expenses
|
292
|
-
frequency: "every 5 weeks"
|
293
|
-
roll-up: 10.4
|
294
|
-
|
295
|
-
settings:
|
296
|
-
currency: USD
|
297
|
-
```
|
298
|
-
|
299
|
-
#### Modifiers
|
300
|
-
|
301
|
-
> **Note**: For modifiers to be included in your hledger reporting, use the `--auto` flag
|
302
|
-
|
303
|
-
Currently, a YML forecast allows a user to include forecasted % uplifts or downshifts:
|
304
|
-
|
305
|
-
```yml
|
306
|
-
monthly:
|
307
|
-
- account: "Assets:Bank"
|
308
|
-
from: "2023-03-01"
|
309
|
-
transactions:
|
310
|
-
- amount: 500
|
311
|
-
category: "Expenses:Food"
|
312
|
-
description: Food
|
313
|
-
modifiers:
|
314
|
-
- amount: 0.02
|
315
|
-
description: "Inflation"
|
316
|
-
from: "2024-01-01"
|
317
|
-
to: "2024-12-31"
|
318
|
-
- amount: 0.05
|
319
|
-
description: "Inflation"
|
320
|
-
from: "2025-01-01"
|
321
|
-
to: "2025-12-31"
|
322
|
-
```
|
323
|
-
|
324
|
-
This will generate an [auto-posting](https://hledger.org/dev/hledger.html#auto-postings) in your forecast which will uplift any transaction with an `Expenses:Food` category. In the first year the uplift with be 2% and in the following year, 5%.
|
325
|
-
|
326
|
-
#### Additional YML features
|
327
|
-
|
328
|
-
Dates in a YML file can be constrained by the `to` date in two ways:
|
329
|
-
|
330
|
-
```yml
|
331
|
-
monthly:
|
332
|
-
- account: "Assets:Bank"
|
333
|
-
from: "2023-03-01"
|
334
|
-
to: "2025-01-01"
|
335
|
-
transactions:
|
336
|
-
# details omitted for brevity
|
337
|
-
```
|
338
|
-
|
339
|
-
or:
|
340
|
-
|
341
|
-
```yml
|
342
|
-
monthly:
|
343
|
-
- account: "Assets:Bank"
|
344
|
-
from: "2023-03-01"
|
345
|
-
transactions:
|
346
|
-
- amount: 2000
|
347
|
-
category: "Expenses:Mortgage"
|
348
|
-
description: Mortgage
|
349
|
-
to: "2025-01-01"
|
350
|
-
```
|
351
|
-
|
352
201
|
### Tracking
|
353
202
|
|
354
203
|
> **Note**: Marking a transaction for tracking will ensure that it is only written into the forecast if it isn't found within a specified transaction file
|
@@ -362,19 +211,6 @@ type,frequency,account,from,to,description,category,amount,roll-up,summary_exclu
|
|
362
211
|
once,,Assets:Bank,2023-03-05,,Refund for that damn laptop,Expenses:Shopping,-3000,,,TRUE
|
363
212
|
```
|
364
213
|
|
365
|
-
Or:
|
366
|
-
|
367
|
-
```yml
|
368
|
-
once:
|
369
|
-
- account: "Assets:Bank"
|
370
|
-
from: "2023-03-05"
|
371
|
-
transactions:
|
372
|
-
- amount: -3000
|
373
|
-
category: "Expenses:Shopping"
|
374
|
-
description: Refund for that damn laptop
|
375
|
-
track: true
|
376
|
-
```
|
377
|
-
|
378
214
|
> **Note**: This feature has been designed to work with `once` transaction types only
|
379
215
|
|
380
216
|
To use this feature, ensure you pass a filepath to the `-t` flag, such as:
|
data/example.journal
CHANGED
@@ -1,47 +1,47 @@
|
|
1
1
|
~ monthly from 2023-03-01 * Salary, Bills, Food, New Kitchen
|
2
|
-
Income:Salary $-3,500.00; Salary
|
3
|
-
Expenses:Bills $175.00
|
4
|
-
Expenses:Food $500.00
|
5
|
-
Expenses:House $208.33
|
2
|
+
Income:Salary $-3,500.00 ; Salary
|
3
|
+
Expenses:Bills $175.00 ; Bills
|
4
|
+
Expenses:Food $500.00 ; Food
|
5
|
+
Expenses:House $208.33 ; New Kitchen
|
6
6
|
Assets:Bank
|
7
7
|
|
8
8
|
~ monthly from 2023-03-01 to 2025-01-01 * Mortgage
|
9
|
-
Expenses:Mortgage $2,000.00
|
9
|
+
Expenses:Mortgage $2,000.00 ; Mortgage
|
10
10
|
Assets:Bank
|
11
11
|
|
12
12
|
~ monthly from 2023-03-01 to 2024-02-29 * Holiday
|
13
|
-
Expenses:Holiday $125.00
|
13
|
+
Expenses:Holiday $125.00 ; Holiday
|
14
14
|
Assets:Bank
|
15
15
|
|
16
16
|
~ monthly from 2023-03-01 to 2025-03-01 * Rainy day fund
|
17
|
-
Assets:Savings $300.00
|
17
|
+
Assets:Savings $300.00 ; Rainy day fund
|
18
18
|
Assets:Bank
|
19
19
|
|
20
20
|
~ monthly from 2024-01-01 * Pension draw down
|
21
|
-
Income:Pension $-500.00
|
21
|
+
Income:Pension $-500.00 ; Pension draw down
|
22
22
|
Assets:Pension
|
23
23
|
|
24
24
|
~ every 3 months from 2023-04-01 * Quarterly bonus
|
25
|
-
Income:Bonus $-1,000.00; Quarterly bonus
|
25
|
+
Income:Bonus $-1,000.00 ; Quarterly bonus
|
26
26
|
Assets:Bank
|
27
27
|
|
28
28
|
~ every 6 months from 2023-04-01 * Top up holiday funds
|
29
|
-
Expenses:Holiday $500.00
|
29
|
+
Expenses:Holiday $500.00 ; Top up holiday funds
|
30
30
|
Assets:Bank
|
31
31
|
|
32
32
|
~ yearly from 2023-04-01 * Annual bonus
|
33
|
-
Income:Bonus $-2,000.00; Annual bonus
|
33
|
+
Income:Bonus $-2,000.00 ; Annual bonus
|
34
34
|
Assets:Bank
|
35
35
|
|
36
36
|
~ every 2 weeks from 2023-03-01 * Hair and beauty
|
37
|
-
Expenses:Personal Care $80.00
|
37
|
+
Expenses:Personal Care $80.00 ; Hair and beauty
|
38
38
|
Assets:Bank
|
39
39
|
|
40
40
|
~ every 5 weeks from 2023-03-01 * Misc expenses
|
41
|
-
Expenses:General Expenses $30.00
|
41
|
+
Expenses:General Expenses $30.00 ; Misc expenses
|
42
42
|
Assets:Bank
|
43
43
|
|
44
|
-
~
|
44
|
+
~ 2024-01-01 * [TRACKED] Refund for that damn laptop
|
45
45
|
Expenses:Shopping $-3,000.00; Refund for that damn laptop
|
46
46
|
Assets:Bank
|
47
47
|
|
data/hledger-forecast.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.version = HledgerForecast::VERSION
|
10
10
|
s.authors = ['Oli Morris']
|
11
11
|
s.summary = "An extended wrapper around hledger's forecasting functionality"
|
12
|
-
s.description = 'Use a CSV
|
12
|
+
s.description = 'Use a CSV file for improved forecasting with hledger'
|
13
13
|
s.email = 'olimorris@users.noreply.github.com'
|
14
14
|
s.homepage = 'https://github.com/olimorris/hledger-forecast'
|
15
15
|
s.license = 'MIT'
|
@@ -12,7 +12,11 @@ module HledgerForecast
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def evaluate_date(from, to)
|
15
|
-
|
15
|
+
if to[0] != "="
|
16
|
+
return to if to.is_a?(Date)
|
17
|
+
|
18
|
+
return Date.parse(to)
|
19
|
+
end
|
16
20
|
|
17
21
|
# Subtract a day from the final date
|
18
22
|
(from >> @calculator.evaluate(to.slice(1..-1))) - 1
|
data/lib/hledger_forecast/cli.rb
CHANGED
@@ -79,16 +79,9 @@ module HledgerForecast
|
|
79
79
|
opts.separator ""
|
80
80
|
|
81
81
|
opts.on("-f", "--forecast FILE",
|
82
|
-
"The path to the FORECAST csv
|
82
|
+
"The path to the FORECAST csv file to generate from") do |file|
|
83
83
|
options[:forecast_file] = file
|
84
|
-
|
85
|
-
options[:file_type] = if File.extname(file) == '.csv'
|
86
|
-
"csv"
|
87
|
-
else
|
88
|
-
"yml"
|
89
|
-
end
|
90
|
-
|
91
|
-
options[:output_file] ||= file.sub(options[:file_type], 'journal')
|
84
|
+
options[:output_file] ||= file.sub('csv', 'journal')
|
92
85
|
end
|
93
86
|
|
94
87
|
opts.on("-o", "--output-file FILE",
|
@@ -102,7 +95,7 @@ module HledgerForecast
|
|
102
95
|
end
|
103
96
|
|
104
97
|
opts.on("-v", "--verbose",
|
105
|
-
"
|
98
|
+
"Do not group transactions in the output file") do
|
106
99
|
options[:verbose] = true
|
107
100
|
end
|
108
101
|
|
@@ -112,7 +105,7 @@ module HledgerForecast
|
|
112
105
|
end
|
113
106
|
|
114
107
|
opts.on("--no-track",
|
115
|
-
"
|
108
|
+
"Do not track any transactions") do
|
116
109
|
options[:no_track] = true
|
117
110
|
end
|
118
111
|
|
@@ -150,12 +143,7 @@ module HledgerForecast
|
|
150
143
|
opts.separator ""
|
151
144
|
|
152
145
|
opts.on("-f", "--forecast FILE",
|
153
|
-
"The path to the FORECAST csv
|
154
|
-
options[:file_type] = if File.extname(file) == '.csv'
|
155
|
-
"csv"
|
156
|
-
else
|
157
|
-
"yml"
|
158
|
-
end
|
146
|
+
"The path to the FORECAST csv file to summarize") do |file|
|
159
147
|
options[:forecast_file] = file
|
160
148
|
end
|
161
149
|
|
@@ -240,7 +228,6 @@ module HledgerForecast
|
|
240
228
|
forecast = File.read(options[:forecast_file])
|
241
229
|
|
242
230
|
begin
|
243
|
-
forecast = HledgerForecast::CSVParser.parse(forecast) if options[:file_type] == "csv"
|
244
231
|
transactions = Generator.generate(forecast, options)
|
245
232
|
rescue StandardError => e
|
246
233
|
puts "An error occurred while generating transactions: #{e.message}"
|
@@ -6,61 +6,78 @@ module HledgerForecast
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def generate(config, cli_options = nil)
|
9
|
-
forecast =
|
9
|
+
forecast = CSV.parse(config, headers: true)
|
10
10
|
@settings = Settings.config(forecast, cli_options)
|
11
11
|
|
12
|
-
|
13
|
-
forecast.each do |
|
14
|
-
next if
|
12
|
+
processed = []
|
13
|
+
forecast.each do |row|
|
14
|
+
next if row['type'] == "settings"
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
processed.push(process_forecast(row))
|
17
|
+
end
|
18
|
+
|
19
|
+
unless @settings[:verbose]
|
20
|
+
processed = processed.group_by do |row|
|
21
|
+
[row[:type], row[:frequency], row[:from], row[:to], row[:account], row[:track]]
|
22
|
+
end
|
23
|
+
|
24
|
+
processed = processed.map do |(type, frequency, from, to, account, track), transactions|
|
25
|
+
{
|
26
|
+
type: type,
|
27
|
+
frequency: frequency,
|
28
|
+
from: from,
|
29
|
+
to: to,
|
30
|
+
account: account,
|
31
|
+
track: track || false,
|
32
|
+
transactions: transactions
|
33
|
+
}
|
18
34
|
end
|
19
35
|
end
|
20
36
|
|
21
37
|
Formatter.output_to_ledger(
|
22
|
-
Transactions::Default.generate(
|
23
|
-
Transactions::Trackers.generate(
|
24
|
-
Transactions::Modifiers.generate(output, @settings)
|
38
|
+
Transactions::Default.generate(processed, @settings),
|
39
|
+
Transactions::Trackers.generate(processed, @settings)
|
25
40
|
)
|
26
41
|
end
|
27
42
|
|
28
43
|
private
|
29
44
|
|
30
|
-
def
|
31
|
-
|
45
|
+
def process_forecast(row)
|
46
|
+
row['amount'] = Utilities.convert_amount(row['amount'])
|
32
47
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
48
|
+
{
|
49
|
+
type: row['type'],
|
50
|
+
frequency: row['frequency'] || nil,
|
51
|
+
account: row['account'],
|
52
|
+
from: Date.parse(row['from']),
|
53
|
+
to: row['to'] ? Calculator.new.evaluate_date(Date.parse(row['from']), row['to']) : nil,
|
54
|
+
description: row['description'],
|
55
|
+
category: row['category'],
|
56
|
+
amount: Formatter.format_money(Calculator.new.evaluate(row['amount']), @settings),
|
57
|
+
track: Transactions::Trackers.track?(row, @settings) ? true : false
|
40
58
|
}
|
59
|
+
end
|
41
60
|
|
42
|
-
|
61
|
+
def transform_data(data)
|
62
|
+
transformed_data = []
|
43
63
|
|
44
|
-
|
45
|
-
|
46
|
-
item.merge(transactions: transactions)
|
47
|
-
end
|
48
|
-
end
|
64
|
+
data.each do |group_key, transactions|
|
65
|
+
next if group_key == "settings"
|
49
66
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
track: Transactions::Trackers.track?(t, block, @settings) ? true : false,
|
59
|
-
frequency: t['frequency'] || nil
|
67
|
+
split_keys = group_key.split("@@")
|
68
|
+
|
69
|
+
group_info = {
|
70
|
+
type: split_keys[0],
|
71
|
+
from: split_keys[1],
|
72
|
+
to: split_keys[2],
|
73
|
+
account: split_keys[3],
|
74
|
+
transactions: transactions
|
60
75
|
}
|
76
|
+
|
77
|
+
transformed_data << group_info
|
61
78
|
end
|
62
79
|
|
63
|
-
|
80
|
+
transformed_data
|
64
81
|
end
|
65
82
|
end
|
66
83
|
end
|
@@ -1,41 +1,56 @@
|
|
1
1
|
module HledgerForecast
|
2
|
-
# Set the options from a user's
|
2
|
+
# Set the options from a user's config
|
3
3
|
class Settings
|
4
4
|
def self.config(forecast, cli_options)
|
5
5
|
settings = {}
|
6
|
+
settings[:max_amount] = 0
|
7
|
+
settings[:max_category] = 0
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
+
forecast.each do |row|
|
10
|
+
if row['type'] != 'settings'
|
11
|
+
category_length = row['category'].length
|
12
|
+
settings[:max_category] = category_length if category_length > settings[:max_category]
|
9
13
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
+
amount = if row['amount'].is_a?(Integer) || row['amount'].is_a?(Float)
|
15
|
+
((row['amount'] + 3) * 100).to_s
|
16
|
+
else
|
17
|
+
row['amount'].to_s
|
18
|
+
end
|
14
19
|
|
15
|
-
|
16
|
-
|
17
|
-
settings
|
18
|
-
end
|
20
|
+
settings[:max_amount] = amount.length if amount.length > settings[:max_amount]
|
21
|
+
end
|
19
22
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
23
|
+
if row['type'] == 'settings'
|
24
|
+
|
25
|
+
settings[:currency] = if row['frequency'] == "currency"
|
26
|
+
row['account']
|
27
|
+
else
|
28
|
+
"USD"
|
29
|
+
end
|
30
|
+
|
31
|
+
settings[:show_symbol] = if row['frequency'] == "show_symbol"
|
32
|
+
row['account']
|
33
|
+
else
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
settings[:sign_before_symbol] = if row['frequency'] == "sign_before_symbol"
|
38
|
+
row['account']
|
39
|
+
else
|
40
|
+
false
|
41
|
+
end
|
42
|
+
|
43
|
+
settings[:thousands_separator] = if row['frequency'] == "thousands_separator"
|
44
|
+
row['account']
|
45
|
+
else
|
46
|
+
","
|
47
|
+
end
|
35
48
|
end
|
49
|
+
|
50
|
+
settings.merge!(cli_options) if cli_options
|
36
51
|
end
|
37
52
|
|
38
|
-
|
53
|
+
settings
|
39
54
|
end
|
40
55
|
end
|
41
56
|
end
|