From feea329d0d027fb720eb6c90076b09f41fa76c4e Mon Sep 17 00:00:00 2001 From: chen Date: Fri, 15 Mar 2019 11:52:43 -0400 Subject: [PATCH 01/10] Add test_scenario_debug for debug. Same data with dev dataset --- bpfin/tests/test_financials/test_scenario.py | 145 +++++++++++++++++++ 1 file changed, 145 insertions(+) diff --git a/bpfin/tests/test_financials/test_scenario.py b/bpfin/tests/test_financials/test_scenario.py index 1c95e57..4415d19 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,149 @@ 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() + ) + + print('test_scenario_2 ==== ') + print('prior_liability_dict==== ', liability_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 + ) + + result = {} + result['feasibility'] = scenario.get_feasibility() + result['annual_ds'] = scenario.get_annual_debt_service() + result['graph_dict'] = scenario.get_graph_dict() + result['economics'] = scenario.get_economics() + result['financing_plan'] = scenario.get_financing_plan() + + # print('Before #100PR result of financing_plan==', [60000, 5552.02, 947.98]) + # print('#100PR result of financing_plan==', result['financing_plan']) + # print('economics==', result['economics']) + # outcome = db.fail_scenario_outcome + + 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( -- GitLab From 7d26f0cdd79d05fc2e9cdb5e2abecfaf67a90c2f Mon Sep 17 00:00:00 2001 From: chen Date: Fri, 15 Mar 2019 15:55:23 -0400 Subject: [PATCH 02/10] Refactor scenario post I/S and B/S algo. Add test_scenario case with same dataset in dev --- bpfin/financials/scenario.py | 10 ++++-- bpfin/tests/test_financials/test_scenario.py | 33 +++++++++++--------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/bpfin/financials/scenario.py b/bpfin/financials/scenario.py index 613a700..b8725f8 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_financials/test_scenario.py b/bpfin/tests/test_financials/test_scenario.py index 4415d19..8a4575f 100644 --- a/bpfin/tests/test_financials/test_scenario.py +++ b/bpfin/tests/test_financials/test_scenario.py @@ -151,9 +151,6 @@ def test_scenario_debug(): net_income_dictionary=prior_IS_table.get_noi_dict() ) - print('test_scenario_2 ==== ') - print('prior_liability_dict==== ', liability_dict) - scenario = Scenario( analysis_date=analysis_date, commission_date=date(2020,1,31), @@ -197,17 +194,15 @@ def test_scenario_debug(): customer_preference=customer_preference ) - result = {} - result['feasibility'] = scenario.get_feasibility() - result['annual_ds'] = scenario.get_annual_debt_service() - result['graph_dict'] = scenario.get_graph_dict() - result['economics'] = scenario.get_economics() - result['financing_plan'] = scenario.get_financing_plan() - - # print('Before #100PR result of financing_plan==', [60000, 5552.02, 947.98]) - # print('#100PR result of financing_plan==', result['financing_plan']) - # print('economics==', result['economics']) - # 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 1==1 # assert result == outcome @@ -273,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 -- GitLab From 6ac55835ff45a28efad75447a7f95b13f2defe19 Mon Sep 17 00:00:00 2001 From: chen Date: Fri, 15 Mar 2019 18:00:39 -0400 Subject: [PATCH 03/10] moving back_end_prelim uggly test to test file --- bpfin/back_end_call/back_end_prelim.py | 32 ------------------- .../test_back_end_prelim.py | 32 +++++++++++++++++++ 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/bpfin/back_end_call/back_end_prelim.py b/bpfin/back_end_call/back_end_prelim.py index c6ba9bf..7f8449b 100644 --- a/bpfin/back_end_call/back_end_prelim.py +++ b/bpfin/back_end_call/back_end_prelim.py @@ -204,35 +204,3 @@ def prelim_scenario(raw_monthly_bill_table, raw_annual_bill_table, raw_income_in 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() - 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 9be90b1..0bab0a3 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,35 @@ """ To Do we still need to write test files for back_end_call prelim_analysis """ + +# **** 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() + -- GitLab From 99f32c0647047311c21f1a5fac4845690c372eef Mon Sep 17 00:00:00 2001 From: chen Date: Fri, 15 Mar 2019 18:37:01 -0400 Subject: [PATCH 04/10] Write up test_back_end_prelim, with dev case and fail case, unfinished --- .../test_back_end_prelim.py | 186 +++++++++++++++--- 1 file changed, 164 insertions(+), 22 deletions(-) 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 0bab0a3..abb8c09 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,29 +1,171 @@ """ 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) + # 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]) + # print('\neconomics',prelim_result[0]) + result = {} + result['economics'] = prelim_result[0] + 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 + # 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) + + # TODO: complete 2 test cases, and also make sure fail case returns values that can be stored into database/be displayed on front end + print('full fail case ==== ', prelim_result) + print('\neconomics',prelim_result[0]) + result = {} + result['economics'] = prelim_result[0] + outcome = {} + outcome['economics'] = db.fail_scenario_outcome['economics'] + assert result == outcome -# **** 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) -- GitLab From d5566dd8fa0794ba1e31e7efee4bf6561bf91875 Mon Sep 17 00:00:00 2001 From: chen Date: Mon, 18 Mar 2019 18:19:51 -0400 Subject: [PATCH 05/10] Add test data set for fail back_end_call_prelim --- bpfin/back_end_call/back_end_prelim.py | 3 ++- .../test_back_end_call/test_back_end_prelim.py | 17 ++++++++++++++--- bpfin/tests/testdata/feature_data.py | 8 ++++++++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/bpfin/back_end_call/back_end_prelim.py b/bpfin/back_end_call/back_end_prelim.py index 7f8449b..0f0ec76 100644 --- a/bpfin/back_end_call/back_end_prelim.py +++ b/bpfin/back_end_call/back_end_prelim.py @@ -201,6 +201,7 @@ def prelim_scenario(raw_monthly_bill_table, raw_annual_bill_table, raw_income_in scenario_ob.get_post_balance_sheet_statement(), budget_plot, loan_summary, - downpayment + downpayment, + scenario_ob.get_feasibility(), ) 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 abb8c09..986bf92 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 @@ -114,6 +114,8 @@ def test_back_end_prelim_dev(): full_saving_dict=full_saving_dict, req_dscr=req_dscr, customer_preference=customer_preference) + # TODO: complete 2 test cases, and also make sure fail case returns values that can be stored into database/be displayed on front end + # 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]) @@ -157,13 +159,22 @@ def test_back_end_prelim_fail(): req_dscr=db.req_dscr, customer_preference=db.fail_customer_preference) - # TODO: complete 2 test cases, and also make sure fail case returns values that can be stored into database/be displayed on front end - print('full fail case ==== ', prelim_result) - print('\neconomics',prelim_result[0]) result = {} result['economics'] = prelim_result[0] + result['graph_dict'] = prelim_result[1] + result['feasibility'] = prelim_result[9] + result['loan_summary'] = prelim_result[7] + result['budget_plot'] = prelim_result[6] + result['downpayment'] = prelim_result[8] 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[2] == prelim_result[4] + assert prelim_result[3] == prelim_result[5] assert result == outcome diff --git a/bpfin/tests/testdata/feature_data.py b/bpfin/tests/testdata/feature_data.py index ca63d77..9673c69 100644 --- a/bpfin/tests/testdata/feature_data.py +++ b/bpfin/tests/testdata/feature_data.py @@ -1108,4 +1108,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, } -- GitLab From d2686b0b54a472c94c7dc3591e260e8289426516 Mon Sep 17 00:00:00 2001 From: chen Date: Tue, 26 Mar 2019 17:45:55 -0400 Subject: [PATCH 06/10] Add test_back_end_prelim_1, with feature data updated --- .../test_back_end_prelim.py | 49 ++++++++++++++----- bpfin/tests/testdata/feature_data.py | 8 +++ 2 files changed, 44 insertions(+), 13 deletions(-) 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 986bf92..475dbb3 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 @@ -114,18 +114,7 @@ def test_back_end_prelim_dev(): full_saving_dict=full_saving_dict, req_dscr=req_dscr, customer_preference=customer_preference) - # TODO: complete 2 test cases, and also make sure fail case returns values that can be stored into database/be displayed on front end - - # 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]) - # print('\neconomics',prelim_result[0]) + result = {} result['economics'] = prelim_result[0] outcome = {} @@ -139,7 +128,6 @@ def test_back_end_prelim_dev(): 'min_cash_dscr': 3.219949472736734, } assert result==outcome - # assert result == outcome def test_back_end_prelim_fail(): @@ -178,6 +166,41 @@ def test_back_end_prelim_fail(): 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[0] + result['graph_dict'] = prelim_result[1] + result['feasibility'] = prelim_result[9] + result['loan_summary'] = prelim_result[7] + result['budget_plot'] = prelim_result[6] + result['downpayment'] = prelim_result[8] + 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) diff --git a/bpfin/tests/testdata/feature_data.py b/bpfin/tests/testdata/feature_data.py index 9673c69..9b0981e 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, } -- GitLab From 53f1238453781c7c1beb3b85383e710609999301 Mon Sep 17 00:00:00 2001 From: chen Date: Wed, 3 Apr 2019 11:21:47 -0400 Subject: [PATCH 07/10] Update bpfin v0.2.6 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 2a00505..bb10cb6 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', -- GitLab From 2b37cc75f6a0597e683aad42d06c80676e0dbdb7 Mon Sep 17 00:00:00 2001 From: chen Date: Wed, 3 Apr 2019 15:15:03 -0400 Subject: [PATCH 08/10] Refactor back_end_prelim, returns dictionary --- bpfin/back_end_call/back_end_prelim.py | 48 ++++++++++++++------------ 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/bpfin/back_end_call/back_end_prelim.py b/bpfin/back_end_call/back_end_prelim.py index 0f0ec76..18e1188 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 + 'graphic_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, @@ -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,17 +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, - scenario_ob.get_feasibility(), - ) + return { + 'economics': scenario_ob.get_economics(), + 'graphic_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(), + } -- GitLab From 3bc5183b74bc19054e908e3241e21461be762cf9 Mon Sep 17 00:00:00 2001 From: chen Date: Wed, 3 Apr 2019 15:48:33 -0400 Subject: [PATCH 09/10] Update test file with new return of dict --- bpfin/back_end_call/back_end_prelim.py | 4 +-- .../test_back_end_prelim.py | 30 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/bpfin/back_end_call/back_end_prelim.py b/bpfin/back_end_call/back_end_prelim.py index 18e1188..3204279 100644 --- a/bpfin/back_end_call/back_end_prelim.py +++ b/bpfin/back_end_call/back_end_prelim.py @@ -38,7 +38,7 @@ def prelim_scenario(raw_monthly_bill_table, raw_annual_bill_table, raw_income_in dict of items: { 'economics' (dictionary): overview of project economics of this scenario, see description - 'graphic_dict' (dictionary): dict of dict, showcase energy saving, energy debt service, net savings, 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 @@ -198,7 +198,7 @@ def prelim_scenario(raw_monthly_bill_table, raw_annual_bill_table, raw_income_in return { 'economics': scenario_ob.get_economics(), - 'graphic_dict': scenario_ob.get_graph_dict(), + 'graph_dict': scenario_ob.get_graph_dict(), 'budget_plot': budget_plot, 'loan_summary': loan_summary, 'downpayment': downpayment, 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 475dbb3..4d0e507 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 @@ -116,7 +116,7 @@ def test_back_end_prelim_dev(): customer_preference=customer_preference) result = {} - result['economics'] = prelim_result[0] + result['economics'] = prelim_result['economics'] outcome = {} outcome['economics'] = { 'estimated_cost': 66500.0, @@ -148,12 +148,12 @@ def test_back_end_prelim_fail(): customer_preference=db.fail_customer_preference) result = {} - result['economics'] = prelim_result[0] - result['graph_dict'] = prelim_result[1] - result['feasibility'] = prelim_result[9] - result['loan_summary'] = prelim_result[7] - result['budget_plot'] = prelim_result[6] - result['downpayment'] = prelim_result[8] + 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'] @@ -161,8 +161,8 @@ def test_back_end_prelim_fail(): 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[2] == prelim_result[4] - assert prelim_result[3] == prelim_result[5] + assert prelim_result['prior_is'] == prelim_result['post_is'] + assert prelim_result['prior_bs'] == prelim_result['post_bs'] assert result == outcome @@ -184,12 +184,12 @@ def test_back_end_prelim_1(): customer_preference=db.customer_preference) result = {} - result['economics'] = prelim_result[0] - result['graph_dict'] = prelim_result[1] - result['feasibility'] = prelim_result[9] - result['loan_summary'] = prelim_result[7] - result['budget_plot'] = prelim_result[6] - result['downpayment'] = prelim_result[8] + 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'] -- GitLab From 783b7dbba34d9a49da18b855a9e0b564a3d2795b Mon Sep 17 00:00:00 2001 From: chen Date: Wed, 3 Apr 2019 15:50:17 -0400 Subject: [PATCH 10/10] minor update of description file --- bpfin/back_end_call/back_end_prelim.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bpfin/back_end_call/back_end_prelim.py b/bpfin/back_end_call/back_end_prelim.py index 3204279..ba93bcb 100644 --- a/bpfin/back_end_call/back_end_prelim.py +++ b/bpfin/back_end_call/back_end_prelim.py @@ -99,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, ...} -- GitLab