hledger-forecast 1.4.0 → 1.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +25 -15
- data/hledger-forecast.gemspec +1 -1
- data/lib/hledger_forecast/cli.rb +79 -8
- data/lib/hledger_forecast/comparator.rb +86 -0
- data/lib/hledger_forecast/version.rb +1 -1
- data/lib/hledger_forecast.rb +2 -0
- data/spec/{command_spec.rb → cli_spec.rb} +28 -0
- data/spec/compare_spec.rb +54 -0
- data/spec/stubs/output1.csv +2 -0
- data/spec/stubs/output2.csv +2 -0
- metadata +13 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '09b594c8b6cf3c239d070abbb2101cf63a7d2b987f4c2e6680ba02b160c29e24'
|
4
|
+
data.tar.gz: 8df343c7d6baa56d46f053d83fb6152c26ef94308c96a493c4995b78ddfccf80
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d395581b614dd9d9931701964959092a6a897ce16daad53b3f1b7b96583e4905962f09bfe3f0cdac1a2583d0e287bb4f602d53c1dc674cd1ecb1dc421c8cafd1
|
7
|
+
data.tar.gz: 241f5d557cc7f777790fe3546a897aa2af73052b35555031bd0d13dcf4d9f65a117002da7c34726334bcec2b76eb3fb6a508dd699dfa7c9306c4980092776a3b
|
data/README.md
CHANGED
@@ -11,30 +11,30 @@
|
|
11
11
|
<a href="https://github.com/olimorris/hledger-forecast/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/olimorris/hledger-forecast/ci.yml?branch=main&label=tests&style=for-the-badge"></a>
|
12
12
|
</p>
|
13
13
|
|
14
|
-
**"Improved", you say?** Using a _CSV_ (or _YML_) file, forecasts can be quickly generated into a _journal_ file ready to be fed into [hledger](https://github.com/simonmichael/hledger). **A
|
14
|
+
**"Improved", you say?** Using a _CSV_ (or _YML_) 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
|
-
- :
|
21
|
-
- :
|
22
|
-
- :
|
23
|
-
- :
|
24
|
-
- :
|
20
|
+
- :rocket: Uses a simple CSV (or YML) file to generate forecasts which can be used with hledger
|
21
|
+
- :calendar: Can smartly track forecasts against your bank statement
|
22
|
+
- :dollar: Can automatically apply modifiers such as inflation/deflation to forecasts
|
23
|
+
- :mag: Enables the use of maths in your forecasts (for amounts and dates)
|
24
|
+
- :bar_chart: Display your forecasts as income and expenditure reports (e.g. daily, weekly, monthly)
|
25
|
+
- :twisted_rightwards_arrows: Compare and display the difference between hledger outputs
|
25
26
|
- :computer: Simple and easy to use CLI
|
26
27
|
|
27
28
|
## :camera_flash: Screenshots
|
28
29
|
|
29
|
-
**CSV forecast and
|
30
|
+
**A CSV forecast and the hledger journal it generates**
|
30
31
|
|
31
|
-
<img src="https://github.com/olimorris/hledger-forecast/assets/9512444/430503b5-f447-4972-b122-b48f8628aff9" alt="
|
32
|
+
<img src="https://github.com/olimorris/hledger-forecast/assets/9512444/430503b5-f447-4972-b122-b48f8628aff9" alt="hledger-Forecast" />
|
32
33
|
|
33
|
-
**
|
34
|
+
**The ouput from the `summarize` command**
|
34
35
|
|
35
36
|
<img src="https://github.com/olimorris/hledger-forecast/assets/9512444/f5017ea2-9606-46ec-8b38-8840dc175e7b" alt="Summarize command" />
|
36
37
|
|
37
|
-
|
38
38
|
## :package: Installation
|
39
39
|
|
40
40
|
Assuming you have Ruby and [Rubygems](http://rubygems.org/pages/download) installed on your system, simply run:
|
@@ -52,8 +52,9 @@ The available options are:
|
|
52
52
|
Usage: hledger-forecast [command] [options]
|
53
53
|
|
54
54
|
Commands:
|
55
|
-
generate Generate
|
55
|
+
generate Generate a forecast from a file
|
56
56
|
summarize Summarize the forecast file and output to the terminal
|
57
|
+
compare Compare and highlight the differences between two CSV files
|
57
58
|
|
58
59
|
Options:
|
59
60
|
-h, --help Show this help message
|
@@ -91,9 +92,7 @@ If you use the `hledger-ui` tool, it may be helpful to use the `--verbose` flag.
|
|
91
92
|
|
92
93
|
### Summarize command
|
93
94
|
|
94
|
-
As your
|
95
|
-
Furthermore, being able to see your monthly profit and loss statement _if_ you were to purchase that new item may
|
96
|
-
influence your buying decision. In hledger-forecast, this can be achieved by:
|
95
|
+
As your forecast file grows, it can be helpful to sum up the total amounts and output them to the CLI. Think of this command as your own _profit and loss_ summarizer, generating a statement over a period you specify.
|
97
96
|
|
98
97
|
hledger-forecast summarize -f my_forecast.csv
|
99
98
|
|
@@ -107,6 +106,18 @@ The available options are:
|
|
107
106
|
-v, --verbose Show additional information in the summary
|
108
107
|
-h, --help Show this help message
|
109
108
|
|
109
|
+
### Compare command
|
110
|
+
|
111
|
+
A core part of managing your personal finances is the comparison of what you _expected_ to happen versus what _actually_ happened. This can be challenging to accomplish with hledger so to make this easier, the app has a useful `compare` command:
|
112
|
+
|
113
|
+
hledger-forecast compare [path/to/file1.csv] [path/to/file2.csv]
|
114
|
+
|
115
|
+
To generate CSV output with hledger, append `-O csv > output.csv` to your desired command.
|
116
|
+
|
117
|
+
To make it easier to read horizontal output in the terminal, consider the use of a terminal pager like [most](https://en.wikipedia.org/wiki/Most_(Unix)) by appending `| most` to the compare command.
|
118
|
+
|
119
|
+
> **Note:** The two CSV files being compared must have the same structure
|
120
|
+
|
110
121
|
## :gear: Creating your forecast
|
111
122
|
|
112
123
|
The app makes it easy to generate a comprehensive _journal_ file with very few lines of code, making it much easier to stay on top of your forecasting from month to month.
|
@@ -375,4 +386,3 @@ The app will use a hledger query to determine if the combination of category and
|
|
375
386
|
## :pencil2: Contributing
|
376
387
|
|
377
388
|
I am open to any pull requests that fix bugs but would ask that any new functionality is discussed before it could be accepted.
|
378
|
-
|
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 = '
|
12
|
+
s.description = 'Use a CSV or YAML 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'
|
data/lib/hledger_forecast/cli.rb
CHANGED
@@ -8,6 +8,8 @@ module HledgerForecast
|
|
8
8
|
generate(options)
|
9
9
|
when 'summarize'
|
10
10
|
summarize(options)
|
11
|
+
when 'compare'
|
12
|
+
compare(options)
|
11
13
|
else
|
12
14
|
puts "Unknown command: #{command}"
|
13
15
|
exit(1)
|
@@ -22,8 +24,9 @@ module HledgerForecast
|
|
22
24
|
opts.banner = "Usage: hledger-forecast [command] [options]"
|
23
25
|
opts.separator ""
|
24
26
|
opts.separator "Commands:"
|
25
|
-
opts.separator " generate Generate
|
27
|
+
opts.separator " generate Generate a forecast from a file"
|
26
28
|
opts.separator " summarize Summarize the forecast file and output to the terminal"
|
29
|
+
opts.separator " compare Compare and highlight the differences between two CSV files"
|
27
30
|
opts.separator ""
|
28
31
|
opts.separator "Options:"
|
29
32
|
|
@@ -38,6 +41,11 @@ module HledgerForecast
|
|
38
41
|
end
|
39
42
|
end
|
40
43
|
|
44
|
+
if args.empty?
|
45
|
+
puts global
|
46
|
+
exit(1)
|
47
|
+
end
|
48
|
+
|
41
49
|
begin
|
42
50
|
global.order!(args)
|
43
51
|
command = args.shift || 'generate'
|
@@ -52,6 +60,8 @@ module HledgerForecast
|
|
52
60
|
options = parse_generate_options(args)
|
53
61
|
when 'summarize'
|
54
62
|
options = parse_summarize_options(args)
|
63
|
+
when 'compare'
|
64
|
+
options = parse_compare_options(args)
|
55
65
|
else
|
56
66
|
puts "Unknown command: #{command}"
|
57
67
|
puts global
|
@@ -64,7 +74,7 @@ module HledgerForecast
|
|
64
74
|
def self.parse_generate_options(args)
|
65
75
|
options = {}
|
66
76
|
|
67
|
-
OptionParser.new do |opts|
|
77
|
+
global = OptionParser.new do |opts|
|
68
78
|
opts.banner = "Usage: hledger-forecast generate [options]"
|
69
79
|
opts.separator ""
|
70
80
|
|
@@ -110,11 +120,24 @@ module HledgerForecast
|
|
110
120
|
puts opts
|
111
121
|
exit
|
112
122
|
end
|
113
|
-
end
|
123
|
+
end
|
124
|
+
|
125
|
+
begin
|
126
|
+
global.parse!(args)
|
127
|
+
rescue OptionParser::InvalidOption => e
|
128
|
+
puts e
|
129
|
+
puts global
|
130
|
+
exit(1)
|
131
|
+
end
|
132
|
+
|
133
|
+
if options.empty?
|
134
|
+
puts global
|
135
|
+
exit(1)
|
136
|
+
end
|
114
137
|
|
115
|
-
options[:forecast_file]
|
116
|
-
options[:file_type]
|
117
|
-
options[:output_file]
|
138
|
+
options[:forecast_file] ||= "forecast.csv"
|
139
|
+
options[:file_type] ||= "csv"
|
140
|
+
options[:output_file] ||= "forecast.journal"
|
118
141
|
|
119
142
|
options
|
120
143
|
end
|
@@ -122,7 +145,7 @@ module HledgerForecast
|
|
122
145
|
def self.parse_summarize_options(args)
|
123
146
|
options = {}
|
124
147
|
|
125
|
-
OptionParser.new do |opts|
|
148
|
+
global = OptionParser.new do |opts|
|
126
149
|
opts.banner = "Usage: hledger-forecast summarize [options]"
|
127
150
|
opts.separator ""
|
128
151
|
|
@@ -168,7 +191,47 @@ module HledgerForecast
|
|
168
191
|
puts opts
|
169
192
|
exit
|
170
193
|
end
|
171
|
-
end
|
194
|
+
end
|
195
|
+
|
196
|
+
begin
|
197
|
+
global.parse!(args)
|
198
|
+
rescue OptionParser::InvalidOption => e
|
199
|
+
puts e
|
200
|
+
puts global
|
201
|
+
exit(1)
|
202
|
+
end
|
203
|
+
|
204
|
+
if options.empty?
|
205
|
+
puts global
|
206
|
+
exit(1)
|
207
|
+
end
|
208
|
+
|
209
|
+
options
|
210
|
+
end
|
211
|
+
|
212
|
+
def self.parse_compare_options(args)
|
213
|
+
options = {}
|
214
|
+
|
215
|
+
global = OptionParser.new do |opts|
|
216
|
+
opts.banner = "Usage: hledger-forecast compare [path/to/file1.csv] [path/to/file2.csv]"
|
217
|
+
opts.separator ""
|
218
|
+
end
|
219
|
+
|
220
|
+
begin
|
221
|
+
global.parse!(args)
|
222
|
+
rescue OptionParser::InvalidOption => e
|
223
|
+
puts e
|
224
|
+
puts global
|
225
|
+
exit(1)
|
226
|
+
end
|
227
|
+
|
228
|
+
if args[0].nil? || args[1].nil?
|
229
|
+
puts global
|
230
|
+
exit(1)
|
231
|
+
end
|
232
|
+
|
233
|
+
options[:file1] = args[0]
|
234
|
+
options[:file2] = args[1]
|
172
235
|
|
173
236
|
options
|
174
237
|
end
|
@@ -210,5 +273,13 @@ module HledgerForecast
|
|
210
273
|
|
211
274
|
puts SummarizerFormatter.format(summarizer[:output], summarizer[:settings])
|
212
275
|
end
|
276
|
+
|
277
|
+
def self.compare(options)
|
278
|
+
if !File.exist?(options[:file1]) || !File.exist?(options[:file2])
|
279
|
+
return puts "\nError: ".bold.red + "One or more of the files could not be found to compare"
|
280
|
+
end
|
281
|
+
|
282
|
+
puts Comparator.compare(options[:file1], options[:file2])
|
283
|
+
end
|
213
284
|
end
|
214
285
|
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module HledgerForecast
|
2
|
+
# Compare the output of two CSV files
|
3
|
+
class Comparator
|
4
|
+
def initialize
|
5
|
+
@table = Terminal::Table.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.compare(file1, file2)
|
9
|
+
new.compare(file1, file2)
|
10
|
+
end
|
11
|
+
|
12
|
+
def compare(file1, file2)
|
13
|
+
compare_csvs(file1, file2)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def compare_csvs(file1, file2)
|
19
|
+
csv1 = CSV.read(file1)
|
20
|
+
csv2 = CSV.read(file2)
|
21
|
+
|
22
|
+
unless csv1.length == csv2.length && csv1[0].length == csv2[0].length
|
23
|
+
return puts "\nError: ".bold.red + "The files have different formats and cannot be compared"
|
24
|
+
end
|
25
|
+
|
26
|
+
@table.add_row csv2[0].map(&:bold)
|
27
|
+
@table.add_separator
|
28
|
+
|
29
|
+
generate_diff(csv1, csv2).drop(1).each do |row|
|
30
|
+
@table.add_row [row[0].bold] + row[1..]
|
31
|
+
end
|
32
|
+
|
33
|
+
puts @table
|
34
|
+
end
|
35
|
+
|
36
|
+
def header?(row_num)
|
37
|
+
row_num == 0
|
38
|
+
end
|
39
|
+
|
40
|
+
def generate_diff(csv1, csv2)
|
41
|
+
csv1.each_with_index.map do |row, i|
|
42
|
+
row.each_with_index.map do |cell, j|
|
43
|
+
if header?(i) || j == 0 # Checking for the first column here
|
44
|
+
csv2[i][j]
|
45
|
+
else
|
46
|
+
difference = parse_money(csv2[i][j]) - parse_money(cell)
|
47
|
+
format_difference(difference, detect_currency(cell))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def detect_currency(str)
|
54
|
+
return nil if str == "0"
|
55
|
+
|
56
|
+
# Explicitly check for common currencies
|
57
|
+
return "GBP" if str.include?("£")
|
58
|
+
return "EUR" if str.include?("€")
|
59
|
+
return "USD" if str.include?("$")
|
60
|
+
|
61
|
+
Money::Currency.table.each_value do |currency|
|
62
|
+
return currency[:iso_code] if str.include?(currency[:symbol])
|
63
|
+
end
|
64
|
+
|
65
|
+
nil
|
66
|
+
end
|
67
|
+
|
68
|
+
def parse_money(value)
|
69
|
+
return 0.0 if value.strip == '0'
|
70
|
+
|
71
|
+
value.gsub(/[^0-9.-]/, '').to_f
|
72
|
+
end
|
73
|
+
|
74
|
+
def format_difference(amount, currency)
|
75
|
+
formatted_amount = if currency.nil?
|
76
|
+
format("%.2f", amount)
|
77
|
+
else
|
78
|
+
Formatter.format_money(amount, { currency: currency })
|
79
|
+
end
|
80
|
+
|
81
|
+
return formatted_amount if amount == 0
|
82
|
+
|
83
|
+
amount > 0 ? formatted_amount.green : formatted_amount.red
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/hledger_forecast.rb
CHANGED
@@ -12,9 +12,11 @@ require 'yaml'
|
|
12
12
|
|
13
13
|
Money.locale_backend = nil
|
14
14
|
Money.rounding_mode = BigDecimal::ROUND_HALF_UP
|
15
|
+
Money.default_currency = 'USD'
|
15
16
|
|
16
17
|
require_relative 'hledger_forecast/calculator'
|
17
18
|
require_relative 'hledger_forecast/cli'
|
19
|
+
require_relative 'hledger_forecast/comparator'
|
18
20
|
require_relative 'hledger_forecast/csv_parser'
|
19
21
|
require_relative 'hledger_forecast/formatter'
|
20
22
|
require_relative 'hledger_forecast/generator'
|
@@ -12,6 +12,19 @@ output = <<~JOURNAL
|
|
12
12
|
|
13
13
|
JOURNAL
|
14
14
|
|
15
|
+
def strip_ansi_codes(str)
|
16
|
+
str.gsub(/\e\[([;\d]+)?m/, "")
|
17
|
+
end
|
18
|
+
|
19
|
+
def capture_stdout
|
20
|
+
old_stdout = $stdout
|
21
|
+
$stdout = StringIO.new
|
22
|
+
yield
|
23
|
+
$stdout.string
|
24
|
+
ensure
|
25
|
+
$stdout = old_stdout
|
26
|
+
end
|
27
|
+
|
15
28
|
RSpec.describe 'command' do
|
16
29
|
it 'uses the CLI to generate an output' do
|
17
30
|
generated_journal = './test_output.journal'
|
@@ -30,4 +43,19 @@ RSpec.describe 'command' do
|
|
30
43
|
|
31
44
|
expect(File.read(generated_journal)).to eq(output)
|
32
45
|
end
|
46
|
+
|
47
|
+
it 'uses the CLI to compare two CSV files' do
|
48
|
+
expected_output = strip_ansi_codes(<<~OUTPUT)
|
49
|
+
+---------+---------+---------+
|
50
|
+
| account | 2023-07 | 2023-08 |
|
51
|
+
+---------+---------+---------+
|
52
|
+
| total | £10.00 | €-10.00 |
|
53
|
+
+---------+---------+---------+
|
54
|
+
|
55
|
+
OUTPUT
|
56
|
+
|
57
|
+
actual_output = `./bin/hledger-forecast compare ./spec/stubs/output1.csv ./spec/stubs/output2.csv`
|
58
|
+
|
59
|
+
expect(strip_ansi_codes(actual_output)).to eq(expected_output)
|
60
|
+
end
|
33
61
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require_relative '../lib/hledger_forecast'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
def strip_ansi_codes(str)
|
5
|
+
str.gsub(/\e\[([;\d]+)?m/, "")
|
6
|
+
end
|
7
|
+
|
8
|
+
def capture_stdout
|
9
|
+
old_stdout = $stdout
|
10
|
+
$stdout = StringIO.new
|
11
|
+
yield
|
12
|
+
$stdout.string
|
13
|
+
ensure
|
14
|
+
$stdout = old_stdout
|
15
|
+
end
|
16
|
+
|
17
|
+
RSpec.describe HledgerForecast::Comparator do
|
18
|
+
let(:file1_content) do
|
19
|
+
<<~CSV
|
20
|
+
"account","2023-07","2023-08","2023-09"
|
21
|
+
"total","£100.00","€200.00",0
|
22
|
+
CSV
|
23
|
+
end
|
24
|
+
|
25
|
+
let(:file2_content) do
|
26
|
+
<<~CSV
|
27
|
+
"account","2023-07","2023-08","2023-09"
|
28
|
+
"total","£110.00","-€200.00",£1144.00
|
29
|
+
CSV
|
30
|
+
end
|
31
|
+
|
32
|
+
let(:file1) { StringIO.new(file1_content) }
|
33
|
+
let(:file2) { StringIO.new(file2_content) }
|
34
|
+
|
35
|
+
before do
|
36
|
+
allow(CSV).to receive(:read).with('file1.csv').and_return(CSV.parse(file1.read))
|
37
|
+
allow(CSV).to receive(:read).with('file2.csv').and_return(CSV.parse(file2.read))
|
38
|
+
end
|
39
|
+
|
40
|
+
it "compares the contents of two CSV files and outputs the difference" do
|
41
|
+
comparator = described_class.new
|
42
|
+
|
43
|
+
expected_output = strip_ansi_codes(<<~OUTPUT)
|
44
|
+
+---------+---------+----------+---------+
|
45
|
+
| account | 2023-07 | 2023-08 | 2023-09 |
|
46
|
+
+---------+---------+----------+---------+
|
47
|
+
| total | £10.00 | €-400.00 | 1144.00 |
|
48
|
+
+---------+---------+----------+---------+
|
49
|
+
OUTPUT
|
50
|
+
|
51
|
+
actual_output = capture_stdout { comparator.compare('file1.csv', 'file2.csv') }
|
52
|
+
expect(strip_ansi_codes(actual_output)).to eq(expected_output)
|
53
|
+
end
|
54
|
+
end
|
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: 1.
|
4
|
+
version: 1.5.1
|
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-
|
11
|
+
date: 2023-09-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
@@ -94,8 +94,7 @@ dependencies:
|
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '3.12'
|
97
|
-
description:
|
98
|
-
default functionality in hledger
|
97
|
+
description: Use a CSV or YAML file for improved forecasting with hledger
|
99
98
|
email: olimorris@users.noreply.github.com
|
100
99
|
executables:
|
101
100
|
- hledger-forecast
|
@@ -116,6 +115,7 @@ files:
|
|
116
115
|
- lib/hledger_forecast.rb
|
117
116
|
- lib/hledger_forecast/calculator.rb
|
118
117
|
- lib/hledger_forecast/cli.rb
|
118
|
+
- lib/hledger_forecast/comparator.rb
|
119
119
|
- lib/hledger_forecast/csv_parser.rb
|
120
120
|
- lib/hledger_forecast/formatter.rb
|
121
121
|
- lib/hledger_forecast/generator.rb
|
@@ -126,7 +126,8 @@ files:
|
|
126
126
|
- lib/hledger_forecast/transactions/modifiers.rb
|
127
127
|
- lib/hledger_forecast/transactions/trackers.rb
|
128
128
|
- lib/hledger_forecast/version.rb
|
129
|
-
- spec/
|
129
|
+
- spec/cli_spec.rb
|
130
|
+
- spec/compare_spec.rb
|
130
131
|
- spec/computed_amounts_spec.rb
|
131
132
|
- spec/csv_and_yml_comparison_spec.rb
|
132
133
|
- spec/csv_parser_spec.rb
|
@@ -140,6 +141,8 @@ files:
|
|
140
141
|
- spec/quarterly_spec.rb
|
141
142
|
- spec/stubs/forecast.csv
|
142
143
|
- spec/stubs/forecast.yml
|
144
|
+
- spec/stubs/output1.csv
|
145
|
+
- spec/stubs/output2.csv
|
143
146
|
- spec/stubs/transactions_found.journal
|
144
147
|
- spec/stubs/transactions_found_inverse.journal
|
145
148
|
- spec/stubs/transactions_not_found.journal
|
@@ -166,12 +169,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
166
169
|
- !ruby/object:Gem::Version
|
167
170
|
version: '0'
|
168
171
|
requirements: []
|
169
|
-
rubygems_version: 3.4.
|
172
|
+
rubygems_version: 3.4.19
|
170
173
|
signing_key:
|
171
174
|
specification_version: 4
|
172
175
|
summary: An extended wrapper around hledger's forecasting functionality
|
173
176
|
test_files:
|
174
|
-
- spec/
|
177
|
+
- spec/cli_spec.rb
|
178
|
+
- spec/compare_spec.rb
|
175
179
|
- spec/computed_amounts_spec.rb
|
176
180
|
- spec/csv_and_yml_comparison_spec.rb
|
177
181
|
- spec/csv_parser_spec.rb
|
@@ -185,6 +189,8 @@ test_files:
|
|
185
189
|
- spec/quarterly_spec.rb
|
186
190
|
- spec/stubs/forecast.csv
|
187
191
|
- spec/stubs/forecast.yml
|
192
|
+
- spec/stubs/output1.csv
|
193
|
+
- spec/stubs/output2.csv
|
188
194
|
- spec/stubs/transactions_found.journal
|
189
195
|
- spec/stubs/transactions_found_inverse.journal
|
190
196
|
- spec/stubs/transactions_not_found.journal
|