hledger-forecast 0.1.4 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6d7bd2190c7f86b3d6a1fe76583a8f7e959f4429719b9903de343d25e0bf3b51
4
- data.tar.gz: 7bb59da35fc2f9f3c47b6ed8b45d2ef38fb9c5c084c6bce9d6ee66fd004157a8
3
+ metadata.gz: 60e8bd939c2bb57d5d1fdf01d39d4fd7bc1cd59886a189b8b0d8a8fe7a7b6640
4
+ data.tar.gz: e752946a04d49b531ca303a8832d11a686d610392ce29d5a7d96c5aae2658dee
5
5
  SHA512:
6
- metadata.gz: 3251f466cd2072685cf063268aca5c9ddc6231e9ac5c217049369c3e6b1c1d729967059441d4318247b7477ebaf357dc317e4f40df6b8e44dbe59a14b5005b9a
7
- data.tar.gz: 55251b35a8cfea885fbbcb861ad650635a0fed4c91e618942ddd4eb76c38b9d3826d1b35e9078c1fae9c2ea96aa311cef750cc37fd88d5e4aed75ecb5c6db21f
6
+ metadata.gz: a7b44e5ceebc727be1a578a1210741fc5bbb9ec5e6d5a13feb36012bd35fb253173594ef0a35fb8448e1da697575ecdc97797473f7d5751db032a5065cce2bf8
7
+ data.tar.gz: c341817f928c9120662319a6ef9c1434d22b8872e685283b162ad4043efd9a0d1366eeeed4a58196e54708689833fa24af1b6b9e92dc59b8a75a98ad77810390
data/Gemfile CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
+ gem 'colorize'
5
6
  gem 'money'
6
7
 
7
8
  gemspec
data/README.md CHANGED
@@ -37,6 +37,7 @@ Running `hledger-forecast -h` shows the available options:
37
37
  -s, --start-date DATE The date to start generating from (yyyy-mm-dd)
38
38
  -e, --end-date DATE The date to start generating to (yyyy-mm-dd)
39
39
  --force Force an overwrite of the output file
40
+ --summarize Summarize the forecast file and output to the terminal
40
41
  -h, --help Show this message
41
42
  --version Show version
42
43
 
@@ -73,16 +74,17 @@ Let's examine what's going on in this config file:
73
74
 
74
75
  - Firstly, we're telling the app to create two monthly transactions and repeat them, forever, starting from March 2023. In this case, forever will be the `end_date` specified when running the app
75
76
  - If you ran the app with `hledger-forecast -s 2023-04-01` then no transactions would be generated for March as the start date is greater than the periodic start date
76
- - Notice we're also using [virtual postings](https://hledger.org/1.29/hledger.html#virtual-postings) (designated by the brackets) to be explicit to Hledger. This also makes it easy to filter them out with the `-R` or `--real` option in Hledger
77
+ - 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
77
78
  - We also have not specified a currency; the default (`USD`) will be used
78
79
 
79
80
  ### Extending the config file
80
81
 
81
82
  #### Periods
82
83
 
83
- If you'd like to add quarterly, yearly or one-off transactions, use the following keys:
84
+ If you'd like to add quarterly, half-yearly, yearly or one-off transactions, use the following keys:
84
85
 
85
86
  - `quarterly`
87
+ - `half-yearly`
86
88
  - `yearly`
87
89
  - `once`
88
90
 
@@ -112,6 +114,14 @@ settings:
112
114
  thousands_separator: true # Separate thousands with a comma?
