hledger-forecast 1.4.0 → 1.5.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 +25 -15
- data/lib/hledger_forecast/cli.rb +79 -8
- data/lib/hledger_forecast/comparator.rb +80 -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 +12 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0f769e017bc9ad46ea7d7571f74c64286e9c2415d0696e40f3301438a9038514
|
4
|
+
data.tar.gz: 52f69b30edfbc0c9d5430b88d25687c9c311d6c6aa4b1e5fd3b2815b3602d240
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2721eb985469db575b66172a94ee670e96711437da7b94f27da53301beed9f385b46c19121c9d365ce01fb0423ea5ea728ce511296c29adc26fc2051ff33e794
|
7
|
+
data.tar.gz: e41363954be45ca668dd73cc1a816b47a94419be53cde4fccdfc5a88a55601a2166e5f6eeb6532d4673c3bfe204020122165b71fabcca07a9dbf7cf0f1f80271
|
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/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,80 @@
|
|
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(cell) - parse_money(csv2[i][j])
|
47
|
+
format_difference(difference, detect_currency(cell))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def detect_currency(str)
|
54
|
+
# Explicitly check for common currencies first
|
55
|
+
return "GBP" if str.include?("£")
|
56
|
+
return "EUR" if str.include?("€")
|
57
|
+
return "USD" if str.include?("$")
|
58
|
+
|
59
|
+
Money::Currency.table.each_value do |currency|
|
60
|
+
return currency[:iso_code] if str.include?(currency[:symbol])
|
61
|
+
end
|
62
|
+
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
|
66
|
+
def parse_money(value)
|
67
|
+
# Remove currency symbols and parse the result as a float, then convert to cents
|
68
|
+
cleaned_value = value.gsub(/[^0-9.]/, '').to_f
|
69
|
+
cleaned_value.to_i
|
70
|
+
end
|
71
|
+
|
72
|
+
def format_difference(amount, currency)
|
73
|
+
formatted_amount = Formatter.format_money(amount, { currency: currency })
|
74
|
+
|
75
|
+
return formatted_amount if amount == 0
|
76
|
+
|
77
|
+
amount > 0 ? formatted_amount.green : formatted_amount.red
|
78
|
+
end
|
79
|
+
end
|
80
|
+
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"
|
21
|
+
"total","£100.00","€200.00"
|
22
|
+
CSV
|
23
|
+
end
|
24
|
+
|
25
|
+
let(:file2_content) do
|
26
|
+
<<~CSV
|
27
|
+
"account","2023-07","2023-08"
|
28
|
+
"total","£110.00","€190.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 |
|
46
|
+
+---------+---------+---------+
|
47
|
+
| total | £-10.00 | €10.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.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-
|
11
|
+
date: 2023-08-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
@@ -116,6 +116,7 @@ files:
|
|
116
116
|
- lib/hledger_forecast.rb
|
117
117
|
- lib/hledger_forecast/calculator.rb
|
118
118
|
- lib/hledger_forecast/cli.rb
|
119
|
+
- lib/hledger_forecast/comparator.rb
|
119
120
|
- lib/hledger_forecast/csv_parser.rb
|
120
121
|
- lib/hledger_forecast/formatter.rb
|
121
122
|
- lib/hledger_forecast/generator.rb
|
@@ -126,7 +127,8 @@ files:
|
|
126
127
|
- lib/hledger_forecast/transactions/modifiers.rb
|
127
128
|
- lib/hledger_forecast/transactions/trackers.rb
|
128
129
|
- lib/hledger_forecast/version.rb
|
129
|
-
- spec/
|
130
|
+
- spec/cli_spec.rb
|
131
|
+
- spec/compare_spec.rb
|
130
132
|
- spec/computed_amounts_spec.rb
|
131
133
|
- spec/csv_and_yml_comparison_spec.rb
|
132
134
|
- spec/csv_parser_spec.rb
|
@@ -140,6 +142,8 @@ files:
|
|
140
142
|
- spec/quarterly_spec.rb
|
141
143
|
- spec/stubs/forecast.csv
|
142
144
|
- spec/stubs/forecast.yml
|
145
|
+
- spec/stubs/output1.csv
|
146
|
+
- spec/stubs/output2.csv
|
143
147
|
- spec/stubs/transactions_found.journal
|
144
148
|
- spec/stubs/transactions_found_inverse.journal
|
145
149
|
- spec/stubs/transactions_not_found.journal
|
@@ -166,12 +170,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
166
170
|
- !ruby/object:Gem::Version
|
167
171
|
version: '0'
|
168
172
|
requirements: []
|
169
|
-
rubygems_version: 3.4.
|
173
|
+
rubygems_version: 3.4.19
|
170
174
|
signing_key:
|
171
175
|
specification_version: 4
|
172
176
|
summary: An extended wrapper around hledger's forecasting functionality
|
173
177
|
test_files:
|
174
|
-
- spec/
|
178
|
+
- spec/cli_spec.rb
|
179
|
+
- spec/compare_spec.rb
|
175
180
|
- spec/computed_amounts_spec.rb
|
176
181
|
- spec/csv_and_yml_comparison_spec.rb
|
177
182
|
- spec/csv_parser_spec.rb
|
@@ -185,6 +190,8 @@ test_files:
|
|
185
190
|
- spec/quarterly_spec.rb
|
186
191
|
- spec/stubs/forecast.csv
|
187
192
|
- spec/stubs/forecast.yml
|
193
|
+
- spec/stubs/output1.csv
|
194
|
+
- spec/stubs/output2.csv
|
188
195
|
- spec/stubs/transactions_found.journal
|
189
196
|
- spec/stubs/transactions_found_inverse.journal
|
190
197
|
- spec/stubs/transactions_not_found.journal
|