diff --git a/blocnote/apps/preliminaryFinance/static/preliminaryFinance/scripts/app.js b/blocnote/apps/preliminaryFinance/static/preliminaryFinance/scripts/app.js
index f1de81d1b9b54a09011c66b646544de293f8a077..74ea41d226185d3ec1a58fbcbff140663999aa80 100644
--- a/blocnote/apps/preliminaryFinance/static/preliminaryFinance/scripts/app.js
+++ b/blocnote/apps/preliminaryFinance/static/preliminaryFinance/scripts/app.js
@@ -1,4 +1,3 @@
-var tabCounter = 1;
costEstimationTableHead();
costEstimationTableBody();
savingEstimationTableHead();
@@ -8,161 +7,161 @@ savingEstimationTableBody();
* Return the Scenario name.
*/
function getScenarioName() {
- var docs = document.querySelector("a.nav-link.active input");
- return docs.value;
+ const docs = document.querySelector('a.nav-link.active input');
+ return docs.value;
}
/**
* Add column headings to the Cost Estimation table.
*/
function costEstimationTableHead() {
- head = document.querySelector('#cost-estimation-table thead');
- head.innerHTML = `
-
- | Item |
- Estimated Cost (in $) |
- Option |
-
- `;
+ const head = document.querySelector('#cost-estimation-table thead');
+ head.innerHTML = `
+
+ | Item |
+ Estimated Cost (in $) |
+ Option |
+
+ `;
}
/**
* Load the Cost Estimation table body.
*/
function costEstimationTableBody() {
- body = document.querySelector('#cost-estimation-table tbody');
- var rowCount = body.rows.length;
- var row = body.insertRow(rowCount);
- var cell = row.insertCell(0);
- cell.innerHTML = ``;
- cell = row.insertCell(1);
- cell.innerHTML = `$`;
- cell = row.insertCell(2);
- cell.innerHTML = ``;
- return false;
+ const body = document.querySelector('#cost-estimation-table tbody');
+ const rowCount = body.rows.length;
+ const row = body.insertRow(rowCount);
+ let cell = row.insertCell(0);
+ cell.innerHTML = '';
+ cell = row.insertCell(1);
+ cell.innerHTML = '$';
+ cell = row.insertCell(2);
+ cell.innerHTML = '';
+ return false;
}
/**
* Delete a row in Cost Estimation table.
*/
function deleteCostEstimationRow(rowIndex) {
- table = document.querySelector('#cost-estimation-table tbody');
- var result = confirm('ARE YOU SURE YOU WANT TO DELETE THIS ROW?');
- if (result) {
- var rowCount = table.rows.length;
- if (rowCount === 1) {
- alert('YOU NEED ATLEAST ONE ITEM WITH ITS COST ESTIMATION!');
- return false;
- }
- body.deleteRow(rowIndex-1);
+ const table = document.querySelector('#cost-estimation-table tbody');
+ const result = confirm('ARE YOU SURE YOU WANT TO DELETE THIS ROW?');
+ if (result) {
+ const rowCount = table.rows.length;
+ if (rowCount === 1) {
+ alert('YOU NEED ATLEAST ONE ITEM WITH ITS COST ESTIMATION!');
+ return false;
}
- return false;
+ table.deleteRow(rowIndex-1);
+ }
+ return false;
}
/**
* Display column headings in Savings Estimation Table.
*/
function savingEstimationTableHead() {
- head = document.querySelector('#saving-estimation-table thead');
- head.innerHTML = `
-
- | Utility |
- Estimated Savings (in %) |
- Used Before Retrofit |
- Used After Retrofit |
-
- `;
+ const head = document.querySelector('#saving-estimation-table thead');
+ head.innerHTML = `
+
+ | Utility |
+ Estimated Savings (in %) |
+ Used Before Retrofit |
+ Used After Retrofit |
+
+ `;
}
/**
* Load Savings Estimation Table body.
*/
function savingEstimationTableBody() {
- body = document.querySelector('#saving-estimation-table tbody');
- var rowCount = body.rows.length;
- var row = body.insertRow(rowCount);
- var cell = row.insertCell(0);
- cell.innerHTML = `Electricity`;
- cell = row.insertCell(1);
- cell.innerHTML = `
- %
- `;
- cell = row.insertCell(2);
- cell.innerHTML = `
-
- `;
- cell = row.insertCell(3);
- cell.innerHTML = `
-
- `;
+ const body = document.querySelector('#saving-estimation-table tbody');
+ let rowCount = body.rows.length;
+ let row = body.insertRow(rowCount);
+ let cell = row.insertCell(0);
+ cell.innerHTML = 'Electricity';
+ cell = row.insertCell(1);
+ cell.innerHTML = `
+ %
+ `;
+ cell = row.insertCell(2);
+ cell.innerHTML = `
+
+ `;
+ cell = row.insertCell(3);
+ cell.innerHTML = `
+
+ `;
- rowCount += 1;
- row = body.insertRow(rowCount);
- cell = row.insertCell(0);
- cell.innerHTML = `Gas`;
- cell = row.insertCell(1);
- cell.innerHTML = `
- %
- `;
- cell = row.insertCell(2);
- cell.innerHTML = `
-
- `;
- cell = row.insertCell(3);
- cell.innerHTML = `
-
- `;
+ rowCount += 1;
+ row = body.insertRow(rowCount);
+ cell = row.insertCell(0);
+ cell.innerHTML = 'Gas';
+ cell = row.insertCell(1);
+ cell.innerHTML = `
+ %
+ `;
+ cell = row.insertCell(2);
+ cell.innerHTML = `
+
+ `;
+ cell = row.insertCell(3);
+ cell.innerHTML = `
+
+ `;
- rowCount += 1;
- row = body.insertRow(rowCount);
- cell = row.insertCell(0);
- cell.innerHTML = `Oil`;
- cell = row.insertCell(1);
- cell.innerHTML = `
- %
- `;
- cell = row.insertCell(2);
- cell.innerHTML = `
-
- `;
- cell = row.insertCell(3);
- cell.innerHTML = `
-
- `;
+ rowCount += 1;
+ row = body.insertRow(rowCount);
+ cell = row.insertCell(0);
+ cell.innerHTML = 'Oil';
+ cell = row.insertCell(1);
+ cell.innerHTML = `
+ %
+ `;
+ cell = row.insertCell(2);
+ cell.innerHTML = `
+
+ `;
+ cell = row.insertCell(3);
+ cell.innerHTML = `
+
+ `;
- rowCount += 1;
- row = body.insertRow(rowCount);
- cell = row.insertCell(0);
- cell.innerHTML = `Water`;
- cell = row.insertCell(1);
- cell.innerHTML = `
- %
- `;
- cell = row.insertCell(2);
- cell.innerHTML = `
-
- `;
- cell = row.insertCell(3);
- cell.innerHTML = `
-
- `;
- return false;
+ rowCount += 1;
+ row = body.insertRow(rowCount);
+ cell = row.insertCell(0);
+ cell.innerHTML = 'Water';
+ cell = row.insertCell(1);
+ cell.innerHTML = `
+ %
+ `;
+ cell = row.insertCell(2);
+ cell.innerHTML = `
+
+ `;
+ cell = row.insertCell(3);
+ cell.innerHTML = `
+
+ `;
+ return false;
}
/**
@@ -170,72 +169,72 @@ function savingEstimationTableBody() {
* Upon getting response, display Project Economics table and Energy Expense Savings Projection graph.
*/
function submitScenario() {
- var scenarioName = getScenarioName();
- var savingEstimationBody = document.querySelector('#saving-estimation-table tbody');
- var rowCount = savingEstimationBody.rows.length;
-
- // Package savings estimate into a list of dictionaries.
- savings = [];
- for (var rowIndex=0; rowIndex < rowCount; rowIndex++){
- beforeRetrofit = false;
- afterRetrofit = false;
- record = {};
- checkBoxes = savingEstimationBody.rows[rowIndex].querySelectorAll('input[type="checkbox"]:checked');
- for (index = 0; index < checkBoxes.length; index++) {
- checkbox = checkBoxes[index];
- if (checkbox.name === 'Used before retrofit') {
- beforeRetrofit = true;
- }
- if (checkbox.name === 'Used after retrofit') {
- afterRetrofit = true;
- }
- }
- if (Number(savingEstimationBody.rows[rowIndex].cells[1].children[0].value) > 100) {
- alert(`Please enter a valid savings percentage for ${savingEstimationBody.rows[rowIndex].cells[0].innerHTML}`);
- return false;
- }
+ const scenarioName = getScenarioName();
+ const savingEstimationBody = document.querySelector('#saving-estimation-table tbody');
+ let rowCount = savingEstimationBody.rows.length;
- record = {
- 'utility_type': savingEstimationBody.rows[rowIndex].cells[0].innerHTML,
- 'savings_estimate': savingEstimationBody.rows[rowIndex].cells[1].children[0].value,
- 'used_before_retrofit': beforeRetrofit,
- 'used_after_retrofit': afterRetrofit,
- }
- savings.push(record);
+ // Package savings estimate into a list of dictionaries.
+ let savings = [];
+ for (let rowIndex=0; rowIndex < rowCount; rowIndex++){
+ let beforeRetrofit = false;
+ let afterRetrofit = false;
+ let record = {};
+ const checkBoxes = savingEstimationBody.rows[rowIndex].querySelectorAll('input[type="checkbox"]:checked');
+ for (let index = 0; index < checkBoxes.length; index++) {
+ let checkbox = checkBoxes[index];
+ if (checkbox.name === 'Used before retrofit') {
+ beforeRetrofit = true;
+ }
+ if (checkbox.name === 'Used after retrofit') {
+ afterRetrofit = true;
+ }
+ }
+ if (Number(savingEstimationBody.rows[rowIndex].cells[1].children[0].value) > 100) {
+ alert(`Please enter a valid savings percentage for ${savingEstimationBody.rows[rowIndex].cells[0].innerHTML}`);
+ return false;
}
- var costEstimationBody = document.querySelector('#cost-estimation-table tbody');
- rowCount = costEstimationBody.rows.length;
- const ITEM_INDEX = 0;
- const COST_INDEX = 1;
+ record = {
+ 'utility_type': savingEstimationBody.rows[rowIndex].cells[0].innerHTML,
+ 'estimated_savings': savingEstimationBody.rows[rowIndex].cells[1].children[0].value,
+ 'used_before_retrofit': beforeRetrofit,
+ 'used_after_retrofit': afterRetrofit,
+ };
+ savings.push(record);
+ }
- // Package cost estimation into a list of dictionaries.
- var cost = [];
- for (rowIndex = 0; rowIndex < rowCount; rowIndex++) {
- record = {
- 'item': costEstimationBody.rows[rowIndex].cells[ITEM_INDEX].children[0].value,
- 'cost': costEstimationBody.rows[rowIndex].cells[COST_INDEX].children[0].value,
- };
- cost.push(record);
- }
- result = {
- 'scenario': scenarioName,
- 'savings': savings,
- 'cost': cost,
- }
- request(`scenario/`, {
- method: 'PUT',
- credentials: 'same-origin',
- body: JSON.stringify(result),
- headers: new Headers({
- 'Content-Type': 'application/json',
- 'X-CSRFToken': Cookies.get('csrftoken')
- })
- }).then(res => {
- loadProjectEconomicsTable(res)
- loadGraph(res);
- });
- return false;
+ const costEstimationBody = document.querySelector('#cost-estimation-table tbody');
+ rowCount = costEstimationBody.rows.length;
+ const ITEM_INDEX = 0;
+ const COST_INDEX = 1;
+
+ // Package cost estimation into a list of dictionaries.
+ const cost = [];
+ for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
+ let record = {
+ 'item': costEstimationBody.rows[rowIndex].cells[ITEM_INDEX].children[0].value,
+ 'cost': costEstimationBody.rows[rowIndex].cells[COST_INDEX].children[0].value,
+ };
+ cost.push(record);
+ }
+ const result = {
+ 'scenario': scenarioName,
+ 'savings': savings,
+ 'cost': cost,
+ };
+ request('scenario/', {
+ method: 'PUT',
+ credentials: 'same-origin',
+ body: JSON.stringify(result),
+ headers: new Headers({
+ 'Content-Type': 'application/json',
+ 'X-CSRFToken': Cookies.get('csrftoken')
+ })
+ }).then(res => {
+ loadProjectEconomicsTable(res);
+ loadGraph(res);
+ });
+ return false;
}
/**
@@ -243,75 +242,73 @@ function submitScenario() {
* analysis that gives vital information about the financial health of the building.
*/
function loadProjectEconomicsTable(res) {
- var doc = document.querySelector('#project-economics');
- var title = document.querySelector('#project-economics-title');
- title.innerHTML = `Project Economics`
- var economicsOverview = res.payload.economics_overview;
- var body = document.querySelector('#project-economics-table tbody');
- addPERow(body, economicsOverview);
+ const title = document.querySelector('#project-economics-title');
+ title.innerHTML = 'Project Economics';
+ const economicsOverview = res.payload.economics_overview;
+ const body = document.querySelector('#project-economics-table tbody');
+ addPERow(body, economicsOverview);
}
/**
* Add rows to the project economics table.
*/
function addPERow(body, economicsOverview) {
- body.innerHTML = ``;
- for (var key in economicsOverview){
- rowCount = body.rows.length;
- row = body.insertRow(rowCount);
- cell = row.insertCell(0);
- cell.innerHTML = `${key}`;
- cell = row.insertCell(1);
- cell.innerHTML = `${economicsOverview[key]}`;
- }
+ body.innerHTML = '';
+ for (let key in economicsOverview){
+ let rowCount = body.rows.length;
+ let row = body.insertRow(rowCount);
+ let cell = row.insertCell(0);
+ cell.innerHTML = `${key}`;
+ cell = row.insertCell(1);
+ cell.innerHTML = `${economicsOverview[key]}`;
+ }
}
/**
* Load the Energy Expense Savings Projection stacked bar graph.
*/
function loadGraph(res) {
- var graph = document.querySelector('#savings-schedule');
- graph.innerHTML = `
-
-
-
- `;
- var config = {
+ const graph = document.querySelector('#savings-schedule');
+ graph.innerHTML = `
+
+
+
+ `;
+ const config = {
+ type: 'bar',
+ data: {
+ labels: res.payload.year_list,
+ datasets: [{
type: 'bar',
- data: {
- labels: res.payload.year_list,
- datasets: [{
- type: 'bar',
- label: 'Energy Expense',
- backgroundColor: "#66B2FF",
- data: res.payload.energy_expense_list,
- }, {
- type: 'bar',
- label: 'Total Loan',
- backgroundColor: "#E0E0E0",
- data: res.payload.total_loan_list,
- }, {
- type: 'bar',
- label: 'Net Savings',
- backgroundColor: "#99FF99",
- data: res.payload.net_savings_list,
- }]
- },
- options: {
- scales: {
- xAxes: [{
- stacked: true
- }],
- yAxes: [{
- stacked: true
- }]
- }
- }
- };
- var doc = document.querySelector('#savings-schedule');
- var title = document.querySelector('#savings-schedule-title');
- title.innerHTML = 'Energy Expense Savings Projection';
- var ctx = document.getElementById("myChart").getContext("2d");
- new Chart(ctx, config);
+ label: 'Energy Expense',
+ backgroundColor: '#66B2FF',
+ data: res.payload.energy_expense_list,
+ }, {
+ type: 'bar',
+ label: 'Total Loan',
+ backgroundColor: '#E0E0E0',
+ data: res.payload.total_loan_list,
+ }, {
+ type: 'bar',
+ label: 'Net Savings',
+ backgroundColor: '#99FF99',
+ data: res.payload.net_savings_list,
+ }]
+ },
+ options: {
+ scales: {
+ xAxes: [{
+ stacked: true
+ }],
+ yAxes: [{
+ stacked: true
+ }]
+ }
+ }
+ };
+ const title = document.querySelector('#savings-schedule-title');
+ title.innerHTML = 'Energy Expense Savings Projection';
+ const ctx = document.getElementById('myChart').getContext('2d');
+ new Chart(ctx, config);
}
diff --git a/blocnote/apps/preliminaryFinance/views.py b/blocnote/apps/preliminaryFinance/views.py
index ea789de4f61f401d11cf9accea3e68be5f8066f7..d5c7800f0b372977294a46674e11bbaec778e836 100644
--- a/blocnote/apps/preliminaryFinance/views.py
+++ b/blocnote/apps/preliminaryFinance/views.py
@@ -9,6 +9,7 @@ from blocnote.lib.fetch_data import (
get_liabilities, get_cash_balance, get_financing_overview, get_utility_bill, get_annual_bills, get_income_statement,
get_loan_options, get_growth_rate, get_customer_preference, get_building_data
)
+from blocnote.apps.preliminaryFinance.models import Scenario, CostEstimation, SavingsEstimation
from bpfin.back_end_call.back_end_prelim import prelim_scenario
def get_savings_percent(savings):
@@ -22,7 +23,7 @@ def get_savings_percent(savings):
"""
savings_percent = {}
for record in savings:
- savings_percent[str.lower(record['utility_type'])] = float(record['savings_estimate'])/100
+ savings_percent[str.lower(record['utility_type'])] = float(record['estimated_savings'])/100
return savings_percent
class Index(View):
@@ -52,6 +53,34 @@ class Scenarios(View):
to bpfin to calculate all the outputs to be displayed and pass the information to the frontend.
"""
+ def save_scenario(self, scenario_details, cost_list, savings):
+ """Save given scenario for the building id.
+
+ Take the scenario details and save it in the database. This will create or update a scenario as we are working
+ with one scenario right now. This will change in the future to keep storing new scenarios.
+
+ Args:
+ scenario_details (Dictionary): This contains the scenario details in the form of a dictionary.
+ """
+ scenario_obj = Scenario.objects.update_or_create(
+ building_id=scenario_details['building_id'],
+ defaults=scenario_details,
+ )
+ CostEstimation.objects.filter(scenario_id=scenario_obj[0].id).delete()
+ for cost in cost_list:
+ cost_estimation = {
+ 'scenario_id': scenario_obj[0].id,
+ 'item': cost['item'],
+ 'cost': float(cost['cost']),
+ }
+ # CostEstimation.objects.create(cost_estimation)
+ cost_obj = CostEstimation(**cost_estimation)
+ cost_obj.save()
+ SavingsEstimation.objects.filter(scenario_id=scenario_obj[0].id).delete()
+ for record in savings:
+ record['estimated_savings'] = float(record['estimated_savings'])/100
+ record['scenario_id'] = scenario_obj[0].id
+ SavingsEstimation.objects.create(**record)
def put(self, request, building_id):
"""Handle HTTP PUT request.
@@ -149,6 +178,20 @@ class Scenarios(View):
'Minimum NOI DSCR': float("{0:.2f}".format(project_economics_overview['min_noi_dscr'])),
'Minimum Cash DSCR': float("{0:.2f}".format(project_economics_overview['min_cash_dscr'])),
}
+ scenario_details = {
+ 'building_id': building_id,
+ 'name': put['scenario'],
+ 'analysis_level': 'prelim',
+ 'estimated_cost': project_economics_overview['estimated_cost'],
+ 'overall_savings': project_economics_overview['overall_saving'],
+ 'first_year_savings': project_economics_overview['first_year_saving'],
+ 'simple_payback': project_economics_overview['simple_payback'],
+ 'min_savings_dscr': project_economics_overview['min_saving_dscr'],
+ 'min_net_operating_income_dscr': 1.5, # TODO: Hard-coded for now. Will be implemented soon.
+ 'min_cash_dscr': project_economics_overview['min_cash_dscr'],
+ 'self_finance_amount': 0, # TODO: Hard-coded for now. Will be implemented soon.
+ }
+ self.save_scenario(scenario_details, cost_list, put['savings'])
return JsonResponse({
'year_list': year_list,
'energy_expense_list': energy_expense_list,