113
115
  ```
114
116
 
117
+ ### Summarizing the config file
118
+
119
+ 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:
120
+
121
+ hledger-forecast -f forecast.yml --summarize
122
+
123
+ where `forecast.yml` is the config file to sum up.
124
+
115
125
  ## :brain: Rationale
116
126
 
117
127
  Firstly, I've come to realise from reading countless blog and Reddit posts on [plain text accounting](https://plaintextaccounting.org), that everyone does it __completely__ differently!
data/bin/hledger-forecast CHANGED
@@ -9,4 +9,4 @@ rescue RuntimeError => e
9
9
  exit(1)
10
10
  end
11
11
 
12
- HledgerForecast::Command.run(options)
12
+ HledgerForecast::CLI.run(options)
data/example.yml CHANGED
@@ -17,6 +17,14 @@ quarterly:
17
17
  category: "[Income:Bonus]"
18
18
  description: Bonus
19
19
 
20
+ half-yearly:
21
+ - account: "[Assets:Bank]"
22
+ date: "2023-04-01"
23
+ transactions:
24
+ - amount: 500
25
+ category: "[Expenses:Holiday]"
26
+ description: Holiday
27
+
20
28
  yearly:
21
29
  - account: "[Assets:Bank]"
22
30
  date: "2023-04-01"
@@ -35,6 +43,6 @@ once:
35
43
 
36
44
  settings:
37
45
  currency: GBP
38
- show_symbol: false
46
+ show_symbol: true
39
47
  sign_before_symbol: true
40
- thousands_separator: false
48
+ thousands_separator: true
@@ -14,6 +14,7 @@ Gem::Specification.new do |s|
14
14
 
15
15
  s.add_dependency "highline", "~> 2.1.0"
16
16
  s.add_dependency "money", "~> 6.16.0"
17
+ s.add_dependency "colorize", "~> 0.8.1"
17
18
  s.add_development_dependency 'rspec', '~> 3.12'
18
19
 
19
20
  s.files = `git ls-files`.split("\n")
@@ -1,11 +1,13 @@
1
1
  module HledgerForecast
2
- class Command
2
+ class CLI
3
3
  def self.run(args)
4
4
  end_date = args[:end_date]
5
5
  start_date = args[:start_date]
6
6
  forecast = File.read(args[:forecast_file])
7
7
  transactions = args[:transactions_file] ? File.read(args[:transactions_file]) : nil
8
8
 
9
+ return HledgerForecast::Summarize.generate(forecast) if args[:summarize]
10
+
9
11
  puts "[Using default dates: #{start_date} to #{end_date}]" if args[:default_dates]
10
12
 
11
13
  transactions = Generator.create_journal_entries(transactions, forecast, start_date, end_date)
@@ -29,7 +29,7 @@ module HledgerForecast
29
29
  Money.from_cents(formatted_transaction['amount'].to_i * 100, @settings[:currency]).format(
30
30
  symbol: @settings[:show_symbol],
31
31
  sign_before_symbol: @settings[:sign_before_symbol],
32
- thousands_separator: @settings[:thousands_separator] ? ',' : nil
32
+ thousands_separator: @settings[:thousands_separator] ? ',' : nil,
33
33
  )
34
34
 
35
35
  formatted_transaction
@@ -48,6 +48,8 @@ module HledgerForecast
48
48
  date.day == start_date.day
49
49
  when 'quarterly'
50
50
  date.day == start_date.day && date.month % 3 == start_date.month % 3
51
+ when 'half-yearly'
52
+ date.day == start_date.day && (date.month - start_date.month) % 6 == 0
51
53
  when 'yearly'
52
54
  date.day == start_date.day && date.month == start_date.month
53
55
  when 'once'
@@ -81,6 +83,7 @@ module HledgerForecast
81
83
  while date <= end_date
82
84
  process_forecast(output, forecast_data, 'monthly', date)
83
85
  process_forecast(output, forecast_data, 'quarterly', date)
86
+ process_forecast(output, forecast_data, 'half-yearly', date)
84
87
  process_forecast(output, forecast_data, 'yearly', date)
85
88
  process_forecast(output, forecast_data, 'once', date)
86
89
 
@@ -32,6 +32,11 @@ module HledgerForecast
32
32
  options[:end_date] = a
33
33
  end
34
34
 
35
+ opts.on("--summarize",
36
+ "Summarize the forecast file and output to the terminal") do |a|
37
+ options[:summarize] = a
38
+ end
39
+
35
40
  opts.on("--force",
36
41
  "Force an overwrite of the output file") do |a|
37
42
  options[:force] = a
@@ -0,0 +1,68 @@
1
+ module HledgerForecast
2
+ # Summarise a forecast YAML file and output it to the CLI
3
+ class Summarize
4
+ def self.sum_transactions(forecast_data, period)
5
+ category_totals = Hash.new(0)
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
+ category_totals
12
+ end
13
+
14
+ def self.print_category_totals(period, category_totals, generator)
15
+ puts "#{period.capitalize}:"
16
+ period_total = 0
17
+
18
+ category_totals.each do |category, amount|
19
+ formatted_amount = generator.format_transaction({ 'amount' => amount })['amount']
20
+ formatted_amount = amount.to_i < 0 ? formatted_amount.red : formatted_amount.green
21
+ puts " #{category.ljust(40)}#{formatted_amount}"
22
+ period_total += amount
23
+ end
24
+
25
+ formatted_period_total = generator.format_transaction({ 'amount' => period_total })['amount']
26
+ formatted_period_total = period_total.to_i < 0 ? formatted_period_total.red : formatted_period_total.green
27
+ puts " TOTAL".ljust(42) + formatted_period_total
28
+ end
29
+
30
+ def self.sum_all_periods(forecast_data)
31
+ periods = %w[monthly quarterly half-yearly yearly once]
32
+ total = {}
33
+ grand_total = 0
34
+
35
+ periods.each do |period|
36
+ total[period] = sum_transactions(forecast_data, period)
37
+ grand_total += total[period]
38
+ end
39
+
40
+ total['total'] = grand_total
41
+ total
42
+ end
43
+
44
+ def self.generate(forecast)
45
+ forecast_data = YAML.safe_load(forecast)
46
+
47
+ category_totals_by_period = {}
48
+ %w[monthly quarterly half-yearly yearly once].each do |period|
49
+ category_totals_by_period[period] = sum_transactions(forecast_data, period)
50
+ end
51
+
52
+ grand_total = category_totals_by_period.values.map(&:values).flatten.sum
53
+
54
+ generator = HledgerForecast::Generator
55
+ generator.configure_settings(forecast_data)
56
+
57
+ puts
58
+ category_totals_by_period.each do |period, category_totals|
59
+ print_category_totals(period, category_totals, generator)
60
+ puts
61
+ end
62
+
63
+ formatted_grand_total = generator.format_transaction({ 'amount' => grand_total })['amount']
64
+ formatted_grand_total = grand_total.to_i < 0 ? formatted_grand_total.red : formatted_grand_total.green
65
+ puts "TOTAL:".ljust(42) + formatted_grand_total
66
+ end
67
+ end
68
+ end
@@ -1,3 +1,3 @@
1
1
  module HledgerForecast
2
- VERSION = "0.1.4"
2
+ VERSION = "0.1.6"
3
3
  end
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'colorize'
3
4
  require 'date'
4
5
  require 'highline'
5
6
  require 'money'
@@ -12,4 +13,5 @@ Money.rounding_mode = BigDecimal::ROUND_HALF_UP
12
13
  require_relative 'hledger_forecast/version'
13
14
  require_relative 'hledger_forecast/options'
14
15
  require_relative 'hledger_forecast/generator'
15
- require_relative 'hledger_forecast/command'
16
+ require_relative 'hledger_forecast/summarize'
17
+ require_relative 'hledger_forecast/CLI'
@@ -0,0 +1,13 @@
1
+ require_relative '../lib/hledger_forecast'
2
+
3
+ RSpec.describe 'generate' do
4
+ it 'generates a forecast with correct HALF-YEARLY transactions' do
5
+ transactions = File.read('spec/stubs/transactions.journal')
6
+ forecast = File.read('spec/stubs/half-yearly/forecast_half-yearly.yml')
7
+
8
+ generated_journal = HledgerForecast::Generator.create_journal_entries(transactions, forecast, '2023-03-01', '2024-04-30')
9
+
10
+ expected_output = File.read('spec/stubs/half-yearly/output_half-yearly.journal')
11
+ expect(generated_journal).to eq(expected_output)
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ settings:
2
+ currency: GBP
3
+
4
+ half-yearly:
5
+ - start: "2023-04-01"
6
+ account: "[Assets:Bank]"
7
+ transactions:
8
+ - description: Holiday
9
+ category: "[Expenses:Holiday]"
10
+ amount: 500
@@ -0,0 +1,20 @@
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-04-01 * Holiday
10
+ [Expenses:Holiday] £500.00
11
+ [Assets:Bank]
12
+
13
+ 2023-10-01 * Holiday
14
+ [Expenses:Holiday] £500.00
15
+ [Assets:Bank]
16
+
17
+ 2024-04-01 * Holiday
18
+ [Expenses:Holiday] £500.00
19
+ [Assets:Bank]
20
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hledger-forecast
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oli Morris
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 6.16.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: colorize
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.8.1
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.8.1
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rspec
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -70,14 +84,18 @@ files:
70
84
  - example.yml
71
85
  - hledger-forecast.gemspec
72
86
  - lib/hledger_forecast.rb
73
- - lib/hledger_forecast/command.rb
87
+ - lib/hledger_forecast/cli.rb
74
88
  - lib/hledger_forecast/generator.rb
75
89
  - lib/hledger_forecast/options.rb
90
+ - lib/hledger_forecast/summarize.rb
76
91
  - lib/hledger_forecast/version.rb
77
92
  - spec/command_spec.rb
93
+ - spec/half-yearly_spec.rb
78
94
  - spec/monthly_spec.rb
79
95
  - spec/once_spec.rb
80
96
  - spec/quarterly_spec.rb
97
+ - spec/stubs/half-yearly/forecast_half-yearly.yml
98
+ - spec/stubs/half-yearly/output_half-yearly.journal
81
99
  - spec/stubs/monthly/forecast_monthly.yml
82
100
  - spec/stubs/monthly/forecast_monthly_enddate.yml
83
101
  - spec/stubs/monthly/forecast_monthly_enddate_top.yml
@@ -119,9 +137,12 @@ specification_version: 4
119
137
  summary: Utility to generate forecasts in Hledger
120
138
  test_files:
121
139
  - spec/command_spec.rb
140
+ - spec/half-yearly_spec.rb
122
141
  - spec/monthly_spec.rb
123
142
  - spec/once_spec.rb
124
143
  - spec/quarterly_spec.rb
144
+ - spec/stubs/half-yearly/forecast_half-yearly.yml
145
+ - spec/stubs/half-yearly/output_half-yearly.journal
125
146
  - spec/stubs/monthly/forecast_monthly.yml
126
147
  - spec/stubs/monthly/forecast_monthly_enddate.yml
127
148
  - spec/stubs/monthly/forecast_monthly_enddate_top.yml