fin_it 0.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/ARCHITECTURE.md +24 -0
- data/CHANGELOG.md +9 -0
- data/CONTRIBUTING.md +20 -0
- data/LICENSE +21 -0
- data/QUICKSTART.md +56 -0
- data/README.md +74 -0
- data/Rakefile +23 -0
- data/SECURITY.md +14 -0
- data/assets/fin_it_logo.png +0 -0
- data/lib/fin_it/account.rb +120 -0
- data/lib/fin_it/calculator/currency_conversion.rb +27 -0
- data/lib/fin_it/calculator/date_helpers.rb +53 -0
- data/lib/fin_it/calculator/variable_hashing.rb +120 -0
- data/lib/fin_it/calculator.rb +480 -0
- data/lib/fin_it/categories/category.rb +137 -0
- data/lib/fin_it/complex_model.rb +169 -0
- data/lib/fin_it/dsl/account_builder.rb +35 -0
- data/lib/fin_it/dsl/calculated_builder.rb +87 -0
- data/lib/fin_it/dsl/config_builder.rb +58 -0
- data/lib/fin_it/dsl/model_builder.rb +938 -0
- data/lib/fin_it/dsl/model_template_builder.rb +29 -0
- data/lib/fin_it/dsl/plan_builder.rb +52 -0
- data/lib/fin_it/dsl/project_inheritance_resolver.rb +46 -0
- data/lib/fin_it/dsl/variable_builder.rb +41 -0
- data/lib/fin_it/dsl.rb +13 -0
- data/lib/fin_it/engine.rb +15 -0
- data/lib/fin_it/financial_model/account_balances.rb +99 -0
- data/lib/fin_it/financial_model/account_hierarchy.rb +158 -0
- data/lib/fin_it/financial_model/category_values.rb +179 -0
- data/lib/fin_it/financial_model/currency_helpers.rb +14 -0
- data/lib/fin_it/financial_model/date_helpers.rb +58 -0
- data/lib/fin_it/financial_model/debugging.rb +353 -0
- data/lib/fin_it/financial_model/period_flows.rb +121 -0
- data/lib/fin_it/financial_model/validation.rb +85 -0
- data/lib/fin_it/financial_model/variable_matching.rb +49 -0
- data/lib/fin_it/financial_model.rb +395 -0
- data/lib/fin_it/model_template.rb +121 -0
- data/lib/fin_it/outputs/base_output.rb +51 -0
- data/lib/fin_it/outputs/console_output.rb +1528 -0
- data/lib/fin_it/outputs/monthly_console_output.rb +145 -0
- data/lib/fin_it/outputs/zaxcel_output.rb +1264 -0
- data/lib/fin_it/payment_schedule.rb +112 -0
- data/lib/fin_it/plan.rb +159 -0
- data/lib/fin_it/reports/balance_sheet.rb +638 -0
- data/lib/fin_it/reports/base_report.rb +239 -0
- data/lib/fin_it/reports/cash_flow_statement.rb +480 -0
- data/lib/fin_it/reports/custom_sheet.rb +436 -0
- data/lib/fin_it/reports/income_statement.rb +793 -0
- data/lib/fin_it/reports/period_comparison.rb +309 -0
- data/lib/fin_it/reports/scenario_comparison.rb +296 -0
- data/lib/fin_it/temporal_value.rb +349 -0
- data/lib/fin_it/transaction_generator/account_resolver.rb +118 -0
- data/lib/fin_it/transaction_generator/cache_management.rb +39 -0
- data/lib/fin_it/transaction_generator/date_generation.rb +57 -0
- data/lib/fin_it/transaction_generator.rb +357 -0
- data/lib/fin_it/version.rb +6 -0
- data/lib/fin_it.rb +27 -0
- data/test/fin_it/calculator_test.rb +109 -0
- data/test/fin_it/complex_model_test.rb +198 -0
- data/test/fin_it/debugging_test.rb +112 -0
- data/test/fin_it/driver_variables_test.rb +109 -0
- data/test/fin_it/dsl_test.rb +581 -0
- data/test/fin_it/financial_model_test.rb +196 -0
- data/test/fin_it/frequency_test.rb +51 -0
- data/test/fin_it/outputs/console_output_test.rb +249 -0
- data/test/fin_it/plan_test.rb +281 -0
- data/test/fin_it/reports/account_balance_test.rb +232 -0
- data/test/fin_it/reports/balance_sheet_test.rb +355 -0
- data/test/fin_it/reports/cash_flow_statement_test.rb +234 -0
- data/test/fin_it/reports/custom_sheet_test.rb +246 -0
- data/test/fin_it/reports/income_statement_test.rb +431 -0
- data/test/fin_it/reports/period_comparison_test.rb +226 -0
- data/test/fin_it/reports/restaurant_model_test.rb +225 -0
- data/test/fin_it/reports/scenario_comparison_test.rb +414 -0
- data/test/scripts/generate_demo_reports.rb +47 -0
- data/test/scripts/startup_saas_demo.rb +62 -0
- data/test/test_helper.rb +25 -0
- data/test/verify_accounting_equation.rb +91 -0
- metadata +264 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'stringio'
|
|
4
|
+
require_relative "../test_helper"
|
|
5
|
+
|
|
6
|
+
class FinancialModelTest < Minitest::Test
|
|
7
|
+
def setup
|
|
8
|
+
@model = FinIt.define(default_currency: 'USD') do
|
|
9
|
+
config do
|
|
10
|
+
start_date 2024
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
account :checking do
|
|
14
|
+
type :asset
|
|
15
|
+
currency 'USD'
|
|
16
|
+
opening_balance 10_000
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
account :savings do
|
|
20
|
+
type :asset
|
|
21
|
+
currency 'USD'
|
|
22
|
+
opening_balance 5_000
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
account :credit_card do
|
|
26
|
+
type :liability
|
|
27
|
+
currency 'USD'
|
|
28
|
+
opening_balance 2_000 # Positive value
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
category :income, type: :income do
|
|
32
|
+
variable :salary, currency: 'USD', frequency: :monthly, account: :checking do
|
|
33
|
+
value 5_000, start_date: "2024-01-01", end_date: "2024-12-31"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
category :expenses, type: :expense do
|
|
38
|
+
variable :rent, currency: 'USD', frequency: :monthly, account: :credit_card do
|
|
39
|
+
value 2_000, start_date: "2024-01-01", end_date: "2024-12-31"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
calculated :utilities,
|
|
43
|
+
formula: "500",
|
|
44
|
+
frequency: :monthly,
|
|
45
|
+
account: :credit_card,
|
|
46
|
+
start_date: "2024-01-01",
|
|
47
|
+
end_date: "2024-12-31" do
|
|
48
|
+
description "Monthly utilities"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def test_account_balance_calculation
|
|
55
|
+
# Generate transactions up to end of February
|
|
56
|
+
@model.generate_transactions(Date.new(2024, 2, 28))
|
|
57
|
+
|
|
58
|
+
# Checking account: opening 10,000 + 2 months salary (5,000 each) = 20,000
|
|
59
|
+
checking_balance = @model.account_balance(:checking, as_of_date: Date.new(2024, 2, 28))
|
|
60
|
+
assert_in_delta 20_000, checking_balance, 0.01, "Checking balance should be 20,000"
|
|
61
|
+
|
|
62
|
+
# Credit card: opening 2,000 + 2 months rent (2,000 each) + 2 months utilities (500 each) = 7,000
|
|
63
|
+
# (Liabilities increase with credits, so expenses credit the liability account)
|
|
64
|
+
credit_balance = @model.account_balance(:credit_card, as_of_date: Date.new(2024, 2, 28))
|
|
65
|
+
assert_in_delta 7_000, credit_balance, 0.01, "Credit card balance should be 7,000"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def test_transaction_queries
|
|
69
|
+
@model.generate_transactions(Date.new(2024, 3, 31))
|
|
70
|
+
|
|
71
|
+
# Query by account
|
|
72
|
+
checking_txns = @model.transactions(account: :checking)
|
|
73
|
+
assert checking_txns.any?, "Should have transactions for checking account"
|
|
74
|
+
assert checking_txns.all? { |t| t[:debit_account] == :checking || t[:credit_account] == :checking },
|
|
75
|
+
"All transactions should involve checking account"
|
|
76
|
+
|
|
77
|
+
# Query by date range
|
|
78
|
+
jan_txns = @model.transactions(date_range: { start: Date.new(2024, 1, 1), end: Date.new(2024, 1, 31) })
|
|
79
|
+
assert jan_txns.any?, "Should have transactions in January"
|
|
80
|
+
assert jan_txns.all? { |t| t[:date].month == 1 }, "All transactions should be in January"
|
|
81
|
+
|
|
82
|
+
# Query by variable
|
|
83
|
+
salary_txns = @model.transactions(variable: :salary)
|
|
84
|
+
assert salary_txns.any?, "Should have salary transactions"
|
|
85
|
+
assert salary_txns.all? { |t| t[:variable] == :salary }, "All transactions should be for salary"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def test_balance_sheet_validation
|
|
89
|
+
# Model should validate A = L + E
|
|
90
|
+
# Assets: checking 10,000 + savings 5,000 = 15,000
|
|
91
|
+
# Liabilities: credit_card 2,000 (positive value)
|
|
92
|
+
# Equity: auto-created to balance = 15,000 - 2,000 = 13,000
|
|
93
|
+
|
|
94
|
+
assert @model.accounts.key?(:equity), "Equity account should exist"
|
|
95
|
+
equity_balance = @model.accounts[:equity].opening_balance
|
|
96
|
+
|
|
97
|
+
total_assets = @model.accounts.values.select { |a| a.type == :asset }.sum { |a| a.opening_balance.to_f.abs }
|
|
98
|
+
total_liabilities = @model.accounts.values.select { |a| a.type == :liability }.sum { |a| a.opening_balance.to_f.abs }
|
|
99
|
+
equity_abs = equity_balance.to_f.abs
|
|
100
|
+
|
|
101
|
+
assert_in_delta total_assets, total_liabilities + equity_abs, 0.01,
|
|
102
|
+
"Balance sheet should balance: Assets = Liabilities + Equity"
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def test_start_date_validation
|
|
106
|
+
# Test with year number
|
|
107
|
+
model1 = FinIt.define(default_currency: 'USD') do
|
|
108
|
+
config do
|
|
109
|
+
start_date 2023
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
account :checking do
|
|
113
|
+
type :asset
|
|
114
|
+
currency 'USD'
|
|
115
|
+
opening_balance 0
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
assert_equal Date.new(2023, 1, 1), model1.start_date
|
|
120
|
+
|
|
121
|
+
# Test with date string
|
|
122
|
+
model2 = FinIt.define(default_currency: 'USD') do
|
|
123
|
+
config do
|
|
124
|
+
start_date "2023-06-15"
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
account :checking do
|
|
128
|
+
type :asset
|
|
129
|
+
currency 'USD'
|
|
130
|
+
opening_balance 0
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
assert_equal Date.new(2023, 6, 15), model2.start_date
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def test_date_validation_prevents_before_start_date
|
|
138
|
+
error = assert_raises(FinIt::StartDateValidationError) do
|
|
139
|
+
@model.account_balance(:checking, as_of_date: Date.new(2023, 12, 31))
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
assert_match(/before model start_date/, error.message)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def test_variable_value_query
|
|
146
|
+
# Get variable value for a specific period
|
|
147
|
+
jan_salary = @model.variable_value(:salary, date: Date.new(2024, 1, 15), period_type: :monthly)
|
|
148
|
+
assert jan_salary, "Salary should exist"
|
|
149
|
+
assert_in_delta 5_000, jan_salary.to_f, 0.01, "Monthly salary should be 5,000"
|
|
150
|
+
|
|
151
|
+
# Annual value
|
|
152
|
+
annual_salary = @model.variable_value(:salary, date: Date.new(2024, 1, 15), period_type: :annual)
|
|
153
|
+
assert_in_delta 60_000, annual_salary.to_f, 0.01, "Annual salary should be 60,000"
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def test_transaction_cache_validation
|
|
157
|
+
# Initially cache should be invalid (no transactions generated)
|
|
158
|
+
assert !@model.transaction_cache_valid?, "Cache should be invalid initially"
|
|
159
|
+
|
|
160
|
+
# Generate transactions
|
|
161
|
+
@model.generate_transactions(Date.new(2024, 12, 31))
|
|
162
|
+
|
|
163
|
+
# Cache should now be valid
|
|
164
|
+
assert @model.transaction_cache_valid?, "Cache should be valid after generation"
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def test_default_start_date_warning
|
|
168
|
+
# Capture warning output
|
|
169
|
+
warning_output = capture_warnings do
|
|
170
|
+
model = FinIt.define(default_currency: 'USD') do
|
|
171
|
+
account :checking do
|
|
172
|
+
type :asset
|
|
173
|
+
currency 'USD'
|
|
174
|
+
opening_balance 0
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
assert model.start_date, "Should have default start date"
|
|
179
|
+
assert_equal Date.new(Date.today.year, 1, 1), model.start_date
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
assert_match(/Warning.*start_date/, warning_output, "Should warn about default start_date")
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
private
|
|
186
|
+
|
|
187
|
+
def capture_warnings
|
|
188
|
+
old_stderr = $stderr
|
|
189
|
+
$stderr = StringIO.new
|
|
190
|
+
yield
|
|
191
|
+
$stderr.string
|
|
192
|
+
ensure
|
|
193
|
+
$stderr = old_stderr
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../test_helper"
|
|
4
|
+
|
|
5
|
+
class FrequencyTest < Minitest::Test
|
|
6
|
+
def setup
|
|
7
|
+
@model = FinIt.define(default_currency: 'USD') do
|
|
8
|
+
config do
|
|
9
|
+
start_date 2024
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
account :test_account do
|
|
13
|
+
type :asset
|
|
14
|
+
currency 'USD'
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
category :income, type: :income do
|
|
18
|
+
variable :daily_income, currency: 'USD', frequency: :daily, account: :test_account do
|
|
19
|
+
value 100 # $100/day
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
variable :monthly_salary, currency: 'USD', frequency: :monthly, account: :test_account do
|
|
23
|
+
value 5_000 # $5,000/month
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
@date = Date.new(2024, 6, 15)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def test_daily_income_annualized
|
|
32
|
+
daily_annual = @model.calculator.calculate(:daily_income, date: @date, period_type: :annual).to_f
|
|
33
|
+
assert_in_delta 36_500, daily_annual, 0.01, "Daily income should annualize to $36,500"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def test_monthly_salary_annualized
|
|
37
|
+
monthly_annual = @model.calculator.calculate(:monthly_salary, date: @date, period_type: :annual).to_f
|
|
38
|
+
assert_in_delta 60_000, monthly_annual, 0.01, "Monthly salary should annualize to $60,000"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def test_daily_income_monthly
|
|
42
|
+
daily_monthly = @model.calculator.calculate(:daily_income, date: @date, period_type: :monthly).to_f
|
|
43
|
+
assert_in_delta 3_041.67, daily_monthly, 0.01, "Daily income should scale to $3,041.67/month"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def test_monthly_salary_monthly
|
|
47
|
+
monthly_monthly = @model.calculator.calculate(:monthly_salary, date: @date, period_type: :monthly).to_f
|
|
48
|
+
assert_in_delta 5_000, monthly_monthly, 0.01, "Monthly salary should be $5,000/month"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../../test_helper"
|
|
4
|
+
|
|
5
|
+
class ConsoleOutputTest < Minitest::Test
|
|
6
|
+
def setup
|
|
7
|
+
@model = FinIt.define(default_currency: 'USD') do
|
|
8
|
+
config do
|
|
9
|
+
start_date 2024
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
category :current_assets, type: :asset do
|
|
13
|
+
account :checking do
|
|
14
|
+
currency 'USD'
|
|
15
|
+
opening_balance 10_000
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
variable :cash, currency: 'USD', frequency: :annual do
|
|
19
|
+
value 10_000, start_date: "2024-01-01", end_date: "2024-12-31"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
category :income, type: :income do
|
|
24
|
+
variable :salary, currency: 'USD', frequency: :annual do
|
|
25
|
+
value 100_000, start_date: "2024-01-01", end_date: "2024-12-31"
|
|
26
|
+
description "Annual salary"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
variable :bonus, currency: 'USD', frequency: :annual do
|
|
30
|
+
value 20_000, start_date: "2024-01-01", end_date: "2024-12-31"
|
|
31
|
+
description "Annual bonus"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
category :expenses, type: :expense do
|
|
36
|
+
variable :rent, currency: 'USD', frequency: :monthly, account: :checking do
|
|
37
|
+
value 2_000, start_date: "2024-01-01", end_date: "2024-12-31"
|
|
38
|
+
description "Monthly rent"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
category :current_liabilities, type: :liability do
|
|
43
|
+
variable :debt, currency: 'USD', frequency: :annual do
|
|
44
|
+
value 5_000, start_date: "2024-01-01", end_date: "2024-12-31"
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
category :equity, type: :equity do
|
|
49
|
+
variable :owner_equity, currency: 'USD', frequency: :annual do
|
|
50
|
+
value 5_000, start_date: "2024-01-01", end_date: "2024-12-31"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def test_monthly_income_statement_output
|
|
57
|
+
report = FinIt::Reports::IncomeStatement.new(
|
|
58
|
+
@model,
|
|
59
|
+
start_date: Date.new(2024, 1, 1),
|
|
60
|
+
end_date: Date.new(2024, 1, 31),
|
|
61
|
+
output_currency: 'USD'
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
# Should generate output without error
|
|
65
|
+
suppress_output do
|
|
66
|
+
result = report.output(FinIt::Outputs::ConsoleOutput)
|
|
67
|
+
assert_nil result, "Output should return nil"
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def test_quarterly_income_statement_output
|
|
72
|
+
report = FinIt::Reports::IncomeStatement.new(
|
|
73
|
+
@model,
|
|
74
|
+
start_date: Date.new(2024, 1, 1),
|
|
75
|
+
end_date: Date.new(2024, 3, 31),
|
|
76
|
+
output_currency: 'USD'
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# Should generate output without error
|
|
80
|
+
suppress_output do
|
|
81
|
+
result = report.output(FinIt::Outputs::ConsoleOutput)
|
|
82
|
+
assert_nil result, "Output should return nil"
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def test_monthly_balance_sheet_output
|
|
87
|
+
report = FinIt::Reports::BalanceSheet.new(
|
|
88
|
+
@model,
|
|
89
|
+
start_date: Date.new(2024, 1, 1),
|
|
90
|
+
end_date: Date.new(2024, 1, 31),
|
|
91
|
+
output_currency: 'USD'
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
# Should generate output without error
|
|
95
|
+
suppress_output do
|
|
96
|
+
result = report.output(FinIt::Outputs::ConsoleOutput)
|
|
97
|
+
assert_nil result, "Output should return nil"
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def test_generate_monthly_reports_output
|
|
102
|
+
report = FinIt::Reports::IncomeStatement.new(
|
|
103
|
+
@model,
|
|
104
|
+
start_date: Date.new(2024, 1, 1),
|
|
105
|
+
end_date: Date.new(2024, 3, 31),
|
|
106
|
+
output_currency: 'USD'
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
monthly_reports = report.generate_monthly(Date.new(2024, 1, 1), Date.new(2024, 3, 31))
|
|
110
|
+
|
|
111
|
+
assert_equal 3, monthly_reports.length
|
|
112
|
+
|
|
113
|
+
# Output each monthly report - should not raise errors
|
|
114
|
+
suppress_output do
|
|
115
|
+
monthly_reports.each do |month_data|
|
|
116
|
+
temp_report = FinIt::Reports::IncomeStatement.new(
|
|
117
|
+
@model,
|
|
118
|
+
start_date: month_data[:period][:start],
|
|
119
|
+
end_date: month_data[:period][:end],
|
|
120
|
+
output_currency: 'USD'
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
result = temp_report.output(FinIt::Outputs::ConsoleOutput)
|
|
124
|
+
assert_nil result, "Output should return nil"
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def test_generate_yearly_report_output
|
|
130
|
+
report = FinIt::Reports::IncomeStatement.new(
|
|
131
|
+
@model,
|
|
132
|
+
start_date: Date.new(2024, 1, 1),
|
|
133
|
+
end_date: Date.new(2024, 12, 31),
|
|
134
|
+
output_currency: 'USD'
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
yearly_report = report.generate_yearly(2024)
|
|
138
|
+
|
|
139
|
+
assert yearly_report[:period]
|
|
140
|
+
assert yearly_report[:report]
|
|
141
|
+
|
|
142
|
+
# Output yearly report - should not raise errors
|
|
143
|
+
suppress_output do
|
|
144
|
+
temp_report = FinIt::Reports::IncomeStatement.new(
|
|
145
|
+
@model,
|
|
146
|
+
start_date: yearly_report[:period][:start],
|
|
147
|
+
end_date: yearly_report[:period][:end],
|
|
148
|
+
output_currency: 'USD'
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
result = temp_report.output(FinIt::Outputs::ConsoleOutput)
|
|
152
|
+
assert_nil result, "Output should return nil"
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def test_generate_at_specific_date_output
|
|
157
|
+
report = FinIt::Reports::IncomeStatement.new(
|
|
158
|
+
@model,
|
|
159
|
+
start_date: Date.new(2024, 1, 1),
|
|
160
|
+
end_date: Date.new(2024, 12, 31),
|
|
161
|
+
output_currency: 'USD'
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
date_report = report.generate_at(Date.new(2024, 6, 15))
|
|
165
|
+
|
|
166
|
+
assert date_report[:period]
|
|
167
|
+
assert date_report[:report]
|
|
168
|
+
|
|
169
|
+
# Output date-specific report - should not raise errors
|
|
170
|
+
suppress_output do
|
|
171
|
+
temp_report = FinIt::Reports::IncomeStatement.new(
|
|
172
|
+
@model,
|
|
173
|
+
start_date: date_report[:period][:start],
|
|
174
|
+
end_date: date_report[:period][:end],
|
|
175
|
+
output_currency: 'USD'
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
result = temp_report.output(FinIt::Outputs::ConsoleOutput)
|
|
179
|
+
assert_nil result, "Output should return nil"
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def test_balance_sheet_monthly_output
|
|
184
|
+
report = FinIt::Reports::BalanceSheet.new(
|
|
185
|
+
@model,
|
|
186
|
+
start_date: Date.new(2024, 1, 1),
|
|
187
|
+
end_date: Date.new(2024, 3, 31),
|
|
188
|
+
output_currency: 'USD'
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
monthly_reports = report.generate_monthly(Date.new(2024, 1, 1), Date.new(2024, 2, 28))
|
|
192
|
+
|
|
193
|
+
assert monthly_reports.length > 0
|
|
194
|
+
|
|
195
|
+
# Output each monthly balance sheet - should not raise errors
|
|
196
|
+
suppress_output do
|
|
197
|
+
monthly_reports.each do |month_data|
|
|
198
|
+
temp_report = FinIt::Reports::BalanceSheet.new(
|
|
199
|
+
@model,
|
|
200
|
+
start_date: month_data[:period][:start],
|
|
201
|
+
end_date: month_data[:period][:end],
|
|
202
|
+
output_currency: 'USD'
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
result = temp_report.output(FinIt::Outputs::ConsoleOutput)
|
|
206
|
+
assert_nil result, "Output should return nil"
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def test_periods_as_columns_output
|
|
212
|
+
report = FinIt::Reports::IncomeStatement.new(
|
|
213
|
+
@model,
|
|
214
|
+
start_date: Date.new(2024, 1, 1),
|
|
215
|
+
end_date: Date.new(2024, 3, 31),
|
|
216
|
+
output_currency: 'USD'
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
monthly_reports = report.generate_monthly(Date.new(2024, 1, 1), Date.new(2024, 3, 31))
|
|
220
|
+
|
|
221
|
+
# Test output with periods as columns
|
|
222
|
+
suppress_output do
|
|
223
|
+
output = FinIt::Outputs::ConsoleOutput.new(report, periods: monthly_reports)
|
|
224
|
+
result = output.generate
|
|
225
|
+
|
|
226
|
+
assert_nil result, "Output should return nil"
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def test_period_summary_as_columns_output
|
|
231
|
+
report = FinIt::Reports::IncomeStatement.new(
|
|
232
|
+
@model,
|
|
233
|
+
start_date: Date.new(2024, 1, 1),
|
|
234
|
+
end_date: Date.new(2024, 3, 31),
|
|
235
|
+
output_currency: 'USD'
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
summary = report.period_summary(period_type: :monthly)
|
|
239
|
+
|
|
240
|
+
# Test output with period summary as columns
|
|
241
|
+
suppress_output do
|
|
242
|
+
output = FinIt::Outputs::ConsoleOutput.new(report, periods: summary)
|
|
243
|
+
result = output.generate
|
|
244
|
+
|
|
245
|
+
assert_nil result, "Output should return nil"
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|