diff --git a/bpfin/back_end_call/back_end_prelim.py b/bpfin/back_end_call/back_end_prelim.py index c6ba9bf75506630f69d242851e8920ccdc7bad17..ba93bcba009eef03bfb05d4f7b7d8cd8da718860 100644 --- a/bpfin/back_end_call/back_end_prelim.py +++ b/bpfin/back_end_call/back_end_prelim.py @@ -35,13 +35,19 @@ def prelim_scenario(raw_monthly_bill_table, raw_annual_bill_table, raw_income_in customer_preference (dictionary): customer preference for financing plan Returns: - project_economics (dictionary): overview of project economics of this scenario, see description - graphic_dictionary (dictionary): dict of dict, showcase energy saving, energy debt service, net savings, see description - scenario_plot (tuple): (saving%, cost), to draw a dot of scenario in budget simulator graph - loan_summary (list): list of list, showing loan financed financing plan. see description - downpayment (float): self-finance_downpayment amount - - + dict of items: + { + 'economics' (dictionary): overview of project economics of this scenario, see description + 'graph_dict' (dictionary): dict of dict, showcase energy saving, energy debt service, net savings, see description + 'budget_plot' (tuple): (saving%, cost), to draw a dot of scenario in budget simulator graph + 'loan_summary' (list): list of list, showing loan financed financing plan. see description + 'downpayment' (float): self-finance_downpayment amount + 'prior_is' (dictionary): income statement in the format of income statement table for presnetation layer + 'prior_bs' (dictionary): balance sheet in the format of income statement table for presnetation layer + 'post_is' (dictionary): income statement in the format of income statement table for presnetation layer + 'post_bs' (dictionary): balance sheet in the format of income statement table for presnetation layer + 'feasibility' (Boolean): a flag indicating feasibility of the scenario + } Description: raw_income_input = {2014: {'revenue': 90.0, 'utility_expense': 55.0, 'non_utility_expense': 35.0}, 2015:{},} raw_monthly_bill_table = { @@ -84,7 +90,7 @@ def prelim_scenario(raw_monthly_bill_table, raw_annual_bill_table, raw_income_in 'cust_saving_dscr': float, customer required lower limit of (saving / debt service) ratio } - project_economics = { + economics = { 'estimated_cost': 150000.0, 'overall_saving': 0.46592312148565274, 'first_year_saving': 28667.507248011731, @@ -93,13 +99,13 @@ def prelim_scenario(raw_monthly_bill_table, raw_annual_bill_table, raw_income_in 'min_noi_dscr': 1.7556178946382468, 'min_cash_dscr': 5.6110894382891772 } - loan_financing_plan = [ + loan_summary = [ ['Lender', 'Amount Borrowed', 'Amount Upper Limit', 'Annual Interest Rate', 'Duration, months', 'Monthly Debt Service'], ['NYSERDA', 25000.0, 500000, 0.08, 120, 303.31898588839437], ['Joe Fund', 50000.0, 50000, 0.05, 108, 575.86365841823613], ['Tooraj Capital', 75000.0, 75000, 0.07, 114, 902.56078079882502] ] - graph_dictionary = { + graph_dict = { 'energy_expenses': {2012: 55002.38772098512, 2013: 55616.154107144292, ...}, 'total_loan': {2012: 0, 2013: 0, 2014: 0, 2015: 0, 2016: 0, 2017: 17817.434251054554, ...}, 'net_savings': {2014: 0.0, 2015: 0.0, 2016: 0.0, 2017: 1399.2525568434357, ...} @@ -109,7 +115,6 @@ def prelim_scenario(raw_monthly_bill_table, raw_annual_bill_table, raw_income_in add return of: annual_financial_projection_table monthly_financial_projection_table - write unit test file for scenario class and for prelim_scenario back_end_call """ prior_annual_bill_table, manual_input_dict, prior_month_bill, unsued_display_table = form_annual_bill_table( raw_monthly_bill_table, raw_annual_bill_table, analysis_date @@ -191,48 +196,16 @@ def prelim_scenario(raw_monthly_bill_table, raw_annual_bill_table, raw_income_in budget_plot = (scenario_ob.get_budget_plot()) - # return scenario_ob.get_graph_dict(), scenario_ob.get_economics(), scenario_ob.get_annual_debt_service() - return ( - scenario_ob.get_economics(), - scenario_ob.get_graph_dict(), - scenario_ob.get_prior_income_statement(), - scenario_ob.get_prior_balance_sheet_statement(), - scenario_ob.get_post_income_statement(), - scenario_ob.get_post_balance_sheet_statement(), - budget_plot, - loan_summary, - downpayment - ) - - -# **** ugly test **** -# from bpfin.tests.testdata import feature_data as db -# import pprint - -# print( -# prelim_scenario( -# raw_monthly_bill_table=db.raw_monthly_bill_table, -# raw_annual_bill_table=db.raw_annual_bill_table, -# raw_income_input=db.raw_income_input, -# growth_rate_flag=-2.0, -# raw_liability_input=db.raw_liability_input, -# raw_cash_balance=db.raw_cash_balance, -# raw_loan_input_list=db.raw_loan_input_list, -# analysis_date=db.analysis_date, -# commission_date=db.commission_date, -# construction_cost=db.cost_estimation, -# percent_saving_dict=db.percent_saving_dict, -# full_saving_dict=db.full_saving_dict, -# req_dscr=db.req_dscr, -# customer_preference=db.customer_preference -# ) -# ) - -# pp = pprint.PrettyPrinter(width=120, indent=4, compact=True) -# pp.pprint(prior_income_statement_result) - -# writein = str(result) -# f = open('data_generation.py', 'w') -# f.write(writein) -# f.close() + return { + 'economics': scenario_ob.get_economics(), + 'graph_dict': scenario_ob.get_graph_dict(), + 'budget_plot': budget_plot, + 'loan_summary': loan_summary, + 'downpayment': downpayment, + 'prior_is': scenario_ob.get_prior_income_statement(), + 'prior_bs': scenario_ob.get_prior_balance_sheet_statement(), + 'post_is': scenario_ob.get_post_income_statement(), + 'post_bs': scenario_ob.get_post_balance_sheet_statement(), + 'feasibility': scenario_ob.get_feasibility(), + } diff --git a/bpfin/financials/scenario.py b/bpfin/financials/scenario.py index 613a700aff14f34148dcf664a9bc6ef9140b74d9..b8725f884577257536755276511fb98a749412b5 100644 --- a/bpfin/financials/scenario.py +++ b/bpfin/financials/scenario.py @@ -328,7 +328,10 @@ class Scenario(): def get_post_income_statement(self): """Fetch full income statement table post to retrofit.""" - post_full_income_statement = self.post_income_statement_table.get_full_income_table() + if self.get_feasibility(): + post_full_income_statement = self.post_income_statement_table.get_full_income_table() + else: + post_full_income_statement = self.prior_income_statement_table.get_full_income_table() return self.get_statement(post_full_income_statement, IS_Item_List) def get_prior_balance_sheet_statement(self): @@ -336,7 +339,10 @@ class Scenario(): return self.get_statement(prior_full_balance_statement, BS_Item_List) def get_post_balance_sheet_statement(self): - post_full_balance_statement = self.post_balance_sheet_table.get_cash_dict() + if self.get_feasibility(): + post_full_balance_statement = self.post_balance_sheet_table.get_cash_dict() + else: + post_full_balance_statement = self.prior_balance_sheet_table.get_cash_dict() return self.get_statement(post_full_balance_statement, BS_Item_List) def get_financing_plan(self): diff --git a/bpfin/tests/test_back_end_call/test_back_end_prelim.py b/bpfin/tests/test_back_end_call/test_back_end_prelim.py index 9be90b14ea6004ad89d28c0f19df8b7c77b6cc57..4d0e507630430e7fcd0fdba80fc51cc075ca16a0 100644 --- a/bpfin/tests/test_back_end_call/test_back_end_prelim.py +++ b/bpfin/tests/test_back_end_call/test_back_end_prelim.py @@ -1,3 +1,211 @@ """ To Do we still need to write test files for back_end_call prelim_analysis """ +from bpfin.back_end_call.back_end_prelim import prelim_scenario +from bpfin.financials.scenario import Scenario +from bpfin.financials.cash_balance import cash_balance +from bpfin.back_end_call.back_end_inputs import form_annual_bill_table +from bpfin.financials.liability import final_liability_dict +from bpfin.financials.balance_sheet_projection import balance_sheet_projection +from bpfin.financials.financial_income import Income_Statement_Table +from bpfin.financials.financial_balance import Balance_Sheet_Table +from bpfin.tests.testdata import feature_data as db +from bpfin.lib.other import UTILITY_TYPE_LIST +from datetime import date +import pprint + +def test_back_end_prelim_dev(): + analysis_date = { + 'proforma_start': date(2011, 1, 1), + 'proforma_duration': 30} + + raw_monthly_bill_table = { + UTILITY_TYPE_LIST[0]: None, + UTILITY_TYPE_LIST[1]: None, + UTILITY_TYPE_LIST[2]: None, + UTILITY_TYPE_LIST[3]: None} + + raw_annual_bill_table = { + UTILITY_TYPE_LIST[0]: {2016: 3776, 2015: 3143.18, 2013: 3485.21}, + UTILITY_TYPE_LIST[1]: {2017: 394.24, 2015: 362.59, 2016: 340.64}, + UTILITY_TYPE_LIST[2]: {2014: 20084.94, 2012: 20692.32, 2013: 18633.83}, + UTILITY_TYPE_LIST[3]: {2015: 199.45, 2014: 200.01} + } + + growth_rate_flag=0.02 + raw_income_input = { + 2014: { + 'revenue': 110008.00, + 'utility_expense': 28737.92, + 'non_utility_expense': 65668.08, + }, + 2015: { + 'revenue': 110605.00, + 'utility_expense': 28907.53, + 'non_utility_expense': 66027.47, + }, + 2016: { + 'revenue': 113507.30, + 'utility_expense': 28542.57, + 'non_utility_expense': 67956.63, + } + } + raw_cash_balance = { + date(2017, 12, 31): (8500, True), + date(2018, 12, 31): (10500, True), + } + raw_liability_input = { + 'debt1': (1550, 'Paris Capital', 90, date(2018, 12, 12)), + 'debt2': (120, 'HPD', 45, date(2019, 2, 1)) + } + manual_input_dict = { + UTILITY_TYPE_LIST[0]: True, + UTILITY_TYPE_LIST[1]: True, + UTILITY_TYPE_LIST[2]: True, + UTILITY_TYPE_LIST[3]: True + } + loan_term_2 = {'institute': 'Goldman', 'max_amount': 60000, 'interest': 0.0925, 'duration': 120} + loan_term_3 = {'institute': 'NYGB', 'max_amount': 10000, 'interest': 0.09, 'duration': 96} + loan_input_list = [loan_term_2, loan_term_3] + + prior_annual_bill_table, manual_input_dict, prior_month_bill, unsued_display_table = form_annual_bill_table( + raw_monthly_bill_table, raw_annual_bill_table, analysis_date) + + prior_IS_table = Income_Statement_Table( + raw_income_input, + prior_annual_bill_table, + analysis_date) + prior_IS_table.project(growth_rate_flag=growth_rate_flag, annual_bill_table=prior_annual_bill_table) + + percent_saving_dict = { + UTILITY_TYPE_LIST[0]: -2.40, + UTILITY_TYPE_LIST[1]: -0.50, + UTILITY_TYPE_LIST[2]: 1.00, + UTILITY_TYPE_LIST[3]: 0.0 + } + full_saving_dict = { + UTILITY_TYPE_LIST[0]: None, + UTILITY_TYPE_LIST[1]: None, + UTILITY_TYPE_LIST[2]: None, + UTILITY_TYPE_LIST[3]: None + } + customer_preference = { + 'downpayment_max': 8000.00, + 'expected_payback': 150, + } + req_dscr = { + 'req_noi_dscr': 1.15, + 'req_cash_dscr': 1.15, + 'req_saving_dscr': 1.10 + } + + prelim_result = prelim_scenario( + raw_monthly_bill_table=raw_monthly_bill_table, + raw_annual_bill_table=raw_annual_bill_table, + raw_income_input=raw_income_input, + growth_rate_flag=growth_rate_flag, + raw_liability_input=raw_liability_input, + raw_cash_balance=raw_cash_balance, + raw_loan_input_list=loan_input_list, + analysis_date=analysis_date, + commission_date=date(2020,1,31), + construction_cost=66500.00, + percent_saving_dict=percent_saving_dict, + full_saving_dict=full_saving_dict, + req_dscr=req_dscr, + customer_preference=customer_preference) + + result = {} + result['economics'] = prelim_result['economics'] + outcome = {} + outcome['economics'] = { + 'estimated_cost': 66500.0, + 'overall_saving': 0.4739309857039658, + 'first_year_saving': 11297.273000000001, + 'simple_payback': 5.886376296297345, + 'min_saving_dscr': 1.0999999999999999, + 'min_noi_dscr': 3.162510789362292, + 'min_cash_dscr': 3.219949472736734, + } + assert result==outcome + + +def test_back_end_prelim_fail(): + prelim_result = prelim_scenario( + raw_monthly_bill_table=db.raw_monthly_bill_table, + raw_annual_bill_table=db.raw_annual_bill_table, + raw_income_input=db.raw_income_input, + growth_rate_flag=-2, + raw_liability_input=db.raw_liability_input, + raw_cash_balance=db.raw_cash_balance, + raw_loan_input_list=db.fail_loan_input_list, + analysis_date=db.analysis_date, + commission_date=db.commission_date, + construction_cost=db.cost_estimation, + percent_saving_dict=db.fail_saving_dict, + full_saving_dict=db.full_saving_dict, + req_dscr=db.req_dscr, + customer_preference=db.fail_customer_preference) + + result = {} + result['economics'] = prelim_result['economics'] + result['graph_dict'] = prelim_result['graph_dict'] + result['feasibility'] = prelim_result['feasibility'] + result['loan_summary'] = prelim_result['loan_summary'] + result['budget_plot'] = prelim_result['budget_plot'] + result['downpayment'] = prelim_result['downpayment'] + outcome = {} + outcome['economics'] = db.fail_scenario_outcome['economics'] + outcome['graph_dict'] = db.fail_scenario_outcome['graph_dict'] + outcome['feasibility'] = db.fail_scenario_outcome['feasibility'] + outcome['loan_summary'] = db.fail_scenario_outcome['loan_summary'] + outcome['budget_plot'] = db.fail_scenario_outcome['budget_plot'] + outcome['downpayment'] = db.fail_scenario_outcome['downpayment'] + assert prelim_result['prior_is'] == prelim_result['post_is'] + assert prelim_result['prior_bs'] == prelim_result['post_bs'] + assert result == outcome + + +def test_back_end_prelim_1(): + prelim_result = prelim_scenario( + raw_monthly_bill_table=db.raw_monthly_bill_table, + raw_annual_bill_table=db.raw_annual_bill_table, + raw_income_input=db.raw_income_input, + growth_rate_flag=-2, + raw_liability_input=db.raw_liability_input, + raw_cash_balance=db.raw_cash_balance, + raw_loan_input_list=db.raw_loan_input_list, + analysis_date=db.analysis_date, + commission_date=db.commission_date, + construction_cost=db.cost_estimation, + percent_saving_dict=db.percent_saving_dict, + full_saving_dict=db.full_saving_dict, + req_dscr=db.req_dscr, + customer_preference=db.customer_preference) + + result = {} + result['economics'] = prelim_result['economics'] + result['graph_dict'] = prelim_result['graph_dict'] + result['feasibility'] = prelim_result['feasibility'] + result['loan_summary'] = prelim_result['loan_summary'] + result['budget_plot'] = prelim_result['budget_plot'] + result['downpayment'] = prelim_result['downpayment'] + outcome = {} + outcome['economics'] = db.scenario_outcome['economics'] + outcome['graph_dict'] = db.scenario_outcome['graph_dict'] + outcome['feasibility'] = db.scenario_outcome['feasibility'] + outcome['loan_summary'] = db.scenario_outcome['loan_summary'] + outcome['budget_plot'] = db.scenario_outcome['budget_plot'] + outcome['downpayment'] = db.scenario_outcome['downpayment'] + # assert prelim_result[2] == prelim_result[4] + # assert prelim_result[3] == prelim_result[5] + assert result == outcome + +# pp = pprint.PrettyPrinter(width=120, indent=4, compact=True) +# pp.pprint(prior_income_statement_result) + +# writein = str(result) +# f = open('data_generation.py', 'w') +# f.write(writein) +# f.close() + diff --git a/bpfin/tests/test_financials/test_scenario.py b/bpfin/tests/test_financials/test_scenario.py index 1c95e57f892a13d00f20516213233fc58bfc62ed..8a4575f0cfd0aa0277f88654b562ff22d9f468b8 100644 --- a/bpfin/tests/test_financials/test_scenario.py +++ b/bpfin/tests/test_financials/test_scenario.py @@ -6,6 +6,8 @@ from bpfin.financials.balance_sheet_projection import balance_sheet_projection from bpfin.financials.financial_income import Income_Statement_Table from bpfin.financials.financial_balance import Balance_Sheet_Table from bpfin.tests.testdata import feature_data as db +from bpfin.lib.other import UTILITY_TYPE_LIST +from datetime import date def test_scenario_1(): growth_rate_flag=-2 @@ -69,6 +71,144 @@ def test_scenario_1(): assert result == outcome +def test_scenario_debug(): + analysis_date = { + 'proforma_start': date(2011, 1, 1), + 'proforma_duration': 30} + + raw_monthly_bill_table = { + UTILITY_TYPE_LIST[0]: None, + UTILITY_TYPE_LIST[1]: None, + UTILITY_TYPE_LIST[2]: None, + UTILITY_TYPE_LIST[3]: None} + + raw_annual_bill_table = { + UTILITY_TYPE_LIST[0]: {2016: 3776, 2015: 3143.18, 2013: 3485.21}, + UTILITY_TYPE_LIST[1]: {2017: 394.24, 2015: 362.59, 2016: 340.64}, + UTILITY_TYPE_LIST[2]: {2014: 20084.94, 2012: 20692.32, 2013: 18633.83}, + UTILITY_TYPE_LIST[3]: {2015: 199.45, 2014: 200.01} + } + + growth_rate_flag=0.02 + raw_income_input = { + 2014: { + 'revenue': 110008.00, + 'utility_expense': 28737.92, + 'non_utility_expense': 65668.08, + }, + 2015: { + 'revenue': 110605.00, + 'utility_expense': 28907.53, + 'non_utility_expense': 66027.47, + }, + 2016: { + 'revenue': 113507.30, + 'utility_expense': 28542.57, + 'non_utility_expense': 67956.63, + } + } + raw_cash_balance = { + date(2017, 12, 31): (8500, True), + date(2018, 12, 31): (10500, True), + } + raw_liability_input = { + 'debt1': (1550, 'Paris Capital', 90, date(2018, 12, 12)), + 'debt2': (120, 'HPD', 45, date(2019, 2, 1)) + } + manual_input_dict = { + UTILITY_TYPE_LIST[0]: True, + UTILITY_TYPE_LIST[1]: True, + UTILITY_TYPE_LIST[2]: True, + UTILITY_TYPE_LIST[3]: True + } + loan_term_2 = {'institute': 'Goldman', 'max_amount': 60000, 'interest': 0.0925, 'duration': 120} + loan_term_3 = {'institute': 'NYGB', 'max_amount': 10000, 'interest': 0.09, 'duration': 96} + loan_input_list = [loan_term_2, loan_term_3] + + + prior_annual_bill_table, manual_input_dict, prior_month_bill, unsued_display_table = form_annual_bill_table( + raw_monthly_bill_table, raw_annual_bill_table, analysis_date) + + prior_IS_table = Income_Statement_Table( + raw_income_input, + prior_annual_bill_table, + analysis_date) + prior_IS_table.project(growth_rate_flag=growth_rate_flag, annual_bill_table=prior_annual_bill_table) + + cash_balance_dict = cash_balance(analysis_date, raw_cash_balance) + liability_dict=final_liability_dict(analysis_date, raw_liability_input) + + + prior_BS_table = Balance_Sheet_Table( + cash_balance_dictionary=cash_balance_dict, + other_debt_service_dictionary=liability_dict, + net_income_dictionary=prior_IS_table.get_noi_dict() + ) + + prior_BS_table.project_balance_sheet( + analysis_date=db.analysis_date, + other_debt_service_dictionary=liability_dict, + net_income_dictionary=prior_IS_table.get_noi_dict() + ) + + scenario = Scenario( + analysis_date=analysis_date, + commission_date=date(2020,1,31), + construction_cost=66500.00, + manual_input_dict=manual_input_dict, + prior_annual_bill_table=prior_annual_bill_table, + prior_income_statement_table=prior_IS_table, + other_debt_service=liability_dict, + growth_rate_flag=growth_rate_flag, + prior_balance_sheet_table=prior_BS_table, + loan_input_list=loan_input_list, + ) + + percent_saving_dict = { + UTILITY_TYPE_LIST[0]: -2.40, + UTILITY_TYPE_LIST[1]: -0.50, + UTILITY_TYPE_LIST[2]: 1.00, + UTILITY_TYPE_LIST[3]: 0.0 + } + full_saving_dict = { + UTILITY_TYPE_LIST[0]: None, + UTILITY_TYPE_LIST[1]: None, + UTILITY_TYPE_LIST[2]: None, + UTILITY_TYPE_LIST[3]: None + } + customer_preference = { + 'downpayment_max': 8000.00, + 'expected_payback': 150, + } + req_dscr = { + 'req_noi_dscr': 1.15, + 'req_cash_dscr': 1.15, + 'req_saving_dscr': 1.10 + } + + scenario.prelim_analysis( + prior_month_bill=prior_month_bill, + percent_saving_dict=percent_saving_dict, + full_saving_dict=full_saving_dict, + req_dscr=req_dscr, + customer_preference=customer_preference + ) + + # print('\nscenario_ob.get_economics(),',scenario.get_economics()) + # print('\nscenario_ob.get_graph_dict(),',scenario.get_graph_dict()) + # print('\nscenario_ob.get_prior_income_statement(),',scenario.get_prior_income_statement()[3]) + # print('\nscenario_ob.get_prior_balance_sheet_statement(),',scenario.get_prior_balance_sheet_statement()) + # print('\nscenario_ob.get_post_income_statement(),',scenario.get_post_income_statement()[3]) + # print('\nscenario_ob.get_post_balance_sheet_statement(),',scenario.get_post_balance_sheet_statement()) + # print('\nbudget_plot,',scenario.get_budget_plot()) + # print('\nloan_summary,',scenario.get_loan_summary()) + # print('\ndownpayment',scenario.get_financing_plan()[-1]) + + assert 1==1 + # assert result == outcome + + + def test_scenario_fail(): growth_rate_flag=-2 prior_annual_bill_table, manual_input_dict, prior_month_bill, unsued_display_table = form_annual_bill_table( @@ -128,7 +268,17 @@ def test_scenario_fail(): outcome = db.fail_scenario_outcome + # print('\nscenario_ob.get_economics(),',scenario.get_economics()) + # print('\nscenario_ob.get_graph_dict(),',scenario.get_graph_dict()) + # print('\nscenario_ob.get_prior_income_statement(),',scenario.get_prior_income_statement()[3]) + # print('\nscenario_ob.get_prior_balance_sheet_statement(),',scenario.get_prior_balance_sheet_statement()) + # print('\nscenario_ob.get_post_income_statement(),',scenario.get_post_income_statement()[3]) + # print('\nscenario_ob.get_post_balance_sheet_statement(),',scenario.get_post_balance_sheet_statement()) + # print('\nbudget_plot,',scenario.get_budget_plot()) + # print('\nloan_summary,',scenario.get_loan_summary()) + # print('\ndownpayment',scenario.get_financing_plan()[-1]) assert result == outcome + assert scenario.get_prior_income_statement() == scenario.get_post_income_statement() # import pprint diff --git a/bpfin/tests/testdata/feature_data.py b/bpfin/tests/testdata/feature_data.py index ca63d77a962475d21a78e066f81bb5a6b01033e1..9b0981e6b3d09e55c063e1fd8b4eb6443479c7a7 100644 --- a/bpfin/tests/testdata/feature_data.py +++ b/bpfin/tests/testdata/feature_data.py @@ -1038,6 +1038,14 @@ scenario_outcome = { 'simple_payback': 5.2324047117980035,}, 'financing_plan': [25000.0, 50000.0, 75000.0, 0.0], + 'loan_summary': [ + ['Lender','Amount Borrowed','Amount Upper Limit','Annual Interest Rate','Duration','Monthly Debt Service'], + ['NYSERDA', 25000.0, 500000, 0.08, 120, 303.31898588839437], + ['Joe Fund', 50000.0, 50000, 0.05, 108, 575.8636584182361], + ['Tooraj Capital',75000.0,75000,0.07,114,902.560780798825], + ], + 'budget_plot': (0.46592312148565274, 150000.0), + 'downpayment': 0.0, } @@ -1108,4 +1116,12 @@ fail_scenario_outcome = { 'overall_saving': 0.46592312148565274, 'simple_payback': 5.2324047117980035,}, 'financing_plan': [0, 0, 0, 0], + 'loan_summary': [ + ['Lender', 'Amount Borrowed', 'Amount Upper Limit', 'Annual Interest Rate', 'Duration', 'Monthly Debt Service'], + ['NYSERDA', 0, 500000, 0.08, 12, 0.0], + ['Joe Fund', 0, 50000, 0.05, 24, 0.0], + ['Tooraj Capital', 0, 75000, 0.07, 6, 0.0] + ], + 'budget_plot': (0.46592312148565274, 150000.0), + 'downpayment': 0, } diff --git a/setup.py b/setup.py index 2a0050509eb0e21a7c96ccb0136af26828b062d3..bb10cb66477e7adb8cbfcf41efb6c53ec72de0d0 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ reqs = [str(req.req) for req in install_reqs] setup( name='bpfin', - version='0.2.5', + version='0.2.6', description='Finance models and utilites', author='BlocPower', author_email='admin@blocpower.org',