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
@@ -1,66 +1,41 @@
|
|
1
1
|
require_relative '../lib/hledger_forecast'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
monthly:
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
to: "2023-06-01"
|
13
|
-
category: "Expenses:Mortgage"
|
14
|
-
amount: 2000.00
|
15
|
-
- description: Mortgage top up
|
16
|
-
to: "2023-06-01"
|
17
|
-
category: "Expenses:Mortgage Top Up"
|
18
|
-
amount: 200.00
|
19
|
-
- description: Food
|
20
|
-
category: "Expenses:Food"
|
21
|
-
amount: 100.00
|
22
|
-
- description: Party time
|
23
|
-
category: "Expenses:Going Out"
|
24
|
-
amount: 50.00
|
25
|
-
YAML
|
26
|
-
|
27
|
-
base_output = <<~JOURNAL
|
3
|
+
config = <<~CSV
|
4
|
+
type,frequency,account,from,to,description,category,amount,roll-up,summary_exclude,track
|
5
|
+
monthly,,Assets:Bank,01/03/2023,01/06/2023,Mortgage,Expenses:Mortgage,2000.00,,,
|
6
|
+
monthly,,Assets:Bank,01/03/2023,01/06/2023,Mortgage top up,Expenses:Mortgage,200.00,,,
|
7
|
+
monthly,,Assets:Bank,01/03/2023,,Food,Expenses:Food,100.00,,,
|
8
|
+
settings,currency,GBP,,,,,,,,
|
9
|
+
CSV
|
10
|
+
|
11
|
+
output = <<~JOURNAL
|
28
12
|
~ monthly from 2023-03-01 to 2023-06-01 * Mortgage, Mortgage top up
|
29
|
-
Expenses:Mortgage
|
30
|
-
Expenses:Mortgage
|
13
|
+
Expenses:Mortgage £2,000.00 ; Mortgage
|
14
|
+
Expenses:Mortgage £200.00 ; Mortgage top up
|
31
15
|
Assets:Bank
|
32
16
|
|
33
|
-
~ monthly from 2023-03-01 * Food
|
34
|
-
Expenses:Food
|
35
|
-
Expenses:Going Out £50.00 ; Party time
|
17
|
+
~ monthly from 2023-03-01 * Food
|
18
|
+
Expenses:Food £100.00 ; Food
|
36
19
|
Assets:Bank
|
37
20
|
|
38
21
|
JOURNAL
|
39
22
|
|
40
|
-
computed_config = <<~
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
- from: "2023-03-01"
|
46
|
-
account: "Assets:Bank"
|
47
|
-
transactions:
|
48
|
-
- description: Mortgage
|
49
|
-
category: "Expenses:Mortgage"
|
50
|
-
to: "=12"
|
51
|
-
amount: 2000.00
|
52
|
-
YAML
|
23
|
+
computed_config = <<~CSV
|
24
|
+
type,frequency,account,from,to,description,category,amount,roll-up,summary_exclude,track
|
25
|
+
monthly,,Assets:Bank,01/03/2023,=12,Mortgage,Expenses:Mortgage,2000.00,,,
|
26
|
+
settings,currency,GBP,,,,,,,,
|
27
|
+
CSV
|
53
28
|
|
54
29
|
computed_output = <<~JOURNAL
|
55
30
|
~ monthly from 2023-03-01 to 2024-02-29 * Mortgage
|
56
|
-
Expenses:Mortgage £2,000.00; Mortgage
|
31
|
+
Expenses:Mortgage £2,000.00 ; Mortgage
|
57
32
|
Assets:Bank
|
58
33
|
|
59
34
|
JOURNAL
|
60
35
|
|
61
36
|
RSpec.describe 'generate' do
|
62
37
|
it 'generates a forecast with correct MONTHLY transactions that have an end date' do
|
63
|
-
expect(HledgerForecast::Generator.generate(
|
38
|
+
expect(HledgerForecast::Generator.generate(config)).to eq(output)
|
64
39
|
end
|
65
40
|
|
66
41
|
it 'generates a forecast with correct MONTHLY transactions that have a COMPUTED end date' do
|
data/spec/monthly_spec.rb
CHANGED
@@ -1,37 +1,20 @@
|
|
1
1
|
require_relative '../lib/hledger_forecast'
|
2
2
|
|
3
|
-
config = <<~
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
description: Mortgage
|
11
|
-
- amount: 100
|
12
|
-
category: "Expenses:Food"
|
13
|
-
description: Food
|
14
|
-
- account: "Assets:Savings"
|
15
|
-
from: "2023-03-01"
|
16
|
-
transactions:
|
17
|
-
- amount: -1000
|
18
|
-
category: "Assets:Bank"
|
19
|
-
description: Savings
|
20
|
-
|
21
|
-
settings:
|
22
|
-
currency: GBP
|
23
|
-
YAML
|
3
|
+
config = <<~CSV
|
4
|
+
type,frequency,account,from,to,description,category,amount,roll-up,summary_exclude,track
|
5
|
+
monthly,,Assets:Bank,01/03/2023,,Bills,Expenses:Bills,175,,,
|
6
|
+
monthly,,Assets:Bank,01/03/2023,,Food,Expenses:Food,500,,,
|
7
|
+
monthly,,Assets:Bank,01/03/2023,,Savings,Assets:Savings,-1000,,,
|
8
|
+
settings,currency,GBP,,,,,,,,
|
9
|
+
CSV
|
24
10
|
|
25
11
|
output = <<~JOURNAL
|
26
|
-
~ monthly from 2023-03-01 *
|
27
|
-
Expenses:
|
28
|
-
Expenses:Food
|
12
|
+
~ monthly from 2023-03-01 * Bills, Food, Savings
|
13
|
+
Expenses:Bills £175.00 ; Bills
|
14
|
+
Expenses:Food £500.00 ; Food
|
15
|
+
Assets:Savings £-1,000.00; Savings
|
29
16
|
Assets:Bank
|
30
17
|
|
31
|
-
~ monthly from 2023-03-01 * Savings
|
32
|
-
Assets:Bank £-1,000.00; Savings
|
33
|
-
Assets:Savings
|
34
|
-
|
35
18
|
JOURNAL
|
36
19
|
|
37
20
|
RSpec.describe 'generate' do
|
data/spec/once_spec.rb
CHANGED
@@ -1,21 +1,14 @@
|
|
1
1
|
require_relative '../lib/hledger_forecast'
|
2
2
|
|
3
|
-
config = <<~
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
- from: "2023-07-01"
|
9
|
-
account: "Assets:Bank"
|
10
|
-
transactions:
|
11
|
-
- description: New Kitchen
|
12
|
-
category: "Expense:House"
|
13
|
-
amount: 5,000.00
|
14
|
-
YAML
|
3
|
+
config = <<~CSV
|
4
|
+
type,frequency,account,from,to,description,category,amount,roll-up,summary_exclude,track
|
5
|
+
once,,Assets:Bank,01/07/2023,,New Kitchen,Expenses:House,5000,,,
|
6
|
+
settings,currency,GBP,,,,,,,,
|
7
|
+
CSV
|
15
8
|
|
16
9
|
output = <<~JOURNAL
|
17
10
|
~ 2023-07-01 * New Kitchen
|
18
|
-
|
11
|
+
Expenses:House £5,000.00; New Kitchen
|
19
12
|
Assets:Bank
|
20
13
|
|
21
14
|
JOURNAL
|
data/spec/quarterly_spec.rb
CHANGED
@@ -1,17 +1,10 @@
|
|
1
1
|
require_relative '../lib/hledger_forecast'
|
2
2
|
|
3
|
-
config = <<~
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
- from: "2023-04-01"
|
9
|
-
account: "Assets:Bank"
|
10
|
-
transactions:
|
11
|
-
- description: Bonus
|
12
|
-
category: "Income:Bonus"
|
13
|
-
amount: -1,000.00
|
14
|
-
YAML
|
3
|
+
config = <<~CSV
|
4
|
+
type,frequency,account,from,to,description,category,amount,roll-up,summary_exclude,track
|
5
|
+
quarterly,,Assets:Bank,01/04/2023,,Bonus,Income:Bonus,-1000,,,
|
6
|
+
settings,currency,GBP,,,,,,,,
|
7
|
+
CSV
|
15
8
|
|
16
9
|
output = <<~JOURNAL
|
17
10
|
~ every 3 months from 2023-04-01 * Bonus
|
data/spec/summarizer_spec.rb
CHANGED
@@ -1,51 +1,20 @@
|
|
1
1
|
require_relative '../lib/hledger_forecast'
|
2
2
|
|
3
|
-
config = <<~
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
- amount: 100
|
13
|
-
category: "Expenses:Food"
|
14
|
-
description: Food
|
15
|
-
- account: "Assets:Savings"
|
16
|
-
from: "2023-03-01"
|
17
|
-
transactions:
|
18
|
-
- amount: -1000
|
19
|
-
category: "Assets:Bank"
|
20
|
-
description: Savings
|
21
|
-
|
22
|
-
custom:
|
23
|
-
- account: "[Assets:Bank]"
|
24
|
-
from: "2023-05-01"
|
25
|
-
transactions:
|
26
|
-
- amount: 80
|
27
|
-
category: "[Expenses:Personal Care]"
|
28
|
-
description: Hair and beauty
|
29
|
-
frequency: "every 2 weeks"
|
30
|
-
roll-up: 26
|
31
|
-
- account: "[Assets:Checking]"
|
32
|
-
from: "2023-05-01"
|
33
|
-
transactions:
|
34
|
-
- amount: 50
|
35
|
-
category: "[Expenses:Groceries]"
|
36
|
-
description: Gotta feed that stomach
|
37
|
-
frequency: "every 5 days"
|
38
|
-
roll-up: 73
|
39
|
-
|
40
|
-
settings:
|
41
|
-
currency: GBP
|
42
|
-
YAML
|
3
|
+
config = <<~CSV
|
4
|
+
type,frequency,account,from,to,description,category,amount,roll-up,summary_exclude,track
|
5
|
+
monthly,,Assets:Bank,01/03/2023,=24,Mortgage,Expenses:Mortgage,2000.55,,,
|
6
|
+
monthly,,Assets:Bank,01/03/2023,,Food,Expenses:Food,100,,,
|
7
|
+
monthly,,Assets:Savings,01/03/2023,,Savings,Assets:Bank,-1000,,,
|
8
|
+
custom,every 2 weeks,[Assets:Bank],01/05/2023,,Hair and beauty,[Expenses:Personal Care],80,26,,
|
9
|
+
custom,every 2 weeks,[Assets:Checking],01/05/2023,,Extra Food,[Expenses:Groceries],50,73,,
|
10
|
+
settings,currency,GBP,,,,,,,,
|
11
|
+
CSV
|
43
12
|
|
44
13
|
RSpec.describe HledgerForecast::Summarizer do
|
45
14
|
let(:summarizer) { described_class.new }
|
46
15
|
|
47
16
|
describe '#generate with roll_up' do
|
48
|
-
let(:forecast) {
|
17
|
+
let(:forecast) { CSV.parse(config, headers: true) }
|
49
18
|
let(:cli_options) { { roll_up: 'monthly' } }
|
50
19
|
|
51
20
|
before do
|
@@ -69,7 +38,7 @@ RSpec.describe HledgerForecast::Summarizer do
|
|
69
38
|
end
|
70
39
|
|
71
40
|
describe '#generate' do
|
72
|
-
let(:forecast) {
|
41
|
+
let(:forecast) { CSV.parse(config, headers: true) }
|
73
42
|
let(:cli_options) { nil }
|
74
43
|
|
75
44
|
before do
|
data/spec/track_spec.rb
CHANGED
@@ -4,31 +4,17 @@ current_month = Date.new(Date.today.year, Date.today.month, 1)
|
|
4
4
|
previous_month = current_month.prev_month
|
5
5
|
next_month = current_month.next_month
|
6
6
|
|
7
|
-
base_config = <<~
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
description: Tax owed
|
15
|
-
track: true
|
16
|
-
- amount: 100
|
17
|
-
category: "Expenses:Food"
|
18
|
-
description: Food expenses
|
19
|
-
- amount: -1500
|
20
|
-
category: "Income:Salary"
|
21
|
-
description: Salary
|
22
|
-
to: "2023-08-01"
|
23
|
-
track: true
|
24
|
-
|
25
|
-
settings:
|
26
|
-
currency: GBP
|
27
|
-
YAML
|
7
|
+
base_config = <<~CSV
|
8
|
+
type,frequency,account,from,to,description,category,amount,roll-up,summary_exclude,track
|
9
|
+
once,,Assets:Bank,05/03/2023,,Tax owed,Expenses:Tax,3000,,,true
|
10
|
+
once,,Assets:Bank,05/03/2023,,Food expenses,Expenses:Food,100,,,
|
11
|
+
once,,Assets:Bank,05/03/2023,01/08/2023,Salary,Income:Salary,-1500,,,true
|
12
|
+
settings,currency,GBP,,,,,,,,
|
13
|
+
CSV
|
28
14
|
|
29
15
|
base_output = <<~JOURNAL
|
30
16
|
~ 2023-03-05 * Food expenses
|
31
|
-
Expenses:Food £100.00
|
17
|
+
Expenses:Food £100.00 ; Food expenses
|
32
18
|
Assets:Bank
|
33
19
|
|
34
20
|
~ #{next_month} * [TRACKED] Tax owed
|
@@ -54,19 +40,11 @@ RSpec.describe 'Tracking transactions -' do
|
|
54
40
|
it 'writes a NON-FOUND entry for dates that are close to the current period' do
|
55
41
|
require 'tempfile'
|
56
42
|
|
57
|
-
forecast_config = <<~
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
- amount: 5000
|
63
|
-
category: "Expenses:House"
|
64
|
-
description: New kitchen
|
65
|
-
track: true
|
66
|
-
|
67
|
-
settings:
|
68
|
-
currency: GBP
|
69
|
-
YAML
|
43
|
+
forecast_config = <<~CSV
|
44
|
+
type,frequency,account,from,to,description,category,amount,roll-up,summary_exclude,track
|
45
|
+
once,,Assets:Bank,"#{previous_month}",,New kitchen,Expenses:House,5000,,,true
|
46
|
+
settings,currency,GBP,,,,,,,,
|
47
|
+
CSV
|
70
48
|
|
71
49
|
journal = <<~JOURNAL
|
72
50
|
#{previous_month} * Opening balance
|
@@ -104,19 +82,11 @@ RSpec.describe 'Tracking transactions -' do
|
|
104
82
|
end
|
105
83
|
|
106
84
|
it 'treats a future tracked transaction as a regular transaction' do
|
107
|
-
forecast_config = <<~
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
- amount: 100
|
113
|
-
category: "Expenses:Food"
|
114
|
-
description: Food expenses
|
115
|
-
track: true
|
116
|
-
|
117
|
-
settings:
|
118
|
-
currency: GBP
|
119
|
-
YAML
|
85
|
+
forecast_config = <<~CSV
|
86
|
+
type,frequency,account,from,to,description,category,amount,roll-up,summary_exclude,track
|
87
|
+
monthly,,Assets:Bank,"#{next_month}",,Food expenses,Expenses:Food,100,,,true
|
88
|
+
settings,currency,GBP,,,,,,,,
|
89
|
+
CSV
|
120
90
|
|
121
91
|
options = {}
|
122
92
|
options[:transaction_file] = 'spec/stubs/transactions_not_found.journal'
|
@@ -125,7 +95,7 @@ RSpec.describe 'Tracking transactions -' do
|
|
125
95
|
|
126
96
|
output = <<~JOURNAL
|
127
97
|
~ monthly from #{next_month} * Food expenses
|
128
|
-
Expenses:Food £100.00; Food expenses
|
98
|
+
Expenses:Food £100.00 ; Food expenses
|
129
99
|
Assets:Bank
|
130
100
|
|
131
101
|
JOURNAL
|
data/spec/verbose_output_spec.rb
CHANGED
@@ -2,15 +2,15 @@ require_relative '../lib/hledger_forecast'
|
|
2
2
|
|
3
3
|
output = <<~JOURNAL
|
4
4
|
~ monthly from 2023-03-01 * Mortgage
|
5
|
-
Expenses:Mortgage £2,000.55; Mortgage
|
5
|
+
Expenses:Mortgage £2,000.55 ; Mortgage
|
6
6
|
Assets:Bank
|
7
7
|
|
8
8
|
~ monthly from 2023-03-01 * Food
|
9
|
-
Expenses:Food £100.00
|
9
|
+
Expenses:Food £100.00 ; Food
|
10
10
|
Assets:Bank
|
11
11
|
|
12
12
|
~ monthly from 2023-03-01 * Savings
|
13
|
-
Assets:Bank £-1,000.00; Savings
|
13
|
+
Assets:Bank £-1,000.00 ; Savings
|
14
14
|
Assets:Savings
|
15
15
|
|
16
16
|
JOURNAL
|
data/spec/yearly_spec.rb
CHANGED
@@ -1,17 +1,10 @@
|
|
1
1
|
require_relative '../lib/hledger_forecast'
|
2
2
|
|
3
|
-
config = <<~
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
- account: "Assets:Bank"
|
9
|
-
from: "2023-04-01"
|
10
|
-
transactions:
|
11
|
-
- description: Bonus
|
12
|
-
category: "Income:Bonus"
|
13
|
-
amount: -3,000.00
|
14
|
-
YAML
|
3
|
+
config = <<~CSV
|
4
|
+
type,frequency,account,from,to,description,category,amount,roll-up,summary_exclude,track
|
5
|
+
yearly,,Assets:Bank,01/04/2023,,Bonus,Income:Bonus,-3000,,,
|
6
|
+
settings,currency,GBP,,,,,,,,
|
7
|
+
CSV
|
15
8
|
|
16
9
|
output = <<~JOURNAL
|
17
10
|
~ yearly from 2023-04-01 * Bonus
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hledger-forecast
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oli Morris
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-02-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
@@ -94,7 +94,7 @@ dependencies:
|
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '3.12'
|
97
|
-
description: Use a CSV
|
97
|
+
description: Use a CSV file for improved forecasting with hledger
|
98
98
|
email: olimorris@users.noreply.github.com
|
99
99
|
executables:
|
100
100
|
- hledger-forecast
|
@@ -111,13 +111,11 @@ files:
|
|
111
111
|
- bin/hledger-forecast
|
112
112
|
- example.csv
|
113
113
|
- example.journal
|
114
|
-
- example.yml
|
115
114
|
- hledger-forecast.gemspec
|
116
115
|
- lib/hledger_forecast.rb
|
117
116
|
- lib/hledger_forecast/calculator.rb
|
118
117
|
- lib/hledger_forecast/cli.rb
|
119
118
|
- lib/hledger_forecast/comparator.rb
|
120
|
-
- lib/hledger_forecast/csv_parser.rb
|
121
119
|
- lib/hledger_forecast/formatter.rb
|
122
120
|
- lib/hledger_forecast/generator.rb
|
123
121
|
- lib/hledger_forecast/settings.rb
|
@@ -126,22 +124,19 @@ files:
|
|
126
124
|
- lib/hledger_forecast/transactions/default.rb
|
127
125
|
- lib/hledger_forecast/transactions/modifiers.rb
|
128
126
|
- lib/hledger_forecast/transactions/trackers.rb
|
127
|
+
- lib/hledger_forecast/utilities.rb
|
129
128
|
- lib/hledger_forecast/version.rb
|
130
129
|
- spec/cli_spec.rb
|
131
130
|
- spec/compare_spec.rb
|
132
131
|
- spec/computed_amounts_spec.rb
|
133
|
-
- spec/csv_and_yml_comparison_spec.rb
|
134
|
-
- spec/csv_parser_spec.rb
|
135
132
|
- spec/custom_spec.rb
|
136
133
|
- spec/half-yearly_spec.rb
|
137
|
-
- spec/modifier_spec.rb
|
138
134
|
- spec/monthly_end_date_spec.rb
|
139
135
|
- spec/monthly_end_date_transaction_spec.rb
|
140
136
|
- spec/monthly_spec.rb
|
141
137
|
- spec/once_spec.rb
|
142
138
|
- spec/quarterly_spec.rb
|
143
139
|
- spec/stubs/forecast.csv
|
144
|
-
- spec/stubs/forecast.yml
|
145
140
|
- spec/stubs/output1.csv
|
146
141
|
- spec/stubs/output2.csv
|
147
142
|
- spec/stubs/transactions_found.journal
|
@@ -178,18 +173,14 @@ test_files:
|
|
178
173
|
- spec/cli_spec.rb
|
179
174
|
- spec/compare_spec.rb
|
180
175
|
- spec/computed_amounts_spec.rb
|
181
|
-
- spec/csv_and_yml_comparison_spec.rb
|
182
|
-
- spec/csv_parser_spec.rb
|
183
176
|
- spec/custom_spec.rb
|
184
177
|
- spec/half-yearly_spec.rb
|
185
|
-
- spec/modifier_spec.rb
|
186
178
|
- spec/monthly_end_date_spec.rb
|
187
179
|
- spec/monthly_end_date_transaction_spec.rb
|
188
180
|
- spec/monthly_spec.rb
|
189
181
|
- spec/once_spec.rb
|
190
182
|
- spec/quarterly_spec.rb
|
191
183
|
- spec/stubs/forecast.csv
|
192
|
-
- spec/stubs/forecast.yml
|
193
184
|
- spec/stubs/output1.csv
|
194
185
|
- spec/stubs/output2.csv
|
195
186
|
- spec/stubs/transactions_found.journal
|
data/example.yml
DELETED
@@ -1,98 +0,0 @@
|
|
1
|
-
monthly:
|
2
|
-
- account: "Assets:Bank"
|
3
|
-
from: "2023-03-01"
|
4
|
-
transactions:
|
5
|
-
- amount: -3500
|
6
|
-
category: "Income:Salary"
|
7
|
-
description: Salary
|
8
|
-
- amount: 2000
|
9
|
-
category: "Expenses:Mortgage"
|
10
|
-
description: Mortgage
|
11
|
-
to: "2025-01-01"
|
12
|
-
- amount: 175
|
13
|
-
category: "Expenses:Bills"
|
14
|
-
description: Bills
|
15
|
-
- amount: 500
|
16
|
-
category: "Expenses:Food"
|
17
|
-
description: Food
|
18
|
-
modifiers:
|
19
|
-
- amount: 0.02
|
20
|
-
description: "Inflation"
|
21
|
-
from: "2024-01-01"
|
22
|
-
to: "2024-12-31"
|
23
|
-
- amount: 0.05
|
24
|
-
description: "Inflation"
|
25
|
-
from: "2025-01-01"
|
26
|
-
to: "2025-12-31"
|
27
|
-
- amount: "=5000/24"
|
28
|
-
category: "Expenses:House"
|
29
|
-
description: New Kitchen
|
30
|
-
- amount: 125
|
31
|
-
category: "Expenses:Holiday"
|
32
|
-
description: Holiday
|
33
|
-
to: "=12"
|
34
|
-
- account: "Assets:Bank"
|
35
|
-
from: "2023-03-01"
|
36
|
-
to: "2025-01-01"
|
37
|
-
transactions:
|
38
|
-
- amount: 300
|
39
|
-
category: "Assets:Savings"
|
40
|
-
description: "Rainy day fund"
|
41
|
-
- account: "Assets:Pension"
|
42
|
-
from: "2024-01-01"
|
43
|
-
transactions:
|
44
|
-
- amount: -500
|
45
|
-
category: "Income:Pension"
|
46
|
-
description: Pension draw down
|
47
|
-
|
48
|
-
quarterly:
|
49
|
-
- account: "Assets:Bank"
|
50
|
-
from: "2023-04-01"
|
51
|
-
transactions:
|
52
|
-
- amount: -1000.00
|
53
|
-
category: "Income:Bonus"
|
54
|
-
description: Quarterly bonus
|
55
|
-
|
56
|
-
half-yearly:
|
57
|
-
- account: "Assets:Bank"
|
58
|
-
from: "2023-04-01"
|
59
|
-
transactions:
|
60
|
-
- amount: 500
|
61
|
-
category: "Expenses:Holiday"
|
62
|
-
description: Top up holiday funds
|
63
|
-
|
64
|
-
yearly:
|
65
|
-
- account: "Assets:Bank"
|
66
|
-
from: "2023-04-01"
|
67
|
-
transactions:
|
68
|
-
- amount: -2000.00
|
69
|
-
category: "Income:Bonus"
|
70
|
-
description: Annual Bonus
|
71
|
-
|
72
|
-
once:
|
73
|
-
- account: "Assets:Bank"
|
74
|
-
from: "2023-03-05"
|
75
|
-
transactions:
|
76
|
-
- amount: -3000
|
77
|
-
category: "Expenses:Shopping"
|
78
|
-
description: Refund for that damn laptop
|
79
|
-
summary_exclude: true
|
80
|
-
track: true
|
81
|
-
|
82
|
-
custom:
|
83
|
-
- account: "Assets:Bank"
|
84
|
-
from: "2023-03-01"
|
85
|
-
transactions:
|
86
|
-
- amount: 80
|
87
|
-
category: "Expenses:Personal Care"
|
88
|
-
description: Hair and beauty
|
89
|
-
frequency: "every 2 weeks"
|
90
|
-
roll-up: 26
|
91
|
-
- amount: 30
|
92
|
-
category: "Expenses:General Expenses"
|
93
|
-
description: Misc expenses
|
94
|
-
frequency: "every 5 weeks"
|
95
|
-
roll-up: 10.4
|
96
|
-
|
97
|
-
settings:
|
98
|
-
currency: USD
|
@@ -1,106 +0,0 @@
|
|
1
|
-
module HledgerForecast
|
2
|
-
# Formats various items used throughout the application
|
3
|
-
class CSVParser
|
4
|
-
def self.parse(csv_data, cli_options = nil)
|
5
|
-
new.parse(csv_data, cli_options)
|
6
|
-
end
|
7
|
-
|
8
|
-
def parse(csv_data, _cli_options)
|
9
|
-
csv_data = CSV.parse(csv_data, headers: true)
|
10
|
-
yaml_data = {}
|
11
|
-
group_by_type(csv_data, yaml_data)
|
12
|
-
yaml_data.to_yaml
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
def group_by_type(csv_data, yaml_data)
|
18
|
-
csv_data.group_by { |row| row['type'] }.each do |type, rows|
|
19
|
-
if type == 'settings'
|
20
|
-
handle_settings(rows, yaml_data)
|
21
|
-
else
|
22
|
-
yaml_data[type] ||= []
|
23
|
-
group_by_account_and_from(rows, yaml_data[type], type)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def handle_settings(rows, yaml_data)
|
29
|
-
yaml_data['settings'] ||= {}
|
30
|
-
rows.each do |row|
|
31
|
-
yaml_data['settings'][row['frequency']] = cast_to_proper_type(row['account'])
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def group_by_account_and_from(rows, yaml_rows, type)
|
36
|
-
rows.group_by { |row| [row['account'], row['from']] }.each do |(account, from), transactions|
|
37
|
-
yaml_rows << if type == 'custom'
|
38
|
-
build_custom_transaction(account, from, transactions)
|
39
|
-
else
|
40
|
-
build_transaction(account, from, transactions)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def build_transaction(account, from, transactions)
|
46
|
-
transaction = {
|
47
|
-
'account' => account,
|
48
|
-
'from' => Date.parse(from).strftime('%Y-%m-%d'),
|
49
|
-
'transactions' => []
|
50
|
-
}
|
51
|
-
|
52
|
-
transactions.each do |row|
|
53
|
-
transaction['transactions'] << build_transaction_data(row)
|
54
|
-
end
|
55
|
-
|
56
|
-
transaction
|
57
|
-
end
|
58
|
-
|
59
|
-
def build_custom_transaction(account, from, transactions)
|
60
|
-
transaction = {
|
61
|
-
'account' => account,
|
62
|
-
'from' => Date.parse(from).strftime('%Y-%m-%d'),
|
63
|
-
'transactions' => []
|
64
|
-
}
|
65
|
-
|
66
|
-
transactions.each do |row|
|
67
|
-
transaction_data = build_transaction_data(row)
|
68
|
-
transaction_data['frequency'] = row['frequency']
|
69
|
-
transaction_data['roll-up'] = row['roll-up'].to_f if row['roll-up']
|
70
|
-
transaction['transactions'] << transaction_data
|
71
|
-
end
|
72
|
-
|
73
|
-
transaction
|
74
|
-
end
|
75
|
-
|
76
|
-
def build_transaction_data(row)
|
77
|
-
transaction_data = {
|
78
|
-
'amount' => row['amount'].start_with?("=") ? row['amount'].to_s : row['amount'].to_f,
|
79
|
-
'category' => row['category'],
|
80
|
-
'description' => row['description']
|
81
|
-
}
|
82
|
-
|
83
|
-
if row['to']
|
84
|
-
transaction_data['to'] = if row['to'].start_with?("=")
|
85
|
-
row['to']
|
86
|
-
else
|
87
|
-
Date.parse(row['to']).strftime('%Y-%m-%d')
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
transaction_data['summary_exclude'] = true if row['summary_exclude'] && row['summary_exclude'].downcase == "true"
|
92
|
-
transaction_data['track'] = true if row['track'] && row['track'].downcase == "true"
|
93
|
-
|
94
|
-
transaction_data
|
95
|
-
end
|
96
|
-
|
97
|
-
def cast_to_proper_type(str)
|
98
|
-
case str.downcase
|
99
|
-
when 'true', 'false'
|
100
|
-
str.downcase == 'true'
|
101
|
-
else
|
102
|
-
str
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|