hledger-forecast 0.1.8 → 0.1.9
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/README.md +16 -15
- data/example.yml +9 -3
- data/lib/hledger_forecast/generator.rb +6 -4
- data/lib/hledger_forecast/summarize.rb +86 -83
- data/lib/hledger_forecast/version.rb +1 -1
- data/spec/start_date_spec.rb +12 -0
- data/spec/stubs/modifiers/forecast_modifiers.yml +13 -0
- data/spec/stubs/modifiers/output_modifiers.journal +44 -0
- data/spec/stubs/monthly/forecast_monthly.yml +1 -1
- data/spec/stubs/monthly/output_monthly.journal +3 -3
- data/spec/stubs/start_date/forecast_startdate.yml +26 -0
- data/spec/stubs/start_date/output_startdate.journal +56 -0
- metadata +12 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f6dc9ef51b0f8d7927eb2b798d66257b740fad83be62d86c8207a5982aac752f
|
4
|
+
data.tar.gz: aec51b551655e2927de40237c64db32cfd4f4ebc40c855cd2bf97601e27112e2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bf00818fbbb03977e633c1e4c4eba8dd3596a6150e87117aa04e2d4b0df94c83593bef598200fa524a5d7c1777ce0be4bec2c0c4f4f0f8c9cc362732a3c8a1dc
|
7
|
+
data.tar.gz: 7a093260f8624ba0a27ead898fcda52926a00cfa12ed9f3bf67e020eb8d3df0cdfe0aa498164f0d07975f7c39efac9f0c39dd282fdd14e6684328d94b3ebbac1
|
data/README.md
CHANGED
@@ -59,7 +59,9 @@ where:
|
|
59
59
|
- `transactions.journal` might be your bank transactions (your "_actuals_")
|
60
60
|
- `my_forecast.journal` is the generated forecast file
|
61
61
|
|
62
|
-
|
62
|
+
## :gear: Configuration
|
63
|
+
|
64
|
+
### The YAML file
|
63
65
|
|
64
66
|
> **Note**: See the [example.yml](https://github.com/olimorris/hledger-forecast/blob/main/example.yml) file for an example of a complex config file
|
65
67
|
|
@@ -89,9 +91,7 @@ Let's examine what's going on in this config file:
|
|
89
91
|
- Notice we're also using [virtual postings](https://hledger.org/1.29/hledger.html#virtual-postings) (designated by the brackets). This makes it easy to filter them out with the `-R` or `--real` option in Hledger
|
90
92
|
- We also have not specified a currency; the default (`USD`) will be used
|
91
93
|
|
92
|
-
###
|
93
|
-
|
94
|
-
#### Periods
|
94
|
+
### Periods
|
95
95
|
|
96
96
|
Besides monthly recurring transactions, the app also supports the following periods:
|
97
97
|
|
@@ -101,12 +101,11 @@ Besides monthly recurring transactions, the app also supports the following peri
|
|
101
101
|
- `once` - Generate _one-time_ transactions on a specified date
|
102
102
|
- `custom` - Generate transactions every _n days/weeks/months_
|
103
103
|
|
104
|
-
|
104
|
+
#### Custom period
|
105
105
|
|
106
106
|
A custom period allows you to specify a given number of days, weeks or months for a transaction to repeat within. These can be included in the config file as follows:
|
107
107
|
|
108
108
|
```yaml
|
109
|
-
# forecast.yml
|
110
109
|
custom:
|
111
110
|
- description: Fortnightly hair and beauty spend
|
112
111
|
recurrence:
|
@@ -126,18 +125,17 @@ Where `quantity` is an integer and `period` is one of:
|
|
126
125
|
- weeks
|
127
126
|
- months
|
128
127
|
|
129
|
-
|
128
|
+
### Dates
|
130
129
|
|
131
130
|
The core of any solid forecast is predicting the correct periods that costs will fall into. When running the app from the CLI, you can specify specific dates to generate transactions over (see the [usage](#rocket-usage) section).
|
132
131
|
|
133
132
|
You can further control the dates at a period/top-level as well as at a transaction level:
|
134
133
|
|
135
|
-
|
134
|
+
#### Top level
|
136
135
|
|
137
136
|
In the example below, all transactions in the `monthly` block will be constrained by the end date:
|
138
137
|
|
139
138
|
```yaml
|
140
|
-
# forecast.yml
|
141
139
|
monthly:
|
142
140
|
- account: "[Assets:Bank]"
|
143
141
|
start: "2023-03-01"
|
@@ -146,12 +144,11 @@ monthly:
|
|
146
144
|
# details omitted for brevity
|
147
145
|
```
|
148
146
|
|
149
|
-
|
147
|
+
#### Transaction level
|
150
148
|
|
151
|
-
In the example below, only the single transaction will be constrained by the end date:
|
149
|
+
In the example below, only the single transaction will be constrained by the end date and controlled via an additional start date:
|
152
150
|
|
153
151
|
```yaml
|
154
|
-
# forecast.yml
|
155
152
|
monthly:
|
156
153
|
- account: "[Assets:Bank]"
|
157
154
|
start: "2023-03-01"
|
@@ -159,15 +156,17 @@ monthly:
|
|
159
156
|
- amount: 2000
|
160
157
|
category: "[Expenses:Mortgage]"
|
161
158
|
description: Mortgage
|
159
|
+
start: "2023-05-01"
|
162
160
|
end: "2025-01-01"
|
163
161
|
```
|
164
162
|
|
165
|
-
|
163
|
+
The addition of the `start` key means that while the block will start on 2023-03-01, the transaction for the mortgage won't start until `2023-05-01`.
|
164
|
+
|
165
|
+
### Additional settings
|
166
166
|
|
167
167
|
Additional settings in the config file to consider:
|
168
168
|
|
169
169
|
```yaml
|
170
|
-
# forecast.yml
|
171
170
|
settings:
|
172
171
|
currency: GBP # Specify the currency to use
|
173
172
|
show_symbol: true # Show the currency symbol?
|
@@ -175,7 +174,9 @@ settings:
|
|
175
174
|
thousands_separator: true # Separate thousands with a comma?
|
176
175
|
```
|
177
176
|
|
178
|
-
|
177
|
+
## :rainbow: Helpers
|
178
|
+
|
179
|
+
### Summarizing the forecast file
|
179
180
|
|
180
181
|
As your config file grows, it can be helpful to sum up the total amounts and output them in the CLI. This can be achieved by:
|
181
182
|
|
data/example.yml
CHANGED
@@ -2,13 +2,19 @@ monthly:
|
|
2
2
|
- account: "[Assets:Bank]"
|
3
3
|
start: "2023-03-01"
|
4
4
|
transactions:
|
5
|
+
- amount: -100
|
6
|
+
category: "[Income:Bonus]"
|
7
|
+
description: Bonus
|
8
|
+
- amount: -2000
|
9
|
+
category: "[Income:Salary]"
|
10
|
+
description: Salary
|
11
|
+
- amount: 500.00
|
12
|
+
category: "[Expenses:Food]"
|
13
|
+
description: Food
|
5
14
|
- amount: 1000.00
|
6
15
|
category: "[Expenses:Mortgage]"
|
7
16
|
description: Mortgage
|
8
17
|
end: "2024-01-01"
|
9
|
-
- amount: 500.00
|
10
|
-
category: "[Expenses:Food]"
|
11
|
-
description: Food
|
12
18
|
|
13
19
|
quarterly:
|
14
20
|
- account: "[Assets:Bank]"
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module HledgerForecast
|
2
2
|
# Generates journal entries based on a YAML forecast file.
|
3
3
|
# on forecast data and optional existing transactions.
|
4
|
-
#
|
5
4
|
class Generator
|
6
5
|
class << self
|
7
6
|
attr_accessor :settings
|
@@ -26,7 +25,7 @@ module HledgerForecast
|
|
26
25
|
formatted_transaction = transaction.clone
|
27
26
|
|
28
27
|
formatted_transaction['amount'] =
|
29
|
-
Money.from_cents(formatted_transaction['amount'].
|
28
|
+
Money.from_cents(formatted_transaction['amount'].to_f * 100, @settings[:currency]).format(
|
30
29
|
symbol: @settings[:show_symbol],
|
31
30
|
sign_before_symbol: @settings[:sign_before_symbol],
|
32
31
|
thousands_separator: @settings[:thousands_separator] ? ',' : nil
|
@@ -89,9 +88,12 @@ module HledgerForecast
|
|
89
88
|
|
90
89
|
if date_matches
|
91
90
|
forecast['transactions'].each do |transaction|
|
92
|
-
|
91
|
+
transaction_start_date = transaction['start'] ? Date.parse(transaction['start']) : nil
|
92
|
+
transaction_end_date = transaction['end'] ? Date.parse(transaction['end']) : nil
|
93
93
|
|
94
|
-
|
94
|
+
if (transaction_start_date && date < transaction_start_date) || (transaction_end_date && date > transaction_end_date)
|
95
|
+
next
|
96
|
+
end
|
95
97
|
|
96
98
|
write_transactions(output_file, date, account, format_transaction(transaction))
|
97
99
|
end
|
@@ -1,132 +1,135 @@
|
|
1
1
|
module HledgerForecast
|
2
2
|
# Summarise a forecast YAML file and output it to the CLI
|
3
3
|
class Summarize
|
4
|
-
|
5
|
-
|
6
|
-
forecast_data[period]&.each do |entry|
|
7
|
-
entry['transactions'].each do |transaction|
|
8
|
-
category_totals[transaction['category']] += transaction['amount']
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
category_totals
|
13
|
-
end
|
4
|
+
@table = nil
|
5
|
+
@generator = nil
|
14
6
|
|
15
|
-
def self.
|
16
|
-
|
17
|
-
period_total = 0
|
7
|
+
def self.init_table
|
8
|
+
table = Terminal::Table.new
|
18
9
|
|
19
|
-
|
20
|
-
|
21
|
-
formatted_amount = amount.to_i < 0 ? formatted_amount.green : formatted_amount.red
|
22
|
-
puts " #{category.ljust(40)}#{formatted_amount}"
|
23
|
-
period_total += amount
|
24
|
-
end
|
10
|
+
table.add_row([{ value: 'FORECAST SUMMARY'.bold, colspan: 3, alignment: :center }])
|
11
|
+
table.add_separator
|
25
12
|
|
26
|
-
|
27
|
-
formatted_period_total = period_total.to_i < 0 ? formatted_period_total.green : formatted_period_total.red
|
28
|
-
puts " TOTAL".ljust(42) + formatted_period_total
|
13
|
+
@table = table
|
29
14
|
end
|
30
15
|
|
31
|
-
def self.
|
32
|
-
|
33
|
-
|
34
|
-
grand_total = 0
|
16
|
+
def self.init_generator(forecast_data)
|
17
|
+
generator = HledgerForecast::Generator
|
18
|
+
generator.configure_settings(forecast_data)
|
35
19
|
|
36
|
-
|
37
|
-
|
38
|
-
|
20
|
+
@generator = generator
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.sum_transactions(forecast_data, period)
|
24
|
+
category_total = Hash.new(0)
|
25
|
+
forecast_data[period]&.each do |entry|
|
26
|
+
entry['transactions'].each do |transaction|
|
27
|
+
category_total[transaction['category']] += transaction['amount']
|
28
|
+
end
|
39
29
|
end
|
40
30
|
|
41
|
-
|
42
|
-
total
|
31
|
+
category_total
|
43
32
|
end
|
44
33
|
|
45
34
|
def self.sum_custom_transactions(forecast_data)
|
46
|
-
|
35
|
+
category_total = Hash.new(0)
|
47
36
|
custom_periods = []
|
48
37
|
|
49
38
|
forecast_data['custom']&.each do |entry|
|
50
39
|
period_data = {}
|
51
40
|
period_data[:quantity] = entry['recurrence']['quantity']
|
52
41
|
period_data[:period] = entry['recurrence']['period']
|
53
|
-
period_data[:description] = entry['transactions'].first['description']
|
54
42
|
period_data[:category] = entry['transactions'].first['category']
|
55
43
|
period_data[:amount] = entry['transactions'].first['amount']
|
56
44
|
|
57
45
|
entry['transactions'].each do |transaction|
|
58
|
-
|
46
|
+
category_total[transaction['category']] += transaction['amount']
|
59
47
|
end
|
60
48
|
|
61
49
|
custom_periods << period_data
|
62
50
|
end
|
63
51
|
|
64
|
-
{ totals:
|
52
|
+
{ totals: category_total, periods: custom_periods }
|
65
53
|
end
|
66
54
|
|
67
|
-
def self.
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
%w[monthly quarterly half-yearly yearly once custom].each do |period|
|
72
|
-
category_totals_by_period[period] = sum_transactions(forecast_data, period)
|
73
|
-
end
|
55
|
+
def self.format_amount(amount)
|
56
|
+
formatted_amount = @generator.format_transaction({ 'amount' => amount })['amount']
|
57
|
+
amount.to_f < 0 ? formatted_amount.green : formatted_amount.red
|
58
|
+
end
|
74
59
|
|
75
|
-
|
60
|
+
def self.add_rows_to_table(row_data, period_total, custom: false)
|
61
|
+
if custom
|
62
|
+
row_data[:periods].each do |period|
|
63
|
+
@table.add_row [{ value: period[:category], alignment: :left },
|
64
|
+
{ value: "every #{period[:quantity]} #{period[:period]}", alignment: :right },
|
65
|
+
{ value: format_amount(period[:amount]), alignment: :right }]
|
76
66
|
|
77
|
-
|
78
|
-
|
67
|
+
period_total += period[:amount]
|
68
|
+
end
|
69
|
+
else
|
70
|
+
row_data.each do |category, amount|
|
71
|
+
@table.add_row [{ value: category, colspan: 2, alignment: :left },
|
72
|
+
{ value: format_amount(amount), alignment: :right }]
|
79
73
|
|
80
|
-
|
74
|
+
period_total += amount
|
75
|
+
end
|
76
|
+
end
|
81
77
|
|
82
|
-
|
83
|
-
|
78
|
+
period_total
|
79
|
+
end
|
84
80
|
|
81
|
+
def self.add_categories_to_table(categories, forecast_data)
|
85
82
|
first_period = true
|
86
|
-
|
87
|
-
|
88
|
-
next if
|
83
|
+
categories.each do |period, total|
|
84
|
+
category_total = total.reject { |_, amount| amount == 0 }
|
85
|
+
next if category_total.empty?
|
86
|
+
|
87
|
+
sorted_category_total = sort_transactions(category_total)
|
89
88
|
|
90
|
-
table.add_separator unless first_period
|
91
|
-
table.add_row([{ value: period.capitalize, colspan: 3, alignment: :center }])
|
89
|
+
@table.add_separator unless first_period
|
90
|
+
@table.add_row([{ value: period.capitalize.bold, colspan: 3, alignment: :center }])
|
92
91
|
|
93
92
|
period_total = 0
|
93
|
+
period_total += if period == 'custom'
|
94
|
+
add_rows_to_table(sum_custom_transactions(forecast_data), period_total, custom: true)
|
95
|
+
else
|
96
|
+
add_rows_to_table(sorted_category_total, period_total)
|
97
|
+
end
|
94
98
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
formatted_amount = custom_period[:amount].to_i < 0 ? formatted_amount.green : formatted_amount.red
|
100
|
-
table.add_row [{ value: custom_period[:category], alignment: :left },
|
101
|
-
{ value: "every #{custom_period[:quantity]} #{custom_period[:period]}", alignment: :right }, { value: formatted_amount, alignment: :right }]
|
102
|
-
period_total += custom_period[:amount]
|
103
|
-
end
|
104
|
-
else
|
105
|
-
non_zero_totals.each do |category, amount|
|
106
|
-
formatted_amount = generator.format_transaction({ 'amount' => amount })['amount']
|
107
|
-
formatted_amount = amount.to_i < 0 ? formatted_amount.green : formatted_amount.red
|
108
|
-
|
109
|
-
table.add_row [{ value: category, colspan: 2, alignment: :left },
|
110
|
-
{ value: formatted_amount, alignment: :right }]
|
111
|
-
period_total += amount
|
112
|
-
end
|
113
|
-
end
|
99
|
+
format_total("#{period.capitalize} TOTAL", period_total)
|
100
|
+
first_period = false
|
101
|
+
end
|
102
|
+
end
|
114
103
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
{ value: formatted_period_total, alignment: :right }]
|
104
|
+
def self.sort_transactions(category_total)
|
105
|
+
negatives = category_total.select { |_, amount| amount < 0 }.sort_by { |_, amount| amount }
|
106
|
+
positives = category_total.select { |_, amount| amount > 0 }.sort_by { |_, amount| -amount }
|
119
107
|
|
120
|
-
|
108
|
+
negatives.concat(positives).to_h
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.format_total(text, total)
|
112
|
+
@table.add_row [{ value: text.bold, colspan: 2, alignment: :left },
|
113
|
+
{ value: format_amount(total).bold, alignment: :right }]
|
114
|
+
end
|
115
|
+
|
116
|
+
def self.generate(forecast)
|
117
|
+
forecast_data = YAML.safe_load(forecast)
|
118
|
+
|
119
|
+
init_table
|
120
|
+
init_generator(forecast_data)
|
121
|
+
|
122
|
+
category_totals = {}
|
123
|
+
%w[monthly quarterly half-yearly yearly once custom].each do |period|
|
124
|
+
category_totals[period] = sum_transactions(forecast_data, period)
|
121
125
|
end
|
122
126
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
{ value: formatted_grand_total, alignment: :right }]
|
127
|
+
add_categories_to_table(category_totals, forecast_data)
|
128
|
+
|
129
|
+
@table.add_separator
|
130
|
+
format_total("TOTAL", category_totals.values.map(&:values).flatten.sum)
|
128
131
|
|
129
|
-
puts table
|
132
|
+
puts @table
|
130
133
|
end
|
131
134
|
end
|
132
135
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require_relative '../lib/hledger_forecast'
|
2
|
+
RSpec.describe 'generate' do
|
3
|
+
it 'generates a forecast with correct MONTHLY transactions that have a START DATE' do
|
4
|
+
transactions = File.read('spec/stubs/transactions.journal')
|
5
|
+
forecast = File.read('spec/stubs/start_date/forecast_startdate.yml')
|
6
|
+
|
7
|
+
generated_journal = HledgerForecast::Generator.create_journal_entries(transactions, forecast, '2023-03-01', '2023-08-30')
|
8
|
+
|
9
|
+
expected_output = File.read('spec/stubs/start_date/output_startdate.journal')
|
10
|
+
expect(generated_journal).to eq(expected_output)
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
2023-02-01 * Opening balance
|
2
|
+
Assets:Bank £1,000.00
|
3
|
+
Equity:Opening balance
|
4
|
+
|
5
|
+
2023-02-05 * Mortgage payment
|
6
|
+
Expenses:Mortgage £1,500.00
|
7
|
+
Assets:Bank
|
8
|
+
|
9
|
+
2023-03-01 * Mortgage
|
10
|
+
[Expenses:Mortgage] £2,000.00
|
11
|
+
[Assets:Bank]
|
12
|
+
|
13
|
+
2023-03-01 * Food
|
14
|
+
[Expenses:Food] £100.00
|
15
|
+
[Assets:Bank]
|
16
|
+
|
17
|
+
2023-03-01 * Savings
|
18
|
+
[Assets:Bank] -£1,000.00
|
19
|
+
[Assets:Savings]
|
20
|
+
|
21
|
+
2023-04-01 * Mortgage
|
22
|
+
[Expenses:Mortgage] £2,000.00
|
23
|
+
[Assets:Bank]
|
24
|
+
|
25
|
+
2023-04-01 * Food
|
26
|
+
[Expenses:Food] £100.00
|
27
|
+
[Assets:Bank]
|
28
|
+
|
29
|
+
2023-04-01 * Savings
|
30
|
+
[Assets:Bank] -£1,000.00
|
31
|
+
[Assets:Savings]
|
32
|
+
|
33
|
+
2023-05-01 * Mortgage
|
34
|
+
[Expenses:Mortgage] £2,000.00
|
35
|
+
[Assets:Bank]
|
36
|
+
|
37
|
+
2023-05-01 * Food
|
38
|
+
[Expenses:Food] £100.00
|
39
|
+
[Assets:Bank]
|
40
|
+
|
41
|
+
2023-05-01 * Savings
|
42
|
+
[Assets:Bank] -£1,000.00
|
43
|
+
[Assets:Savings]
|
44
|
+
|
@@ -7,7 +7,7 @@
|
|
7
7
|
Assets:Bank
|
8
8
|
|
9
9
|
2023-03-01 * Mortgage
|
10
|
-
[Expenses:Mortgage] £2,000.
|
10
|
+
[Expenses:Mortgage] £2,000.55
|
11
11
|
[Assets:Bank]
|
12
12
|
|
13
13
|
2023-03-01 * Food
|
@@ -19,7 +19,7 @@
|
|
19
19
|
[Assets:Savings]
|
20
20
|
|
21
21
|
2023-04-01 * Mortgage
|
22
|
-
[Expenses:Mortgage] £2,000.
|
22
|
+
[Expenses:Mortgage] £2,000.55
|
23
23
|
[Assets:Bank]
|
24
24
|
|
25
25
|
2023-04-01 * Food
|
@@ -31,7 +31,7 @@
|
|
31
31
|
[Assets:Savings]
|
32
32
|
|
33
33
|
2023-05-01 * Mortgage
|
34
|
-
[Expenses:Mortgage] £2,000.
|
34
|
+
[Expenses:Mortgage] £2,000.55
|
35
35
|
[Assets:Bank]
|
36
36
|
|
37
37
|
2023-05-01 * Food
|
@@ -0,0 +1,26 @@
|
|
1
|
+
settings:
|
2
|
+
currency: GBP
|
3
|
+
|
4
|
+
monthly:
|
5
|
+
- start: "2023-03-01"
|
6
|
+
account: "[Assets:Bank]"
|
7
|
+
transactions:
|
8
|
+
- description: Monthly Mortgage
|
9
|
+
start: "2023-06-01"
|
10
|
+
category: "[Expenses:Mortgage]"
|
11
|
+
amount: 2000
|
12
|
+
- description: Monthly Food
|
13
|
+
category: "[Expenses:Food]"
|
14
|
+
amount: 100
|
15
|
+
|
16
|
+
quarterly:
|
17
|
+
- start: "2023-04-01"
|
18
|
+
account: "[Assets:Bank]"
|
19
|
+
transactions:
|
20
|
+
- description: Quarterly Mortgage
|
21
|
+
start: "2023-07-01"
|
22
|
+
category: "[Expenses:Mortgage]"
|
23
|
+
amount: 1000
|
24
|
+
- description: Quarterly Food
|
25
|
+
category: "[Expenses:Food]"
|
26
|
+
amount: 50
|
@@ -0,0 +1,56 @@
|
|
1
|
+
2023-02-01 * Opening balance
|
2
|
+
Assets:Bank £1,000.00
|
3
|
+
Equity:Opening balance
|
4
|
+
|
5
|
+
2023-02-05 * Mortgage payment
|
6
|
+
Expenses:Mortgage £1,500.00
|
7
|
+
Assets:Bank
|
8
|
+
|
9
|
+
2023-03-01 * Monthly Food
|
10
|
+
[Expenses:Food] £100.00
|
11
|
+
[Assets:Bank]
|
12
|
+
|
13
|
+
2023-04-01 * Monthly Food
|
14
|
+
[Expenses:Food] £100.00
|
15
|
+
[Assets:Bank]
|
16
|
+
|
17
|
+
2023-04-01 * Quarterly Food
|
18
|
+
[Expenses:Food] £50.00
|
19
|
+
[Assets:Bank]
|
20
|
+
|
21
|
+
2023-05-01 * Monthly Food
|
22
|
+
[Expenses:Food] £100.00
|
23
|
+
[Assets:Bank]
|
24
|
+
|
25
|
+
2023-06-01 * Monthly Mortgage
|
26
|
+
[Expenses:Mortgage] £2,000.00
|
27
|
+
[Assets:Bank]
|
28
|
+
|
29
|
+
2023-06-01 * Monthly Food
|
30
|
+
[Expenses:Food] £100.00
|
31
|
+
[Assets:Bank]
|
32
|
+
|
33
|
+
2023-07-01 * Monthly Mortgage
|
34
|
+
[Expenses:Mortgage] £2,000.00
|
35
|
+
[Assets:Bank]
|
36
|
+
|
37
|
+
2023-07-01 * Monthly Food
|
38
|
+
[Expenses:Food] £100.00
|
39
|
+
[Assets:Bank]
|
40
|
+
|
41
|
+
2023-07-01 * Quarterly Mortgage
|
42
|
+
[Expenses:Mortgage] £1,000.00
|
43
|
+
[Assets:Bank]
|
44
|
+
|
45
|
+
2023-07-01 * Quarterly Food
|
46
|
+
[Expenses:Food] £50.00
|
47
|
+
[Assets:Bank]
|
48
|
+
|
49
|
+
2023-08-01 * Monthly Mortgage
|
50
|
+
[Expenses:Mortgage] £2,000.00
|
51
|
+
[Assets:Bank]
|
52
|
+
|
53
|
+
2023-08-01 * Monthly Food
|
54
|
+
[Expenses:Food] £100.00
|
55
|
+
[Assets:Bank]
|
56
|
+
|
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: 0.1.
|
4
|
+
version: 0.1.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oli Morris
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-04-
|
11
|
+
date: 2023-04-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: highline
|
@@ -109,6 +109,7 @@ files:
|
|
109
109
|
- spec/monthly_spec.rb
|
110
110
|
- spec/once_spec.rb
|
111
111
|
- spec/quarterly_spec.rb
|
112
|
+
- spec/start_date_spec.rb
|
112
113
|
- spec/stubs/custom/forecast_custom_days.yml
|
113
114
|
- spec/stubs/custom/forecast_custom_months.yml
|
114
115
|
- spec/stubs/custom/forecast_custom_weeks.yml
|
@@ -119,6 +120,8 @@ files:
|
|
119
120
|
- spec/stubs/custom/output_custom_weeks_twice.journal
|
120
121
|
- spec/stubs/half-yearly/forecast_half-yearly.yml
|
121
122
|
- spec/stubs/half-yearly/output_half-yearly.journal
|
123
|
+
- spec/stubs/modifiers/forecast_modifiers.yml
|
124
|
+
- spec/stubs/modifiers/output_modifiers.journal
|
122
125
|
- spec/stubs/monthly/forecast_monthly.yml
|
123
126
|
- spec/stubs/monthly/forecast_monthly_enddate.yml
|
124
127
|
- spec/stubs/monthly/forecast_monthly_enddate_top.yml
|
@@ -131,6 +134,8 @@ files:
|
|
131
134
|
- spec/stubs/once/output_once.journal
|
132
135
|
- spec/stubs/quarterly/forecast_quarterly.yml
|
133
136
|
- spec/stubs/quarterly/output_quarterly.journal
|
137
|
+
- spec/stubs/start_date/forecast_startdate.yml
|
138
|
+
- spec/stubs/start_date/output_startdate.journal
|
134
139
|
- spec/stubs/transactions.journal
|
135
140
|
- spec/stubs/yearly/forecast_yearly.yml
|
136
141
|
- spec/stubs/yearly/output_yearly.journal
|
@@ -165,6 +170,7 @@ test_files:
|
|
165
170
|
- spec/monthly_spec.rb
|
166
171
|
- spec/once_spec.rb
|
167
172
|
- spec/quarterly_spec.rb
|
173
|
+
- spec/start_date_spec.rb
|
168
174
|
- spec/stubs/custom/forecast_custom_days.yml
|
169
175
|
- spec/stubs/custom/forecast_custom_months.yml
|
170
176
|
- spec/stubs/custom/forecast_custom_weeks.yml
|
@@ -175,6 +181,8 @@ test_files:
|
|
175
181
|
- spec/stubs/custom/output_custom_weeks_twice.journal
|
176
182
|
- spec/stubs/half-yearly/forecast_half-yearly.yml
|
177
183
|
- spec/stubs/half-yearly/output_half-yearly.journal
|
184
|
+
- spec/stubs/modifiers/forecast_modifiers.yml
|
185
|
+
- spec/stubs/modifiers/output_modifiers.journal
|
178
186
|
- spec/stubs/monthly/forecast_monthly.yml
|
179
187
|
- spec/stubs/monthly/forecast_monthly_enddate.yml
|
180
188
|
- spec/stubs/monthly/forecast_monthly_enddate_top.yml
|
@@ -187,6 +195,8 @@ test_files:
|
|
187
195
|
- spec/stubs/once/output_once.journal
|
188
196
|
- spec/stubs/quarterly/forecast_quarterly.yml
|
189
197
|
- spec/stubs/quarterly/output_quarterly.journal
|
198
|
+
- spec/stubs/start_date/forecast_startdate.yml
|
199
|
+
- spec/stubs/start_date/output_startdate.journal
|
190
200
|
- spec/stubs/transactions.journal
|
191
201
|
- spec/stubs/yearly/forecast_yearly.yml
|
192
202
|
- spec/stubs/yearly/output_yearly.journal
|