diff --git a/blocnote/apps/financialInputs/migrations/0002_incomestatement.py b/blocnote/apps/financialInputs/migrations/0002_incomestatement.py
new file mode 100644
index 0000000000000000000000000000000000000000..0f9ce6adc55a65412696af020621529d7db27f9f
--- /dev/null
+++ b/blocnote/apps/financialInputs/migrations/0002_incomestatement.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.6 on 2017-04-27 20:30
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('financialInputs', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='IncomeStatement',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('building_id', models.IntegerField()),
+ ('year', models.DecimalField(decimal_places=0, max_digits=4)),
+ ('revenue', models.DecimalField(decimal_places=2, max_digits=10)),
+ ('utility_expense', models.DecimalField(decimal_places=2, max_digits=10)),
+ ('other_utility_expense', models.DecimalField(decimal_places=2, max_digits=10)),
+ ('non_utility_operating_expense', models.DecimalField(decimal_places=2, max_digits=10)),
+ ],
+ ),
+ ]
diff --git a/blocnote/apps/financialInputs/models.py b/blocnote/apps/financialInputs/models.py
index 16d26d4ee2250e637770260e315026548ee10067..030d735693c38f2d256f93b362629ac929368886 100644
--- a/blocnote/apps/financialInputs/models.py
+++ b/blocnote/apps/financialInputs/models.py
@@ -93,3 +93,18 @@ class CashBalance(models.Model):
statement_date = models.DateField()
is_from_balance_sheet = models.BooleanField(default=False)
balance_amount = models.DecimalField(max_digits=10, decimal_places=2)
+
+
+class IncomeStatement(models.Model):
+ """Store income statement data.
+
+ Store revenue, utility expense, utility expenses other than electricity, gas, oil and water and non-utility
+ expenses for a particular building for a particular year.
+ """
+
+ building_id = models.IntegerField()
+ year = models.DecimalField(max_digits=4, decimal_places=0)
+ revenue = models.DecimalField(max_digits=10, decimal_places=2)
+ utility_expense = models.DecimalField(max_digits=10, decimal_places=2)
+ other_utility_expense = models.DecimalField(max_digits=10, decimal_places=2)
+ non_utility_operating_expense = models.DecimalField(max_digits=10, decimal_places=2)
diff --git a/blocnote/apps/financialInputs/static/financialInputs/scripts/app.js b/blocnote/apps/financialInputs/static/financialInputs/scripts/app.js
index 7b871edaed4b178d398a50641e1af31cff3ed838..83a9488399e1b7f15a5e93c3e1af4590e2e51349 100644
--- a/blocnote/apps/financialInputs/static/financialInputs/scripts/app.js
+++ b/blocnote/apps/financialInputs/static/financialInputs/scripts/app.js
@@ -3,6 +3,7 @@ for (var utility_index in utilities) {
loadInitialBillsTable(utilities[utility_index]);
}
loadBillsOverview();
+getIncomeStatementTable();
getCustomerPreferenceTable();
getLiabilitiesTable();
getCashBalanceForm();
@@ -748,3 +749,304 @@ function createDateComponent(mon, day, yr, num) {
return text;
}
+
+/**
+ * Load income statement table. The column heading are displayed first along with the table body. The growth rate
+ * drop down box is displayed as well.
+ */
+function loadIncomeStatementTable() {
+ loadIncomeStatemenHeading();
+ loadIncomeStatemenBody();
+ loadIncomeStatementDropdownBox('');
+}
+
+/**
+ * Display column heading of the income statement table.
+ */
+function loadIncomeStatemenHeading() {
+ var heading = document.querySelector('#income-statement-table thead');
+ heading.innerHTML = `
+
+
Year
+
+
+
+
Next Year
+
Average
+
+ `;
+}
+
+/**
+ * Display body of the income statement table.
+ */
+function loadIncomeStatemenBody() {
+ var body = document.querySelector('#income-statement-table tbody');
+ body.innerHTML = `
+
+
Revenue
+
+
+
+
+
+
+
+
Utility Expense
+
+
+
+
+
+
+
+
Energy Expense
+
+
+
+
+
+
+
+
Electricity Bill
+
+
+
+
+
+
+
+
Gas Bill
+
+
+
+
+
+
+
+
Oil Bill
+
+
+
+
+
+
+
+
Water Bill
+
+
+
+
+
+
+
+
Other Utility Expense
+
+
+
+
+
+
+
+
Non-Utility Operating Expense
+
+
+
+
+
+
+
+
Net Non-Energy Expense
+
+
+
+
+
+
+
+
Total Expense
+
+
+
+
+
+
+
+
Net Operating Expense
+
+
+
+
+
+
+ `;
+}
+
+/**
+ * Display the growth rate drop down box. This takes in a CAGR value if present. The CAGR value will be passed only
+ * when the calculate button is hit.
+ */
+function loadIncomeStatementDropdownBox(cagr) {
+ dropdownBox = document.querySelector('#income-statement-dropdown-box');
+ var text = ``;
+ text += `
+ Please select Growth Rate
+
+ `;
+ dropdownBox.innerHTML = text;
+}
+
+/**
+ * HTTP GET request to backend. If income statement records already existing, display relevant fields in the table.
+ * Display empty table otherwise.
+ */
+function getIncomeStatementTable() {
+ request(`income-statement/`, {
+ method: 'GET',
+ credentials: 'same-origin',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ }).then(res => {
+ loadIncomeStatementTable();
+ if(res.payload.instance.present) {
+ recordList = res.payload.instance.result;
+ heading = document.querySelector('#income-statement-table-head');
+ body = document.querySelector('#income-statement-table-body');
+ const REVENUE_ROW = 0;
+ const UTILITY_EXPENSE_ROW = 1;
+ const NON_UTILITY_OPERATING_EXPENSE_ROW = 8;
+ for (var index in recordList) {
+ cellIndex = Number(index)+1;
+ heading.rows[0].cells[cellIndex].innerHTML = `
+
+ `;
+ var revenue = recordList[index].revenue;
+ var utilityExpense = recordList[index].utility_expense;
+ var nonUtilityExpense = recordList[index].non_utility_operating_expense;
+ var revenueInput = `
+
+ `;
+ var utilityExpenseInput = `
+
+ `;
+ var nonUtilityExpenseInput = `
+
+ `;
+ updateIncomeStatementTable(REVENUE_ROW, cellIndex, revenueInput);
+ updateIncomeStatementTable(UTILITY_EXPENSE_ROW, cellIndex, utilityExpenseInput);
+ updateIncomeStatementTable(NON_UTILITY_OPERATING_EXPENSE_ROW, cellIndex, nonUtilityExpenseInput);
+ }
+ }
+ });
+}
+
+/**
+ * Fire up when the calculate button is hit. Get all the input data from the table and the growth rate value
+ * and make HTTP PUT request to the backend. Update the table with the calculated data received from the backend.
+ */
+function onCalculateIncomeStatement(data) {
+ var head = document.querySelector('#income-statement-table-head');
+ var body = document.querySelector('#income-statement-table-body');
+ var form = document.querySelector('#income-statement-form');
+ var formData = new FormData(form);
+ var growthRate = formData.get('Growth Rate');
+ var result = [];
+ for (var cellIndex = 1; cellIndex <= 3; cellIndex++) {
+ var record = {};
+ record['year'] = head.rows[0].cells[cellIndex].children[0].value;
+ record['revenue'] = body.rows[0].cells[cellIndex].children[0].value;
+ record['utility-expense'] = body.rows[1].cells[cellIndex].children[0].value;
+ record['non-utility-operating-expense'] = body.rows[8].cells[cellIndex].children[0].value;
+ result.push(record);
+ }
+ result.push({'growth-rate': growthRate});
+ request('income-statement/', {
+ method: 'PUT',
+ credentials: 'same-origin',
+ body: JSON.stringify(result),
+ headers: new Headers({
+ 'Content-Type': 'application/json',
+ 'X-CSRFToken': Cookies.get('csrftoken')
+ })
+ }).then(res => {
+ const REVENUE_ROW = 0;
+ const UTILITY_EXPENSE_ROW = 1;
+ const ENERGY_EXPENSE_ROW = 2;
+ const ELECTRICITY_ROW = 3;
+ const GAS_ROW = 4;
+ const OIL_ROW = 5;
+ const WATER_ROW = 6;
+ const OTHER_UTILITY_EXPENSE_ROW = 7;
+ const NON_UTILITY_OPERATING_EXPENSE_ROW = 8;
+ const NET_NON_ENERGY_EXPENSE_ROW = 9;
+ const TOTAL_EXPENSE_ROW = 10;
+ const NET_OPERATING_EXPENSE = 11;
+ var incomeStatementFull = res.payload.instance;
+ for (key in incomeStatementFull) {
+ cellIndex = Number(key)+1;
+ updateIncomeStatementTable(ENERGY_EXPENSE_ROW, cellIndex, incomeStatementFull[key].energy_opex);
+ updateIncomeStatementTable(ELECTRICITY_ROW, cellIndex, incomeStatementFull[key].electricity_opex);
+ updateIncomeStatementTable(GAS_ROW, cellIndex, incomeStatementFull[key].gas_opex);
+ updateIncomeStatementTable(OIL_ROW, cellIndex, incomeStatementFull[key].oil_opex);
+ updateIncomeStatementTable(WATER_ROW, cellIndex, incomeStatementFull[key].water_opex);
+ updateIncomeStatementTable(OTHER_UTILITY_EXPENSE_ROW, cellIndex, incomeStatementFull[key].other_utility);
+ updateIncomeStatementTable(NET_NON_ENERGY_EXPENSE_ROW, cellIndex, incomeStatementFull[key].net_non_energy_opex);
+ updateIncomeStatementTable(TOTAL_EXPENSE_ROW, cellIndex, incomeStatementFull[key].total_opex);
+ updateIncomeStatementTable(NET_OPERATING_EXPENSE, cellIndex, incomeStatementFull[key].noi);
+ }
+ var future = res.payload.future;
+ const FUTURE_INDEX = 4;
+ heading = document.querySelector('#income-statement-table thead');
+ heading.rows[0].cells[FUTURE_INDEX].innerHTML = future.year;
+ updateIncomeStatementTable(REVENUE_ROW,FUTURE_INDEX,future.revenue);
+ updateIncomeStatementTable(UTILITY_EXPENSE_ROW,FUTURE_INDEX,future.utility_expense);
+ updateIncomeStatementTable(ENERGY_EXPENSE_ROW,FUTURE_INDEX,future.energy_opex);
+ updateIncomeStatementTable(ELECTRICITY_ROW,FUTURE_INDEX,future.electricity_opex);
+ updateIncomeStatementTable(GAS_ROW,FUTURE_INDEX,future.gas_opex);
+ updateIncomeStatementTable(OIL_ROW,FUTURE_INDEX,future.oil_opex);
+ updateIncomeStatementTable(WATER_ROW,FUTURE_INDEX,future.water_opex);
+ updateIncomeStatementTable(OTHER_UTILITY_EXPENSE_ROW,FUTURE_INDEX,future.other_utility);
+ updateIncomeStatementTable(NON_UTILITY_OPERATING_EXPENSE_ROW,FUTURE_INDEX,future.non_utility_expense);
+ updateIncomeStatementTable(NET_NON_ENERGY_EXPENSE_ROW,FUTURE_INDEX,future.net_non_energy_opex);
+ updateIncomeStatementTable(TOTAL_EXPENSE_ROW,FUTURE_INDEX,future.total_opex);
+ updateIncomeStatementTable(NET_OPERATING_EXPENSE,FUTURE_INDEX,future.noi);
+
+ var averageDict = res.payload.average;
+ const AVERAGE_DICT_INDEX = 5;
+ updateIncomeStatementTable(REVENUE_ROW,AVERAGE_DICT_INDEX,averageDict.revenue);
+ updateIncomeStatementTable(UTILITY_EXPENSE_ROW,AVERAGE_DICT_INDEX,averageDict.utility_expense);
+ updateIncomeStatementTable(ENERGY_EXPENSE_ROW,AVERAGE_DICT_INDEX,averageDict.energy_opex);
+ updateIncomeStatementTable(ELECTRICITY_ROW,AVERAGE_DICT_INDEX,averageDict.electricity_opex);
+ updateIncomeStatementTable(GAS_ROW,AVERAGE_DICT_INDEX,averageDict.gas_opex);
+ updateIncomeStatementTable(OIL_ROW,AVERAGE_DICT_INDEX,averageDict.oil_opex);
+ updateIncomeStatementTable(WATER_ROW,AVERAGE_DICT_INDEX,averageDict.water_opex);
+ updateIncomeStatementTable(OTHER_UTILITY_EXPENSE_ROW,AVERAGE_DICT_INDEX,averageDict.other_utility);
+ updateIncomeStatementTable(NON_UTILITY_OPERATING_EXPENSE_ROW,AVERAGE_DICT_INDEX,averageDict.non_utility_expense);
+ updateIncomeStatementTable(NET_NON_ENERGY_EXPENSE_ROW,AVERAGE_DICT_INDEX,averageDict.net_non_energy_opex);
+ updateIncomeStatementTable(TOTAL_EXPENSE_ROW,AVERAGE_DICT_INDEX,averageDict.total_opex);
+ updateIncomeStatementTable(NET_OPERATING_EXPENSE,AVERAGE_DICT_INDEX,averageDict.noi);
+
+ var box = document.querySelector('#growth-rate option');
+ box.innerHTML = `CAGR ${res.payload.CAGR}`;
+ })
+ return false;
+}
+
+/**
+ * Update the income statement table. This takes in the rowIndex, cellIndex and value to be inserted at that cell.
+ */
+function updateIncomeStatementTable(rowIndex, cellIndex, value) {
+ var body = document.querySelector('#income-statement-table tbody');
+ body.rows[rowIndex].cells[cellIndex].innerHTML = value;
+}
diff --git a/blocnote/apps/financialInputs/templates/financialInputs/incomeStatement.html b/blocnote/apps/financialInputs/templates/financialInputs/incomeStatement.html
new file mode 100644
index 0000000000000000000000000000000000000000..f1ce56c4d34af8a8def9b171f847819e387f9bdf
--- /dev/null
+++ b/blocnote/apps/financialInputs/templates/financialInputs/incomeStatement.html
@@ -0,0 +1,22 @@
+
+
Income Statements
+
+
+
+
diff --git a/blocnote/apps/financialInputs/templates/financialInputs/index.html b/blocnote/apps/financialInputs/templates/financialInputs/index.html
index 25174a020214e199257dd30b9e56911c5bade034..1cd3039f5a1f30b7552c28f584dce1dd8877ee8f 100644
--- a/blocnote/apps/financialInputs/templates/financialInputs/index.html
+++ b/blocnote/apps/financialInputs/templates/financialInputs/index.html
@@ -26,6 +26,9 @@
{% include "financialInputs/billsOverview.html" %}
+
+ {% include "financialInputs/incomeStatement.html" %}
+
{% include "financialInputs/cashBalance.html" %}
diff --git a/blocnote/apps/financialInputs/urls.py b/blocnote/apps/financialInputs/urls.py
index 0a0786b2d955a1ac33643c16746046b69f58b7ba..8856aed8d065ed1e90ccf7034c71e7d213bb24e7 100644
--- a/blocnote/apps/financialInputs/urls.py
+++ b/blocnote/apps/financialInputs/urls.py
@@ -10,4 +10,5 @@ urlpatterns = [
url(r'^customer-preference/$', views.CustomerPreferenceView.as_view(), name='customer_preference'),
url(r'^liabilities/$', views.LiabilitiesTable.as_view(), name='liabilities'),
url(r'^cash-balance/$', views.CashBalanceView.as_view(), name='cash_balance'),
+ url(r'^income-statement/$', views.IncomeStatementTable.as_view(), name='income_statement'),
]
diff --git a/blocnote/apps/financialInputs/views.py b/blocnote/apps/financialInputs/views.py
index ea50b691b20d80b64c65d24955c75edb6fec2956..67fc7bf1fba3dc67012e7d05e35dc77b566abf10 100644
--- a/blocnote/apps/financialInputs/views.py
+++ b/blocnote/apps/financialInputs/views.py
@@ -6,9 +6,10 @@ from django.views import View
from datetime import date
from bpfin.utilbills.bill_backend_call import bill_prior_proj_rough_annual
-from bpfin.financials.cash_balance import cash_balance
+from bpfin.financials.financial_lib import organize_bill_overview
+from bpfin.financials.financial_lib import Income_Statement_Table
-from .models import FinancingOverview, Bills, BillsOverview, CustomerPreference, EstimationAlgorithm, Liabilities, CashBalance
+from .models import FinancingOverview, Bills, BillsOverview, CustomerPreference, EstimationAlgorithm, Liabilities, CashBalance, IncomeStatement
from .forms import BlocNoteHeaderForm
@@ -745,3 +746,204 @@ class CashBalanceView(View):
)
return JsonResponse({'instance': 'OK'})
+
+class IncomeStatementTable(View):
+ """Income Statement table.
+
+ Store income statement data. Calculate historical income statement information and one year in the future.
+ Calculate the average of the historical year and the one future year and display in a new column.
+ """
+
+ model = IncomeStatement
+
+ def convert_response_format(self, put):
+ """Convert PUT body format.
+
+ Convert the data in HTTP PUT request into format accepted by bpfin. Obtain the growth rate as well.
+
+ Args:
+ put: HTTP PUT request from frontend.
+
+ Returns:
+ result: Dictionary with year as key and income statement information dictionary as value.
+ growth rate: The selected growth rate to project the future income statement.
+ """
+ result = {}
+ for record in put:
+ if 'growth-rate' not in record:
+ value = {}
+ value['revenue'] = float(record['revenue'])
+ value['utility_expense'] = float(record['utility-expense'])
+ value['non_utility_expense'] = float(record['non-utility-operating-expense'])
+ result[int(record['year'])] = value
+ else:
+ growth_rate = float(record['growth-rate'])
+ return result, growth_rate
+
+ def get_bills_overview_data(self, building_id):
+ """Get Bills overview table data.
+
+ Query the database to get bills overview data.
+
+ Args:
+ building_id: id of the building.
+
+ Returns:
+ bill_overview: A dictionary with utility as key and value a list. This list contains the first element
+ a dictionary with key the year and value the charge for that particular year(actual or
+ projected). The second element is the flag which is true if the utility bill does exist.
+ """
+ objs = BillsOverview.objects.filter(building_id=building_id)
+ bill_overview = {}
+ electricity = {}
+ gas = {}
+ oil = {}
+ water = {}
+ if objs:
+ for obj in objs:
+ electricity[obj.year] = float(obj.electricity)
+ gas[obj.year] = float(obj.gas)
+ oil[obj.year] = float(obj.oil)
+ water[obj.year] = float(obj.water)
+ bill_overview = {
+ 'electricity': [electricity, not obj.electricity_is_user_input],
+ 'gas': [gas, not obj.gas_is_user_input],
+ 'oil': [oil, not obj.oil_is_user_input],
+ 'water': [water, not obj.water_is_user_input],
+ }
+ return bill_overview
+
+ def save(self, result, building_id):
+ """Save income statement data in database.
+
+ Args:
+ result: List of historical income statement data to be stored in the database.
+ building_id: id of the building.
+ """
+ self.model.objects.filter(building_id=building_id).delete()
+ for record in result:
+ self.model.objects.create(
+ building_id=building_id,
+ year=record['year'],
+ revenue=record['revenue'],
+ utility_expense=record['utility_expense'],
+ other_utility_expense=record['other_utility'],
+ non_utility_operating_expense=record['non_utility_expense']
+ )
+
+ def put(self, request, building_id):
+ """Handle HTTP PUT request.
+
+ Receive income statement data from frontend. Convert the format to use in bpfin function. Store result from
+ bpfin logic to the database. Send the historical remaining calculated income statement data, future one year
+ data and average back to the frontend.
+
+ Args:
+ request: HTTP PUT request with the income statement inputs in the body.
+ building_id: id of the building.
+
+ Returns:
+ JsonResponse: Dictionary with key-value as instance with value the historical results, future with future
+ results and average with average results.
+ """
+ put = json.loads(request.body.decode())
+
+ # Convert the response body to the format bpfin accepts.
+ raw_income_statement_input, growth_rate = self.convert_response_format(put)
+
+ # Get bills overview data from the database.
+ bill_overview = self.get_bills_overview_data(building_id)
+
+ # Get the analysis date from the financing overview model.
+ financing_overview_obj = FinancingOverview.objects.get(building_id=building_id)
+ analysis_date = {
+ 'proforma_start': financing_overview_obj.pro_forma_start_date,
+ 'proforma_duration': financing_overview_obj.pro_forma_duration,
+ }
+
+ # organize_bill_overview takes in the bills overview and analysis date and fills in average values in places
+ # where there are no values.
+ bill_overview_organized = organize_bill_overview(bill_overview, analysis_date)
+
+ # income statement table is an object that takes in the income statement input and bill_overview_organized.
+ income_statement_table = Income_Statement_Table(raw_income_statement_input, bill_overview_organized)
+
+ # income_statement_full is the list of records with historical income statement data.
+ income_statement_full = income_statement_table.get_hist_table()
+
+ # cagr is compound annual growth rate.
+ cagr = income_statement_table.get_cagr()
+
+ # project function calculates the income statement data for the next few years based on the growth rate.
+ income_statement_table.project(growth_rate, analysis_date, bill_overview_organized)
+
+ # result stores the historical income statement data as a list.
+ result = [income_statement_full[year] for year in income_statement_full]
+
+ # result_dict has the income statement data for the next year.
+ result_dict = income_statement_table.get_single_year(income_statement_table.hist_end_year + 1)
+
+ # average_dict has the income statement data for the 3 historical years and the next year projected.
+ average_dict = income_statement_table.get_average()
+
+ # save function stores the data in the database.
+ self.save(result, building_id)
+
+ # Change the float formatting to have only 2 decimal places.
+ for record in result:
+ record['energy_opex'] = float("{0:.2f}".format(record['energy_opex']))
+ record['other_utility'] = float("{0:.2f}".format(record['other_utility']))
+ record['net_non_energy_opex'] = float("{0:.2f}".format(record['net_non_energy_opex']))
+ result_dict['energy_opex'] = float("{0:.2f}".format(result_dict['energy_opex']))
+ result_dict['other_utility'] = float("{0:.2f}".format(result_dict['other_utility']))
+ result_dict['net_non_energy_opex'] = float("{0:.2f}".format(result_dict['net_non_energy_opex']))
+ result_dict['revenue'] = float("{0:.2f}".format(result_dict['revenue']))
+ result_dict['utility_expense'] = float("{0:.2f}".format(result_dict['utility_expense']))
+ result_dict['non_utility_expense'] = float("{0:.2f}".format(result_dict['non_utility_expense']))
+ result_dict['total_opex'] = float("{0:.2f}".format(result_dict['total_opex']))
+ result_dict['noi'] = float("{0:.2f}".format(result_dict['noi']))
+
+ average_dict['electricity_opex'] = float("{0:.2f}".format(average_dict['electricity_opex']))
+ average_dict['gas_opex'] = float("{0:.2f}".format(average_dict['gas_opex']))
+ average_dict['oil_opex'] = float("{0:.2f}".format(average_dict['oil_opex']))
+ average_dict['water_opex'] = float("{0:.2f}".format(average_dict['water_opex']))
+ average_dict['energy_opex'] = float("{0:.2f}".format(average_dict['energy_opex']))
+ average_dict['other_utility'] = float("{0:.2f}".format(average_dict['other_utility']))
+ average_dict['net_non_energy_opex'] = float("{0:.2f}".format(average_dict['net_non_energy_opex']))
+ average_dict['revenue'] = float("{0:.2f}".format(average_dict['revenue']))
+ average_dict['utility_expense'] = float("{0:.2f}".format(average_dict['utility_expense']))
+ average_dict['non_utility_expense'] = float("{0:.2f}".format(average_dict['non_utility_expense']))
+ average_dict['total_opex'] = float("{0:.2f}".format(average_dict['total_opex']))
+ average_dict['noi'] = float("{0:.2f}".format(average_dict['noi']))
+
+ cagr = float("{0:.2f}".format(cagr))
+ return JsonResponse({'instance': result, 'future': result_dict, 'average': average_dict, 'CAGR': cagr})
+
+ def get(self, request, building_id):
+ """Handle HTTP GET request.
+
+ Fetch stored income statement data from the database and send to frontend to display.
+
+ Args:
+ request: HTTP GET request.
+ building_id: id of the building.
+
+ Returns:
+ JsonResponse: Instance which contains a list of records. Each record is a dictionary with income
+ statement information from the database.
+ """
+ objs = self.model.objects.filter(building_id=building_id)
+ instance = {}
+ instance['present'] = False
+ if objs:
+ instance['present'] = True
+ result = []
+ for obj in objs:
+ record = {}
+ record['year'] = obj.year
+ record['revenue'] = obj.revenue
+ record['utility_expense'] = obj.utility_expense
+ record['non_utility_operating_expense'] = obj.non_utility_operating_expense
+ result.append(record)
+ instance['result'] = result
+ return JsonResponse({'instance': instance})