hledger-forecast 0.1.9 → 0.2.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/README.md +9 -11
- data/bin/hledger-forecast +2 -2
- data/example.yml +10 -0
- data/lib/hledger_forecast/cli.rb +198 -10
- data/lib/hledger_forecast/generator.rb +1 -1
- data/lib/hledger_forecast/version.rb +1 -1
- data/lib/hledger_forecast.rb +1 -1
- data/spec/command_spec.rb +6 -3
- data/spec/custom_spec.rb +4 -4
- data/spec/half-yearly_spec.rb +1 -1
- data/spec/monthly_spec.rb +3 -3
- data/spec/once_spec.rb +1 -1
- data/spec/quarterly_spec.rb +1 -1
- data/spec/start_date_spec.rb +1 -1
- data/spec/yearly_spec.rb +1 -1
- metadata +2 -3
- data/lib/hledger_forecast/options.rb +0 -77
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a21d32c5ee145d0bca5cb25f07a2fbb6f65126f16c5e15faf2ca11b3fbfac03c
|
4
|
+
data.tar.gz: bbf889db9f129ca62550399b2f2e7818936eee667d356bbeb52b476f305fe6b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b0fa4ad6d50c30eac65acc292d96f500182e211b1a4b9e039dfcff0f204a32ad01d9c01a7570535301bffeb6be865c720d6b8be8ba3e17370a2b992586f351d5
|
7
|
+
data.tar.gz: 554a06876170c161d35b68eececa7904b190aaa0fb6611e2a8bd672fad9b02b48a5a5e26e013db857671fd6f50e33242cb19ddf907fafb31b1b1bd27b74f86df
|
data/README.md
CHANGED
@@ -8,7 +8,7 @@ See the [rationale](#brain-rationale) section for why this gem may be useful to
|
|
8
8
|
|
9
9
|
## :sparkles: Features
|
10
10
|
|
11
|
-
- :book: Uses
|
11
|
+
- :book: Uses simple YAML files to generate forecasts from periodic transactions
|
12
12
|
- :date: Generate forecasts between specified start and end dates
|
13
13
|
- :heavy_dollar_sign: Full currency support (uses the [RubyMoney](https://github.com/RubyMoney/money) gem)
|
14
14
|
- :computer: Simple and easy to use CLI
|
@@ -24,27 +24,25 @@ Assuming you have Ruby and [Rubygems](http://rubygems.org/pages/download) instal
|
|
24
24
|
|
25
25
|
Run:
|
26
26
|
|
27
|
-
hledger-forecast
|
27
|
+
hledger-forecast generate
|
28
28
|
|
29
29
|
> **Note**: This assumes that a `forecast.yml` exists in the current working directory
|
30
30
|
|
31
31
|
Running `hledger-forecast -h` shows the available options:
|
32
32
|
|
33
|
-
Usage: Hledger-Forecast [options]
|
33
|
+
Usage: Hledger-Forecast generate [options]
|
34
34
|
|
35
|
-
-f, --forecast FILE The FORECAST yaml file to generate from
|
36
35
|
-t, --transaction FILE The base TRANSACTIONS file to extend from
|
36
|
+
-f, --forecast FILE The FORECAST yaml file to generate from
|
37
37
|
-o, --output-file FILE The OUTPUT file to create
|
38
38
|
-s, --start-date DATE The date to start generating from (yyyy-mm-dd)
|
39
39
|
-e, --end-date DATE The date to start generating to (yyyy-mm-dd)
|
40
40
|
--force Force an overwrite of the output file
|
41
|
-
|
42
|
-
-h, --help Show this message
|
43
|
-
--version Show version
|
41
|
+
-h, --help Show this help message
|
44
42
|
|
45
43
|
Another example of a common command:
|
46
44
|
|
47
|
-
hledger-forecast -f my_forecast.yml -s 2023-05-01 -e 2024-12-31
|
45
|
+
hledger-forecast generate -f my_forecast.yml -s 2023-05-01 -e 2024-12-31
|
48
46
|
|
49
47
|
This will generate an output file (`my_forecast.journal`) from the forecast file between the two date ranges.
|
50
48
|
|
@@ -180,7 +178,7 @@ settings:
|
|
180
178
|
|
181
179
|
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:
|
182
180
|
|
183
|
-
hledger-forecast -f my_forecast.yml
|
181
|
+
hledger-forecast summarize -f my_forecast.yml
|
184
182
|
|
185
183
|
where `my_forecast.yml` is the config file to sum up.
|
186
184
|
|
@@ -190,8 +188,8 @@ Firstly, I've come to realise from reading countless blog and Reddit posts on [p
|
|
190
188
|
|
191
189
|
My days working in financial modelling have meant that a big macro-enabled spreadsheet was my go-to tool. Growing tired with the manual approach of importing transactions, heavily manipulating them, watching Excel become increasingly slower lead me to PTA. It's been a wonderful discovery.
|
192
190
|
|
193
|
-
One of the aspects of my previous approach to personal finance that I liked was the monthly recap of my performance and the looking ahead to the future. Am I still on track to hit my year-end savings goal given my
|
191
|
+
One of the aspects of my previous approach to personal finance that I liked was the monthly recap of my performance and the looking ahead to the future. Am I still on track to hit my year-end savings goal given my performance to date and my future commitments? And what about my savings goal in 12 and 24 months time? Or, how much are my financial positions impacted if inflation increases by x%? It was at this point in my shift to PTA that I found it difficult to answer those questions quickly.
|
194
192
|
|
195
|
-
While there is support for [forecasting](https://hledger.org/1.29/hledger.html#forecasting) using periodic transactions
|
193
|
+
While there is support in Hledger for [forecasting](https://hledger.org/1.29/hledger.html#forecasting) using periodic transactions, these are computed virtually at runtime. If I notice a big difference in my forecasted year-end balance compared to what I'm expecting, I want to investigate and start reconcilling. Computed transactions make this nigh on impossible to unpick. Also, I get a lot of value out of running different forecast scenarios and seeing the impact. For example, _"what's my savings balance looking like in 3 years time if I get the kitchen remodelled?"_.
|
196
194
|
|
197
195
|
With this gem, my aim was to make it easy for users to change their config file, regenerate the forecast and open a journal file and see the transactions. Or, use multiple forecast files for different scenarios and pass them in turn to Hledger to observe the impact.
|
data/bin/hledger-forecast
CHANGED
@@ -3,10 +3,10 @@
|
|
3
3
|
require_relative '../lib/hledger_forecast'
|
4
4
|
|
5
5
|
begin
|
6
|
-
options = HledgerForecast::
|
6
|
+
subcommand, options = HledgerForecast::Cli.parse_commands
|
7
7
|
rescue RuntimeError => e
|
8
8
|
puts("ERROR: #{e}")
|
9
9
|
exit(1)
|
10
10
|
end
|
11
11
|
|
12
|
-
HledgerForecast::Cli.run(options)
|
12
|
+
HledgerForecast::Cli.run(subcommand, options)
|
data/example.yml
CHANGED
@@ -11,10 +11,20 @@ monthly:
|
|
11
11
|
- amount: 500.00
|
12
12
|
category: "[Expenses:Food]"
|
13
13
|
description: Food
|
14
|
+
- amount: 75
|
15
|
+
category: "[Expenses:Phone]"
|
16
|
+
description: New cell phone
|
17
|
+
start: "2023-08-01"
|
14
18
|
- amount: 1000.00
|
15
19
|
category: "[Expenses:Mortgage]"
|
16
20
|
description: Mortgage
|
17
21
|
end: "2024-01-01"
|
22
|
+
- account: "[Assets:Savings]"
|
23
|
+
start: "2023-03-01"
|
24
|
+
transactions:
|
25
|
+
- amount: -500
|
26
|
+
category: "[Income:Pension]"
|
27
|
+
description: Pension draw down
|
18
28
|
|
19
29
|
quarterly:
|
20
30
|
- account: "[Assets:Bank]"
|
data/lib/hledger_forecast/cli.rb
CHANGED
@@ -1,19 +1,163 @@
|
|
1
1
|
module HledgerForecast
|
2
|
+
# The Command Line Interface for the application
|
3
|
+
# Takes user arguments and translates them into actions
|
2
4
|
class Cli
|
3
|
-
def self.run(args)
|
4
|
-
end_date = args[:end_date]
|
5
|
-
start_date = args[:start_date]
|
6
|
-
forecast = File.read(args[:forecast_file])
|
7
|
-
transactions = args[:transactions_file] ? File.read(args[:transactions_file]) : nil
|
8
5
|
|
9
|
-
|
6
|
+
def self.run(subcommand, options)
|
7
|
+
case subcommand
|
8
|
+
when 'generate'
|
9
|
+
generate(options)
|
10
|
+
when 'summarize'
|
11
|
+
summarize(options)
|
12
|
+
else
|
13
|
+
puts "Unknown command: #{subcommand}"
|
14
|
+
exit(1)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.parse_commands(args = ARGV, _stdin = $stdin)
|
19
|
+
subcommand = nil
|
20
|
+
options = {}
|
21
|
+
|
22
|
+
global = OptionParser.new do |opts|
|
23
|
+
opts.banner = "Usage: hledger-forecast [subcommand] [options]"
|
24
|
+
opts.separator ""
|
25
|
+
opts.separator "Subcommands:"
|
26
|
+
opts.separator " generate Generate the forecast file"
|
27
|
+
opts.separator " summarize Summarize the forecast file and output to the terminal"
|
28
|
+
opts.separator ""
|
29
|
+
opts.separator "Options:"
|
30
|
+
|
31
|
+
opts.on_tail("-h", "--help", "Show this help message") do
|
32
|
+
puts opts
|
33
|
+
exit
|
34
|
+
end
|
35
|
+
|
36
|
+
opts.on_tail("-v", "--version", "Show version") do
|
37
|
+
puts VERSION
|
38
|
+
exit
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
begin
|
43
|
+
global.order!(args)
|
44
|
+
subcommand = args.shift || 'generate'
|
45
|
+
rescue OptionParser::InvalidOption => e
|
46
|
+
puts e
|
47
|
+
puts global
|
48
|
+
exit(1)
|
49
|
+
end
|
50
|
+
|
51
|
+
case subcommand
|
52
|
+
when 'generate'
|
53
|
+
options = parse_generate_options(args)
|
54
|
+
when 'summarize'
|
55
|
+
options = parse_summarize_options(args)
|
56
|
+
else
|
57
|
+
puts "Unknown subcommand: #{subcommand}"
|
58
|
+
puts global
|
59
|
+
exit(1)
|
60
|
+
end
|
61
|
+
|
62
|
+
return subcommand, options
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.parse_generate_options(args)
|
66
|
+
options = {}
|
67
|
+
|
68
|
+
OptionParser.new do |opts|
|
69
|
+
opts.banner = "Usage: Hledger-Forecast generate [options]"
|
70
|
+
opts.separator ""
|
71
|
+
|
72
|
+
opts.on("-t", "--transaction FILE",
|
73
|
+
"The base TRANSACTIONS file to extend from") do |file|
|
74
|
+
options[:transactions_file] = file if file && !file.empty?
|
75
|
+
end
|
76
|
+
|
77
|
+
opts.on("-f", "--forecast FILE",
|
78
|
+
"The FORECAST yaml file to generate from") do |file|
|
79
|
+
options[:forecast_file] = file
|
80
|
+
options[:output_file] ||= file.sub(/\.yml$/, '.journal')
|
81
|
+
end
|
82
|
+
|
83
|
+
opts.on("-o", "--output-file FILE",
|
84
|
+
"The OUTPUT file to create") do |file|
|
85
|
+
options[:output_file] = file
|
86
|
+
end
|
87
|
+
|
88
|
+
opts.on("-s", "--start-date DATE",
|
89
|
+
"The date to start generating from (yyyy-mm-dd)") do |a|
|
90
|
+
options[:start_date] = a
|
91
|
+
end
|
92
|
+
|
93
|
+
opts.on("-e", "--end-date DATE",
|
94
|
+
"The date to start generating to (yyyy-mm-dd)") do |a|
|
95
|
+
options[:end_date] = a
|
96
|
+
end
|
97
|
+
|
98
|
+
opts.on("--force",
|
99
|
+
"Force an overwrite of the output file") do |a|
|
100
|
+
options[:force] = a
|
101
|
+
end
|
102
|
+
|
103
|
+
opts.on_tail("-h", "--help", "Show this help message") do
|
104
|
+
puts opts
|
105
|
+
exit
|
106
|
+
end
|
107
|
+
end.parse!(args)
|
108
|
+
|
109
|
+
options[:forecast_file] = "forecast.yml" unless options[:forecast_file]
|
110
|
+
options[:output_file] = "forecast.journal" unless options[:output_file]
|
111
|
+
|
112
|
+
today = Date.today
|
113
|
+
|
114
|
+
unless options[:start_date]
|
115
|
+
options[:default_dates] = true
|
116
|
+
options[:start_date] =
|
117
|
+
Date.new(today.year, today.month, 1).next_month.to_s
|
118
|
+
end
|
119
|
+
unless options[:end_date]
|
120
|
+
options[:default_dates] = true
|
121
|
+
options[:end_date] = Date.new(today.year + 3, 12, 31).to_s
|
122
|
+
end
|
123
|
+
|
124
|
+
options
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.parse_summarize_options(args)
|
128
|
+
options = {}
|
10
129
|
|
11
|
-
|
130
|
+
OptionParser.new do |opts|
|
131
|
+
opts.banner = "Usage: Hledger-Forecast summarize [options]"
|
132
|
+
opts.separator ""
|
133
|
+
|
134
|
+
opts.on("-f", "--forecast FILE",
|
135
|
+
"The FORECAST yaml file to summarize") do |file|
|
136
|
+
options[:forecast_file] = file
|
137
|
+
end
|
12
138
|
|
13
|
-
|
139
|
+
opts.on_tail("-h", "--help", "Show this help message") do
|
140
|
+
puts opts
|
141
|
+
exit
|
142
|
+
end
|
143
|
+
end.parse!(args)
|
144
|
+
|
145
|
+
options
|
146
|
+
end
|
14
147
|
|
15
|
-
|
16
|
-
|
148
|
+
def self.generate(options)
|
149
|
+
end_date = options[:end_date]
|
150
|
+
start_date = options[:start_date]
|
151
|
+
forecast = File.read(options[:forecast_file])
|
152
|
+
transactions = options[:transactions_file] ? File.read(options[:transactions_file]) : nil
|
153
|
+
|
154
|
+
# Generate the forecast
|
155
|
+
puts "[Using default dates: #{start_date} to #{end_date}]" if options[:default_dates]
|
156
|
+
|
157
|
+
transactions = Generator.generate(transactions, forecast, start_date, end_date)
|
158
|
+
|
159
|
+
output_file = options[:output_file]
|
160
|
+
if File.exist?(output_file) && !options[:force]
|
17
161
|
print "File '#{output_file}' already exists. Overwrite? (y/n): "
|
18
162
|
overwrite = gets.chomp.downcase
|
19
163
|
|
@@ -28,5 +172,49 @@ module HledgerForecast
|
|
28
172
|
puts "File '#{output_file}' has been created."
|
29
173
|
end
|
30
174
|
end
|
175
|
+
|
176
|
+
def self.summarize(options)
|
177
|
+
forecast = File.read(options[:forecast_file])
|
178
|
+
puts Summarize.generate(forecast)
|
179
|
+
end
|
180
|
+
|
181
|
+
# def self.run(args)
|
182
|
+
# end_date = args[:end_date]
|
183
|
+
# start_date = args[:start_date]
|
184
|
+
# forecast = File.read(args[:forecast_file])
|
185
|
+
# transactions = args[:transactions_file] ? File.read(args[:transactions_file]) : nil
|
186
|
+
#
|
187
|
+
# # Output the summary
|
188
|
+
# return HledgerForecast::Summarize.generate(forecast) if args[:summarize]
|
189
|
+
#
|
190
|
+
# # Generate the forecast
|
191
|
+
# unless args[:skip]
|
192
|
+
#
|
193
|
+
# puts "[Using default dates: #{start_date} to #{end_date}]" if args[:default_dates]
|
194
|
+
#
|
195
|
+
# transactions = Generator.generate(transactions, forecast, start_date, end_date)
|
196
|
+
#
|
197
|
+
# output_file = args[:output_file]
|
198
|
+
# if File.exist?(output_file) && !args[:force]
|
199
|
+
# print "File '#{output_file}' already exists. Overwrite? (y/n): "
|
200
|
+
# overwrite = gets.chomp.downcase
|
201
|
+
#
|
202
|
+
# if overwrite == 'y'
|
203
|
+
# File.write(output_file, transactions)
|
204
|
+
# puts "File '#{output_file}' has been overwritten."
|
205
|
+
# else
|
206
|
+
# puts "Operation aborted. File '#{output_file}' was not overwritten."
|
207
|
+
# end
|
208
|
+
# else
|
209
|
+
# File.write(output_file, transactions)
|
210
|
+
# puts "File '#{output_file}' has been created."
|
211
|
+
# end
|
212
|
+
# end
|
213
|
+
#
|
214
|
+
# # Check for missing transactions
|
215
|
+
# return unless args[:check] && args[:transactions_file] && args[:forecast_file]
|
216
|
+
#
|
217
|
+
# HledgerForecast::Checker.check(args)
|
218
|
+
# end
|
31
219
|
end
|
32
220
|
end
|
@@ -101,7 +101,7 @@ module HledgerForecast
|
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
104
|
-
def self.
|
104
|
+
def self.generate(transactions, forecast, start_date, end_date)
|
105
105
|
start_date = Date.parse(start_date)
|
106
106
|
end_date = Date.parse(end_date)
|
107
107
|
forecast_data = YAML.safe_load(forecast)
|
data/lib/hledger_forecast.rb
CHANGED
@@ -12,7 +12,7 @@ Money.locale_backend = nil
|
|
12
12
|
Money.rounding_mode = BigDecimal::ROUND_HALF_UP
|
13
13
|
|
14
14
|
require_relative 'hledger_forecast/version'
|
15
|
-
require_relative 'hledger_forecast/options'
|
16
15
|
require_relative 'hledger_forecast/generator'
|
17
16
|
require_relative 'hledger_forecast/summarize'
|
17
|
+
require_relative 'hledger_forecast/checker'
|
18
18
|
require_relative 'hledger_forecast/cli'
|
data/spec/command_spec.rb
CHANGED
@@ -2,11 +2,14 @@ require_relative '../lib/hledger_forecast'
|
|
2
2
|
|
3
3
|
RSpec.describe 'command' do
|
4
4
|
it 'uses the CLI to generate an output' do
|
5
|
-
|
5
|
+
# Delete the file if it exists
|
6
|
+
generated_journal = './test_output.journal'
|
7
|
+
File.delete(generated_journal) if File.exist?(generated_journal)
|
8
|
+
|
9
|
+
system("./bin/hledger-forecast generate -t ./spec/stubs/transactions.journal -f ./spec/stubs/monthly/forecast_monthly.yml -o ./test_output.journal -s 2023-03-01 -e 2023-05-30 --force")
|
6
10
|
|
7
11
|
expected_output = File.read('spec/stubs/monthly/output_monthly.journal')
|
8
|
-
generated_journal = File.read('./test_output.journal')
|
9
12
|
|
10
|
-
expect(generated_journal).to eq(expected_output)
|
13
|
+
expect(File.read(generated_journal)).to eq(expected_output)
|
11
14
|
end
|
12
15
|
end
|
data/spec/custom_spec.rb
CHANGED
@@ -5,7 +5,7 @@ RSpec.describe 'generate' do
|
|
5
5
|
transactions = File.read('spec/stubs/transactions.journal')
|
6
6
|
forecast = File.read('spec/stubs/custom/forecast_custom_days.yml')
|
7
7
|
|
8
|
-
generated_journal = HledgerForecast::Generator.
|
8
|
+
generated_journal = HledgerForecast::Generator.generate(transactions, forecast, '2023-03-01',
|
9
9
|
'2023-03-10')
|
10
10
|
|
11
11
|
expected_output = File.read('spec/stubs/custom/output_custom_days.journal')
|
@@ -16,7 +16,7 @@ RSpec.describe 'generate' do
|
|
16
16
|
transactions = File.read('spec/stubs/transactions.journal')
|
17
17
|
forecast = File.read('spec/stubs/custom/forecast_custom_weeks.yml')
|
18
18
|
|
19
|
-
generated_journal = HledgerForecast::Generator.
|
19
|
+
generated_journal = HledgerForecast::Generator.generate(transactions, forecast, '2023-03-01',
|
20
20
|
'2023-04-30')
|
21
21
|
|
22
22
|
expected_output = File.read('spec/stubs/custom/output_custom_weeks.journal')
|
@@ -27,7 +27,7 @@ RSpec.describe 'generate' do
|
|
27
27
|
transactions = File.read('spec/stubs/transactions.journal')
|
28
28
|
forecast = File.read('spec/stubs/custom/forecast_custom_weeks_twice.yml')
|
29
29
|
|
30
|
-
generated_journal = HledgerForecast::Generator.
|
30
|
+
generated_journal = HledgerForecast::Generator.generate(transactions, forecast, '2023-03-01',
|
31
31
|
'2023-03-30')
|
32
32
|
|
33
33
|
expected_output = File.read('spec/stubs/custom/output_custom_weeks_twice.journal')
|
@@ -38,7 +38,7 @@ RSpec.describe 'generate' do
|
|
38
38
|
transactions = File.read('spec/stubs/transactions.journal')
|
39
39
|
forecast = File.read('spec/stubs/custom/forecast_custom_months.yml')
|
40
40
|
|
41
|
-
generated_journal = HledgerForecast::Generator.
|
41
|
+
generated_journal = HledgerForecast::Generator.generate(transactions, forecast, '2023-03-01',
|
42
42
|
'2024-02-28')
|
43
43
|
|
44
44
|
expected_output = File.read('spec/stubs/custom/output_custom_months.journal')
|
data/spec/half-yearly_spec.rb
CHANGED
@@ -5,7 +5,7 @@ RSpec.describe 'generate' do
|
|
5
5
|
transactions = File.read('spec/stubs/transactions.journal')
|
6
6
|
forecast = File.read('spec/stubs/half-yearly/forecast_half-yearly.yml')
|
7
7
|
|
8
|
-
generated_journal = HledgerForecast::Generator.
|
8
|
+
generated_journal = HledgerForecast::Generator.generate(transactions, forecast, '2023-03-01', '2024-04-30')
|
9
9
|
|
10
10
|
expected_output = File.read('spec/stubs/half-yearly/output_half-yearly.journal')
|
11
11
|
expect(generated_journal).to eq(expected_output)
|
data/spec/monthly_spec.rb
CHANGED
@@ -5,7 +5,7 @@ RSpec.describe 'generate' do
|
|
5
5
|
transactions = File.read('spec/stubs/transactions.journal')
|
6
6
|
forecast = File.read('spec/stubs/monthly/forecast_monthly.yml')
|
7
7
|
|
8
|
-
generated_journal = HledgerForecast::Generator.
|
8
|
+
generated_journal = HledgerForecast::Generator.generate(transactions, forecast, '2023-03-01', '2023-05-30')
|
9
9
|
|
10
10
|
expected_output = File.read('spec/stubs/monthly/output_monthly.journal')
|
11
11
|
expect(generated_journal).to eq(expected_output)
|
@@ -15,7 +15,7 @@ RSpec.describe 'generate' do
|
|
15
15
|
transactions = File.read('spec/stubs/transactions.journal')
|
16
16
|
forecast = File.read('spec/stubs/monthly/forecast_monthly_enddate.yml')
|
17
17
|
|
18
|
-
generated_journal = HledgerForecast::Generator.
|
18
|
+
generated_journal = HledgerForecast::Generator.generate(transactions, forecast, '2023-03-01', '2023-08-30')
|
19
19
|
|
20
20
|
expected_output = File.read('spec/stubs/monthly/output_monthly_enddate.journal')
|
21
21
|
expect(generated_journal).to eq(expected_output)
|
@@ -25,7 +25,7 @@ RSpec.describe 'generate' do
|
|
25
25
|
transactions = File.read('spec/stubs/transactions.journal')
|
26
26
|
forecast = File.read('spec/stubs/monthly/forecast_monthly_enddate_top.yml')
|
27
27
|
|
28
|
-
generated_journal = HledgerForecast::Generator.
|
28
|
+
generated_journal = HledgerForecast::Generator.generate(transactions, forecast, '2023-03-01', '2023-08-30')
|
29
29
|
|
30
30
|
expected_output = File.read('spec/stubs/monthly/output_monthly_enddate_top.journal')
|
31
31
|
expect(generated_journal).to eq(expected_output)
|
data/spec/once_spec.rb
CHANGED
@@ -5,7 +5,7 @@ RSpec.describe 'generate' do
|
|
5
5
|
transactions = File.read('spec/stubs/transactions.journal')
|
6
6
|
forecast = File.read('spec/stubs/once/forecast_once.yml')
|
7
7
|
|
8
|
-
generated_journal = HledgerForecast::Generator.
|
8
|
+
generated_journal = HledgerForecast::Generator.generate(transactions, forecast, '2023-03-01', '2024-04-30')
|
9
9
|
|
10
10
|
expected_output = File.read('spec/stubs/once/output_once.journal')
|
11
11
|
expect(generated_journal).to eq(expected_output)
|
data/spec/quarterly_spec.rb
CHANGED
@@ -5,7 +5,7 @@ RSpec.describe 'generate' do
|
|
5
5
|
transactions = File.read('spec/stubs/transactions.journal')
|
6
6
|
forecast = File.read('spec/stubs/quarterly/forecast_quarterly.yml')
|
7
7
|
|
8
|
-
generated_journal = HledgerForecast::Generator.
|
8
|
+
generated_journal = HledgerForecast::Generator.generate(transactions, forecast, '2023-03-01', '2023-10-30')
|
9
9
|
|
10
10
|
expected_output = File.read('spec/stubs/quarterly/output_quarterly.journal')
|
11
11
|
expect(generated_journal).to eq(expected_output)
|
data/spec/start_date_spec.rb
CHANGED
@@ -4,7 +4,7 @@ RSpec.describe 'generate' do
|
|
4
4
|
transactions = File.read('spec/stubs/transactions.journal')
|
5
5
|
forecast = File.read('spec/stubs/start_date/forecast_startdate.yml')
|
6
6
|
|
7
|
-
generated_journal = HledgerForecast::Generator.
|
7
|
+
generated_journal = HledgerForecast::Generator.generate(transactions, forecast, '2023-03-01', '2023-08-30')
|
8
8
|
|
9
9
|
expected_output = File.read('spec/stubs/start_date/output_startdate.journal')
|
10
10
|
expect(generated_journal).to eq(expected_output)
|
data/spec/yearly_spec.rb
CHANGED
@@ -5,7 +5,7 @@ RSpec.describe 'generate' do
|
|
5
5
|
transactions = File.read('spec/stubs/transactions.journal')
|
6
6
|
forecast = File.read('spec/stubs/yearly/forecast_yearly.yml')
|
7
7
|
|
8
|
-
generated_journal = HledgerForecast::Generator.
|
8
|
+
generated_journal = HledgerForecast::Generator.generate(transactions, forecast, '2023-03-01', '2024-04-30')
|
9
9
|
|
10
10
|
expected_output = File.read('spec/stubs/yearly/output_yearly.journal')
|
11
11
|
expect(generated_journal).to eq(expected_output)
|
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.
|
4
|
+
version: 0.2.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: 2023-04-
|
11
|
+
date: 2023-04-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: highline
|
@@ -100,7 +100,6 @@ files:
|
|
100
100
|
- lib/hledger_forecast.rb
|
101
101
|
- lib/hledger_forecast/cli.rb
|
102
102
|
- lib/hledger_forecast/generator.rb
|
103
|
-
- lib/hledger_forecast/options.rb
|
104
103
|
- lib/hledger_forecast/summarize.rb
|
105
104
|
- lib/hledger_forecast/version.rb
|
106
105
|
- spec/command_spec.rb
|
@@ -1,77 +0,0 @@
|
|
1
|
-
module HledgerForecast
|
2
|
-
class Options
|
3
|
-
def self.parse_command_line_options(args = ARGV, _stdin = $stdin)
|
4
|
-
options = {}
|
5
|
-
|
6
|
-
OptionParser.new do |opts|
|
7
|
-
opts.banner = "Usage: Hledger-Forecast [options]"
|
8
|
-
opts.separator ""
|
9
|
-
|
10
|
-
opts.on("-f", "--forecast FILE",
|
11
|
-
"The FORECAST yaml file to generate from") do |file|
|
12
|
-
options[:forecast_file] = file
|
13
|
-
options[:output_file] ||= file.sub(/\.yml$/, '.journal')
|
14
|
-
end
|
15
|
-
|
16
|
-
opts.on("-t", "--transaction FILE",
|
17
|
-
"The base TRANSACTIONS file to extend from") do |file|
|
18
|
-
options[:transactions_file] = file if file && !file.empty?
|
19
|
-
end
|
20
|
-
|
21
|
-
opts.on("-o", "--output-file FILE",
|
22
|
-
"The OUTPUT file to create") do |file|
|
23
|
-
options[:output_file] = file
|
24
|
-
end
|
25
|
-
|
26
|
-
opts.on("-s", "--start-date DATE",
|
27
|
-
"The date to start generating from (yyyy-mm-dd)") do |a|
|
28
|
-
options[:start_date] = a
|
29
|
-
end
|
30
|
-
|
31
|
-
opts.on("-e", "--end-date DATE",
|
32
|
-
"The date to start generating to (yyyy-mm-dd)") do |a|
|
33
|
-
options[:end_date] = a
|
34
|
-
end
|
35
|
-
|
36
|
-
opts.on("--summarize",
|
37
|
-
"Summarize the forecast file and output to the terminal") do |a|
|
38
|
-
options[:summarize] = a
|
39
|
-
end
|
40
|
-
|
41
|
-
opts.on("--force",
|
42
|
-
"Force an overwrite of the output file") do |a|
|
43
|
-
options[:force] = a
|
44
|
-
end
|
45
|
-
|
46
|
-
opts.on_tail("-h", "--help", "Show this message") do
|
47
|
-
puts opts
|
48
|
-
exit
|
49
|
-
end
|
50
|
-
|
51
|
-
opts.on_tail("--version", "Show version") do
|
52
|
-
puts VERSION
|
53
|
-
exit
|
54
|
-
end
|
55
|
-
|
56
|
-
opts.parse!(args)
|
57
|
-
end
|
58
|
-
|
59
|
-
options[:forecast_file] = "forecast.yml" unless options[:forecast_file]
|
60
|
-
options[:output_file] = "forecast.journal" unless options[:output_file]
|
61
|
-
|
62
|
-
today = Date.today
|
63
|
-
|
64
|
-
unless options[:start_date]
|
65
|
-
options[:default_dates] = true
|
66
|
-
options[:start_date] =
|
67
|
-
Date.new(today.year, today.month, 1).next_month.to_s
|
68
|
-
end
|
69
|
-
unless options[:end_date]
|
70
|
-
options[:default_dates] = true
|
71
|
-
options[:end_date] = Date.new(today.year + 3, 12, 31).to_s
|
72
|
-
end
|
73
|
-
|
74
|
-
return options
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|