bouch 1.1.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 +7 -0
- data/.gitignore +50 -0
- data/.gitlab-ci.yml +11 -0
- data/.rspec +2 -0
- data/.rubocop.yml +102 -0
- data/.simplecov +4 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +62 -0
- data/LICENSE +674 -0
- data/README.md +142 -0
- data/Rakefile +10 -0
- data/bin/bouch +7 -0
- data/bouch.gemspec +33 -0
- data/lib/bouch.rb +89 -0
- data/lib/bouch/calc.rb +65 -0
- data/lib/bouch/cli.rb +32 -0
- data/lib/bouch/version.rb +5 -0
- data/pouch.example.yml +36 -0
- data/spec/bouch_calc_spec.rb +132 -0
- data/spec/bouch_cli_spec.rb +48 -0
- data/spec/bouch_pouch_yaml_spec.rb +46 -0
- data/spec/bouch_spec.rb +86 -0
- data/spec/bouch_version_spec.rb +9 -0
- data/spec/spec_helper.rb +81 -0
- metadata +146 -0
data/README.md
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Bouch
|
|
2
|
+
[](https://gitlab.com/ssofos/bouch/commits/master) [](https://gitlab.com/ssofos/bouch/commits/master)
|
|
3
|
+
|
|
4
|
+
`Bouch` is the budget pouch. A simple tool to calculate and project your annual personal budget based on fiscal quarter expenditures, income, assets, and debts.
|
|
5
|
+
|
|
6
|
+
Use it to help establish an annual financial plan, set monetary goals, and gain perspective on your financial health.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
To install bouch via RubyGems simple execute this command from a command-line interface:
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
gem install bouch
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
To use bouch as part of your Ruby Project add this line to your Gemfile:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
gem 'bouch'
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
Bouch takes a simple YAML file as its primary data input. This will be referred to as a budget pouch file.
|
|
25
|
+
|
|
26
|
+
There is an example budget pouch file called **pouch.example.yml**.
|
|
27
|
+
|
|
28
|
+
Use this budget pouch file and execute the following command on your favorite terminal emulator's CLI:
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
bouch pouch.example.yml
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
You should see the example budget summary output:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
----------------------
|
|
38
|
+
Quarter 1: 3025.00
|
|
39
|
+
Quarter 2: 3025.00
|
|
40
|
+
Quarter 3: 3025.00
|
|
41
|
+
Quarter 4: 3025.00
|
|
42
|
+
----------------------
|
|
43
|
+
Budget Annual Total: 12100.00
|
|
44
|
+
Budget Annual Income: 28808.00
|
|
45
|
+
Budget Income Percent: 42.00%
|
|
46
|
+
----------------------
|
|
47
|
+
Assets Total: 1000.00
|
|
48
|
+
----------------------
|
|
49
|
+
Debt Total: 420.00
|
|
50
|
+
Debt Ratio: 0.4200
|
|
51
|
+
Debt Ratio Percent: 42.00%
|
|
52
|
+
----------------------
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Pouch Schema
|
|
56
|
+
|
|
57
|
+
To use bouch to calculate your own budget you must create a customized budget pouch file.
|
|
58
|
+
|
|
59
|
+
Budget pouch files are written in Ruby friendly YAML and currently use the following schema:
|
|
60
|
+
|
|
61
|
+
* Deeply nested mappings, also know as hashes
|
|
62
|
+
* Think of hashes as simple groupings of keys and values
|
|
63
|
+
* Primary hash keys:
|
|
64
|
+
* **Budget**
|
|
65
|
+
* **Salary**
|
|
66
|
+
* **Assets**
|
|
67
|
+
* **Debts**
|
|
68
|
+
* **Budget** nested keys and values:
|
|
69
|
+
* **Q1**
|
|
70
|
+
* foo
|
|
71
|
+
* Value: Integer or Float
|
|
72
|
+
* Equals a budget item's quarterly cost
|
|
73
|
+
* bar
|
|
74
|
+
* **cost**
|
|
75
|
+
* Value: Integer or Float
|
|
76
|
+
* Equals the monthly cost of any repeated payment
|
|
77
|
+
* **repeat**
|
|
78
|
+
* Value: true
|
|
79
|
+
* Enables quarterly auto-calculation of the repeat payment
|
|
80
|
+
* **Q2**
|
|
81
|
+
* Same nested schema as Q1
|
|
82
|
+
* **Q3**
|
|
83
|
+
* Same nested schema as Q1
|
|
84
|
+
* **Q4**
|
|
85
|
+
* Same nested schema as Q1
|
|
86
|
+
* **Salary** nested keys and values:
|
|
87
|
+
* **quantity**
|
|
88
|
+
* Value: Float or Integer
|
|
89
|
+
* Equals amount of after-tax money per salary pay period
|
|
90
|
+
* **frequency**
|
|
91
|
+
* Value: Integer
|
|
92
|
+
* Equals number of weeks for each salary pay period
|
|
93
|
+
* **Assets** nested keys and values:
|
|
94
|
+
* foo
|
|
95
|
+
* Value: Integer or Float
|
|
96
|
+
* Equals an asset's total valued amount
|
|
97
|
+
* **Debts** nested keys and values:
|
|
98
|
+
* bar
|
|
99
|
+
* Value: Integer or Float
|
|
100
|
+
* Equals a debt's total valued amount
|
|
101
|
+
* All non-primary nested keys are case insensitive
|
|
102
|
+
|
|
103
|
+
Here is an simple example of of budget pouch file:
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
---
|
|
107
|
+
Budget:
|
|
108
|
+
Q1:
|
|
109
|
+
Rent:
|
|
110
|
+
cost: 1000
|
|
111
|
+
repeat: true
|
|
112
|
+
foo: 20
|
|
113
|
+
bar: 5
|
|
114
|
+
Q2:
|
|
115
|
+
Rent:
|
|
116
|
+
cost: 1000
|
|
117
|
+
repeat: true
|
|
118
|
+
fizz: 20
|
|
119
|
+
buzz: 5
|
|
120
|
+
Q3:
|
|
121
|
+
Rent:
|
|
122
|
+
cost: 1000
|
|
123
|
+
repeat: true
|
|
124
|
+
bubble: 20
|
|
125
|
+
sort: 5
|
|
126
|
+
Q4:
|
|
127
|
+
Rent:
|
|
128
|
+
cost: 1000
|
|
129
|
+
repeat: true
|
|
130
|
+
baz: 20
|
|
131
|
+
qax: 5
|
|
132
|
+
Salary:
|
|
133
|
+
quantity: 1108.00
|
|
134
|
+
frequency: 2
|
|
135
|
+
Assets:
|
|
136
|
+
foo: 500
|
|
137
|
+
bar: 500
|
|
138
|
+
Debts:
|
|
139
|
+
baz: 120
|
|
140
|
+
qax: 300
|
|
141
|
+
...
|
|
142
|
+
```
|
data/Rakefile
ADDED
data/bin/bouch
ADDED
data/bouch.gemspec
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
$LOAD_PATH.unshift File.expand_path('lib', __dir__)
|
|
4
|
+
require 'bouch/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |s|
|
|
7
|
+
s.name = 'bouch'
|
|
8
|
+
s.date = '2018-06-09'
|
|
9
|
+
s.version = Bouch::VERSION
|
|
10
|
+
s.authors = ['Shane R. Sofos']
|
|
11
|
+
s.email = ['ssofos@gmail.com']
|
|
12
|
+
s.homepage = 'https://gitlab.com/ssofos/bouch'
|
|
13
|
+
s.license = 'GPL-3.0'
|
|
14
|
+
s.description = 'The Budget Pouch. Fast annual budget projections.'
|
|
15
|
+
s.summary =
|
|
16
|
+
'A simple tool to calculate and project your ' +
|
|
17
|
+
'annual personal budget based on fiscal quarters ' +
|
|
18
|
+
'expenditures, income, assets, and debts.'
|
|
19
|
+
|
|
20
|
+
s.files = %x(git ls-files).split($INPUT_RECORD_SEPARATOR)
|
|
21
|
+
s.bindir = ['bin']
|
|
22
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
23
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
|
24
|
+
s.require_paths = ['lib']
|
|
25
|
+
|
|
26
|
+
s.add_development_dependency 'bundler'
|
|
27
|
+
s.add_development_dependency 'rake'
|
|
28
|
+
s.add_development_dependency 'rspec'
|
|
29
|
+
s.add_development_dependency 'rubocop', '<=0.56.0'
|
|
30
|
+
s.add_development_dependency 'simplecov'
|
|
31
|
+
|
|
32
|
+
s.required_ruby_version = '>= 2.4.0'
|
|
33
|
+
end
|
data/lib/bouch.rb
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'yaml'
|
|
4
|
+
require 'bouch/calc'
|
|
5
|
+
|
|
6
|
+
# Calculate and create simple financial budgets
|
|
7
|
+
# by parsing a single YAML file as input
|
|
8
|
+
class Bouch
|
|
9
|
+
attr_accessor :assets, :debts, :pouch, :quarters
|
|
10
|
+
include BouchCalculate
|
|
11
|
+
|
|
12
|
+
def initialize(file)
|
|
13
|
+
@assets = Array.new
|
|
14
|
+
@debts = Array.new
|
|
15
|
+
@pouch = YAML.safe_load(IO.read(file))
|
|
16
|
+
@quarters = Hash.new
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Summarize and show aggregate asset totals
|
|
20
|
+
def show_assets_total
|
|
21
|
+
calc_assets(@pouch['Assets']) if @assets.empty?
|
|
22
|
+
puts '----------------------'
|
|
23
|
+
puts format('%-30s %.2f', 'Assets Total:', @assets.sum)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Summarize and show aggregate liabilities totals
|
|
27
|
+
def show_debts_total
|
|
28
|
+
calc_debts(@pouch['Debts']) if @debts.empty?
|
|
29
|
+
puts '----------------------'
|
|
30
|
+
puts format('%-30s %.2f', 'Debt Total:', @debts.sum)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Summarize and show debt ratio
|
|
34
|
+
def show_debt_ratio
|
|
35
|
+
calc_assets(@pouch['Assets']) if @assets.empty?
|
|
36
|
+
calc_debts(@pouch['Debts']) if @debts.empty?
|
|
37
|
+
puts format('%-30s %.4f', 'Debt Ratio:', calc_debt_ratio(@debts.sum, @assets.sum))
|
|
38
|
+
puts format('%-30s %.2f%s', 'Debt Ratio Percent:',
|
|
39
|
+
calc_debt_ratio_percent(calc_debt_ratio(@debts.sum, @assets.sum)),
|
|
40
|
+
'%')
|
|
41
|
+
puts '----------------------'
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Summarize and show all financial quarter budgets
|
|
45
|
+
def show_quarters
|
|
46
|
+
calc_quarters_raw(@pouch['Budget']) if @quarters.empty?
|
|
47
|
+
puts '----------------------'
|
|
48
|
+
4.times do |n|
|
|
49
|
+
puts format('%-30s %.2f', 'Quarter ' + (n + 1).to_s + ':', @quarters[n.to_s].sum)
|
|
50
|
+
end
|
|
51
|
+
puts '----------------------'
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Summarize and show the aggregate annual budget totals
|
|
55
|
+
def show_annual_total
|
|
56
|
+
calc_quarters_raw(@pouch['Budget']) if @quarters.empty?
|
|
57
|
+
puts format('%-30s %.2f', 'Budget Annual Total:', calc_quarters_raw_total.to_s)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Summarize and show the aggregate annual budget as a percentage of income
|
|
61
|
+
def show_budget_percentage
|
|
62
|
+
calc_quarters_raw(@pouch['Budget']) if @quarters.empty?
|
|
63
|
+
puts format('%-30s %.2f%s',
|
|
64
|
+
'Budget Income Percent:',
|
|
65
|
+
calc_budget_percentage(
|
|
66
|
+
calc_quarters_raw_total,
|
|
67
|
+
calc_salary(@pouch['Salary']['quantity'], @pouch['Salary']['frequency'])
|
|
68
|
+
),
|
|
69
|
+
'%')
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Summarize and show annual income
|
|
73
|
+
def show_annual_income
|
|
74
|
+
puts format('%-30s %.2f',
|
|
75
|
+
'Budget Annual Income:',
|
|
76
|
+
calc_salary(@pouch['Salary']['quantity'], @pouch['Salary']['frequency']))
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Summarize and show all aggregate components of the quarterly, annual budgets, assets
|
|
80
|
+
def show_budget
|
|
81
|
+
show_quarters
|
|
82
|
+
show_annual_total
|
|
83
|
+
show_annual_income
|
|
84
|
+
show_budget_percentage
|
|
85
|
+
show_assets_total
|
|
86
|
+
show_debts_total
|
|
87
|
+
show_debt_ratio
|
|
88
|
+
end
|
|
89
|
+
end
|
data/lib/bouch/calc.rb
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Financial budget calculation and operations for Bouch
|
|
4
|
+
module BouchCalculate
|
|
5
|
+
# Calculate asset value aggregate amount
|
|
6
|
+
def calc_assets(assets)
|
|
7
|
+
assets.each_value do |value|
|
|
8
|
+
@assets.push(value)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Calculate the percentage of budget of a salary/income
|
|
13
|
+
def calc_budget_percentage(total, salary)
|
|
14
|
+
((total.to_f / salary.to_f) * 100).round(2)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Calculate debt/liability aggregate amount
|
|
18
|
+
def calc_debts(debts)
|
|
19
|
+
debts.each_value do |value|
|
|
20
|
+
@debts.push(value)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Calculate a debt ratio: total debts divided by total assets
|
|
25
|
+
def calc_debt_ratio(debts, assets)
|
|
26
|
+
(debts.to_f / assets.to_f).round(4)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Calculate a debt ratio percentage
|
|
30
|
+
def calc_debt_ratio_percent(debt_ratio)
|
|
31
|
+
(debt_ratio.to_f * 100).round(2)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Calculate a quarterly repeating budget item amount
|
|
35
|
+
def calc_repeating(item)
|
|
36
|
+
(item.to_f * 3).round(2)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Calculate an annual income based on a weekly frequency salary
|
|
40
|
+
def calc_salary(amount, freq)
|
|
41
|
+
(amount.to_f * (52 / freq)).round(2)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Calculate each financial quarters budget items, including repeating ones
|
|
45
|
+
def calc_quarters_raw(budget)
|
|
46
|
+
budget.each_value do |items|
|
|
47
|
+
@quarters[@quarters.length.to_s] = Array.new
|
|
48
|
+
items.each_value do |value|
|
|
49
|
+
case value
|
|
50
|
+
when Hash
|
|
51
|
+
if value.key?('repeat')
|
|
52
|
+
@quarters[(@quarters.length - 1).to_s].push(calc_repeating(value['cost']))
|
|
53
|
+
end
|
|
54
|
+
else
|
|
55
|
+
@quarters[(@quarters.length - 1).to_s].push(value)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Calculate all financial quarter budget into an aggregate annual budget
|
|
62
|
+
def calc_quarters_raw_total
|
|
63
|
+
@quarters['0'].sum + @quarters['1'].sum + @quarters['2'].sum + @quarters['3'].sum
|
|
64
|
+
end
|
|
65
|
+
end
|
data/lib/bouch/cli.rb
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'bouch'
|
|
4
|
+
require 'bouch/version'
|
|
5
|
+
|
|
6
|
+
class Bouch
|
|
7
|
+
# Parse the command line
|
|
8
|
+
class CLI
|
|
9
|
+
attr_accessor :yaml_file
|
|
10
|
+
|
|
11
|
+
def initialize(file)
|
|
12
|
+
@yaml_file = file
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def start
|
|
16
|
+
if @yaml_file.eql?(nil)
|
|
17
|
+
puts 'Please supply budget pouch YAML file path and rerun bouch.'
|
|
18
|
+
usage
|
|
19
|
+
elsif File.exist?(@yaml_file)
|
|
20
|
+
budget = Bouch.new(@yaml_file)
|
|
21
|
+
budget.show_budget
|
|
22
|
+
else
|
|
23
|
+
puts "Whoops. The budget pouch file specified: #{@yaml_file} ; does not exist!"
|
|
24
|
+
usage
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def usage
|
|
29
|
+
puts "<<bouch #{Bouch::VERSION}>>\nUsage: #{File.basename($PROGRAM_NAME)} [YAML_FILE]"
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
data/pouch.example.yml
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
Budget:
|
|
3
|
+
Q1:
|
|
4
|
+
Rent:
|
|
5
|
+
cost: 1000
|
|
6
|
+
repeat: true
|
|
7
|
+
foo: 20
|
|
8
|
+
bar: 5
|
|
9
|
+
Q2:
|
|
10
|
+
Rent:
|
|
11
|
+
cost: 1000
|
|
12
|
+
repeat: true
|
|
13
|
+
fizz: 20
|
|
14
|
+
buzz: 5
|
|
15
|
+
Q3:
|
|
16
|
+
Rent:
|
|
17
|
+
cost: 1000
|
|
18
|
+
repeat: true
|
|
19
|
+
bubble: 20
|
|
20
|
+
sort: 5
|
|
21
|
+
Q4:
|
|
22
|
+
Rent:
|
|
23
|
+
cost: 1000
|
|
24
|
+
repeat: true
|
|
25
|
+
baz: 20
|
|
26
|
+
qax: 5
|
|
27
|
+
Salary:
|
|
28
|
+
quantity: 1108.00
|
|
29
|
+
frequency: 2
|
|
30
|
+
Assets:
|
|
31
|
+
foo: 500
|
|
32
|
+
bar: 500
|
|
33
|
+
Debts:
|
|
34
|
+
baz: 120
|
|
35
|
+
qax: 300
|
|
36
|
+
...
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'yaml'
|
|
4
|
+
require 'bouch'
|
|
5
|
+
require 'bouch/calc'
|
|
6
|
+
|
|
7
|
+
describe BouchCalculate do
|
|
8
|
+
before :all do
|
|
9
|
+
@yaml = File.realdirpath('pouch.example.yml')
|
|
10
|
+
@bouch = Bouch.new(@yaml)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe '.calc_assets' do
|
|
14
|
+
it 'pushes asset values to an Array and returns a Hash' do
|
|
15
|
+
expect(@bouch.calc_assets(@bouch.pouch['Assets'])).to be_a_kind_of(Hash)
|
|
16
|
+
end
|
|
17
|
+
it 'creates array of assets greater than zero' do
|
|
18
|
+
# Uncomment line below for Debug
|
|
19
|
+
# puts @bouch.assets.inspect
|
|
20
|
+
expect(@bouch.assets.length).to be > 0
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
describe '.calc_budget_percentage' do
|
|
25
|
+
context 'given a budget total and salary income total' do
|
|
26
|
+
it 'returns a percentage of budget of a salary income' do
|
|
27
|
+
expect(@bouch.calc_budget_percentage(12100.00, 28808.00)).to eq(42.00)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe '.calc_debts' do
|
|
33
|
+
it 'pushes debt values to an Array and returns a Hash' do
|
|
34
|
+
expect(@bouch.calc_debts(@bouch.pouch['Debts'])).to be_a_kind_of(Hash)
|
|
35
|
+
end
|
|
36
|
+
it 'creates an array of debts greater than zero' do
|
|
37
|
+
# Uncomment line below for Debug
|
|
38
|
+
# puts @bouch.debts.inspect
|
|
39
|
+
expect(@bouch.debts.length).to be > 0
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe '.calc_debt_ratio' do
|
|
44
|
+
context 'given a sum of debts and assets' do
|
|
45
|
+
it 'returns a Float number' do
|
|
46
|
+
expect(@bouch.calc_debt_ratio(420.00, 1000.00)).to be_a_kind_of(Float)
|
|
47
|
+
end
|
|
48
|
+
it 'returns a debt ratio' do
|
|
49
|
+
expect(@bouch.calc_debt_ratio(420.00, 1000.00)).to eq(0.42)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
describe '.calc_debt_ratio_percent' do
|
|
55
|
+
context 'given a debt ratio' do
|
|
56
|
+
it 'returns a Float number' do
|
|
57
|
+
debt_ratio = @bouch.calc_debt_ratio(420.00, 1000.00)
|
|
58
|
+
# Uncomment line below for Debug
|
|
59
|
+
# puts debt_ratio
|
|
60
|
+
expect(@bouch.calc_debt_ratio_percent(debt_ratio)).to be_a_kind_of(Float)
|
|
61
|
+
end
|
|
62
|
+
it 'returns a debt ratio percentage' do
|
|
63
|
+
debt_ratio = @bouch.calc_debt_ratio(420.00, 1000.00)
|
|
64
|
+
# Uncomment line below for Debug
|
|
65
|
+
# puts debt_ratio
|
|
66
|
+
expect(@bouch.calc_debt_ratio_percent(debt_ratio)).to eq(42.00)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
describe '.calc_repeating' do
|
|
72
|
+
context 'given a numerical cost amount' do
|
|
73
|
+
it 'returns a Float number' do
|
|
74
|
+
expect(@bouch.calc_repeating(1000)).to be_a_kind_of(Float)
|
|
75
|
+
end
|
|
76
|
+
it 'returns a number three times that amount' do
|
|
77
|
+
expect(@bouch.calc_repeating(1000)).to eq(3000.00)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
describe '.calc_salary' do
|
|
83
|
+
context 'given a salary amount and weekly frequency' do
|
|
84
|
+
it 'returns a Float number' do
|
|
85
|
+
expect(@bouch.calc_salary(1108.00, 2)).to be_a_kind_of(Float)
|
|
86
|
+
end
|
|
87
|
+
it 'returns an annual income total' do
|
|
88
|
+
expect(@bouch.calc_salary(1108.00, 2)).to eq(28808.00)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
describe '.calc_quarters_raw' do
|
|
94
|
+
context 'given a quarterly budget' do
|
|
95
|
+
it 'pushes quarterly budget items to a collection of Arrays and returns a Hash' do
|
|
96
|
+
expect(@bouch.calc_quarters_raw(@bouch.pouch['Budget'])).to be_a_kind_of(Hash)
|
|
97
|
+
end
|
|
98
|
+
it 'creates an array of financial quarter one budget items greater than zero' do
|
|
99
|
+
# Uncomment line below for Debug
|
|
100
|
+
# puts @bouch.quarters['0'].inspect
|
|
101
|
+
expect(@bouch.quarters['0'].length).to be > 0
|
|
102
|
+
end
|
|
103
|
+
it 'creates an array of financial quarter two budget items greater than zero' do
|
|
104
|
+
# Uncomment line below for Debug
|
|
105
|
+
# puts @bouch.quarters['1'].inspect
|
|
106
|
+
expect(@bouch.quarters['1'].length).to be > 0
|
|
107
|
+
end
|
|
108
|
+
it 'creates an array of financial quarter three budget items greater than zero' do
|
|
109
|
+
# Uncomment line below for Debug
|
|
110
|
+
# puts @bouch.quarters['2'].inspect
|
|
111
|
+
expect(@bouch.quarters['2'].length).to be > 0
|
|
112
|
+
end
|
|
113
|
+
it 'creates an array of financial quarter four budget items greater than zero' do
|
|
114
|
+
# Uncomment line below for Debug
|
|
115
|
+
# puts @bouch.quarters['3'].inspect
|
|
116
|
+
expect(@bouch.quarters['3'].length).to be > 0
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
describe '.calc_quarters_raw_total' do
|
|
122
|
+
context 'given arrays of quarterly budget items' do
|
|
123
|
+
it 'returns a Float number' do
|
|
124
|
+
expect(@bouch.calc_quarters_raw_total).to be_a_kind_of(Float)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it 'returns a financial quarter aggregate sum' do
|
|
128
|
+
expect(@bouch.calc_quarters_raw_total).to eq(12100.00)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|