diff --git a/blocnote/apps/financialInputs/migrations/0005_auto_20170522_1842.py b/blocnote/apps/financialInputs/migrations/0005_auto_20170522_1842.py new file mode 100644 index 0000000000000000000000000000000000000000..f8393e6b6b56e0b31228f6bd62b390bb31f21f1b --- /dev/null +++ b/blocnote/apps/financialInputs/migrations/0005_auto_20170522_1842.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.6 on 2017-05-22 18:42 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('financialInputs', '0004_growthrate'), + ] + + operations = [ + migrations.AlterField( + model_name='billsoverview', + name='electricity', + field=models.DecimalField(decimal_places=2, max_digits=10, null=True), + ), + migrations.AlterField( + model_name='billsoverview', + name='gas', + field=models.DecimalField(decimal_places=2, max_digits=10, null=True), + ), + migrations.AlterField( + model_name='billsoverview', + name='oil', + field=models.DecimalField(decimal_places=2, max_digits=10, null=True), + ), + migrations.AlterField( + model_name='billsoverview', + name='water', + field=models.DecimalField(decimal_places=2, max_digits=10, null=True), + ), + ] diff --git a/blocnote/apps/financialInputs/models.py b/blocnote/apps/financialInputs/models.py index 78a76d8ec1ef2429e355952186c05bbb3aebdc91..7a994e3cd140fc005bbd8bad6e2ab529bde953fa 100644 --- a/blocnote/apps/financialInputs/models.py +++ b/blocnote/apps/financialInputs/models.py @@ -54,13 +54,13 @@ class BillsOverview(models.Model): building_id = models.IntegerField() year = models.DecimalField(max_digits=4, decimal_places=0) - electricity = models.DecimalField(max_digits=10, decimal_places=2) + electricity = models.DecimalField(max_digits=10, decimal_places=2, null=True) electricity_is_user_input = models.BooleanField(default=False) - water = models.DecimalField(max_digits=10, decimal_places=2) + water = models.DecimalField(max_digits=10, decimal_places=2, null=True) water_is_user_input = models.BooleanField(default=False) - oil = models.DecimalField(max_digits=10, decimal_places=2) + oil = models.DecimalField(max_digits=10, decimal_places=2, null=True) oil_is_user_input = models.BooleanField(default=False) - gas = models.DecimalField(max_digits=10, decimal_places=2) + gas = models.DecimalField(max_digits=10, decimal_places=2, null=True) gas_is_user_input = models.BooleanField(default=False) diff --git a/blocnote/apps/financialInputs/static/financialInputs/scripts/app.js b/blocnote/apps/financialInputs/static/financialInputs/scripts/app.js index fd36648b3eb45d838d4e142ae334b5c9b3094632..0bc6e05dff5e24e6e1ccad9e002c638783abeaec 100644 --- a/blocnote/apps/financialInputs/static/financialInputs/scripts/app.js +++ b/blocnote/apps/financialInputs/static/financialInputs/scripts/app.js @@ -387,6 +387,9 @@ function createBillsOverviewTableCellInput(id, state, value, year) { if (!state) { is_readonly = `readonly`; } + if (value === null) { + value = ''; + } text = ``; return text; } @@ -412,13 +415,14 @@ function createBillsOverviewRows(data) { ${utility} `; - for (var year in data[utility]) { + for (var year in data[utility]) { text += ` ($)${createBillsOverviewTableCellInput(utility, data[user_input], data[utility][year], year)} `; - } + } + text += ` `; @@ -430,7 +434,7 @@ function createBillsOverviewRows(data) { `; for (var charge in data['total_annual_charge']) { text += ` - $${data['total_annual_charge'][charge]} + $${Number(data['total_annual_charge'][charge].toFixed(2))} `; } text += ` @@ -566,7 +570,7 @@ function billsOverviewFormSubmit(form) { totalCharge.push(val); } for (var cellIndex = 2; cellIndex < columnLength; cellIndex++) { - billsOverviewTable.rows[4].cells[cellIndex].innerHTML = totalCharge[cellIndex - 2]; + billsOverviewTable.rows[4].cells[cellIndex].innerHTML = `$${Number(totalCharge[cellIndex - 2].toFixed(2))}`; } }); return false; diff --git a/blocnote/apps/financialInputs/views.py b/blocnote/apps/financialInputs/views.py index 76770bd9f1e2f711c5b68cb43b98242e1b49eeca..3d69d6be5ebe999f2e9da49a50744eebb6fef1a4 100644 --- a/blocnote/apps/financialInputs/views.py +++ b/blocnote/apps/financialInputs/views.py @@ -7,10 +7,9 @@ from django.http import JsonResponse from django.db import connections from django.views import View -from bpfin.utilbills.bill_backend_call import bill_prior_proj_rough_annual from bpfin.financials.financial_lib import organize_bill_overview from bpfin.financials.financial_lib import Income_Statement_Table - +from bpfin.lib.back_end_call import monthly_bill from .models import Fund, FinancingOverview, Bills, BillsOverview, CustomerPreference, EstimationAlgorithm from .models import Liabilities, CashBalance, IncomeStatement, LoanOptions, DefaultLoan, Lender, GrowthRate @@ -313,70 +312,6 @@ class BillsTable(View): return JsonResponse({'result': result, 'present': present}) -def get_total_charge(utility_type, analysis_date, building_id): - """Get annual total utility charge. - - Obtain annual charge for a utility for every year from the Pro Forma start year till end year. Make calls to bpfin - to perform the tasks. - - Args: - utility_type: Which utility type. - analysis_date: Dictionary containing the Pro Forma start date and duration. - building_id: id of the building. - - Returns: - annual_bill: Dictionary with year as keys and the annual charge for that year as value. - """ - bills_object = Bills.objects.filter( - building_id=building_id, - utility_type=utility_type, - ) - - if bills_object: - raw_bill = {} - raw_bill['utility_type'] = utility_type - raw_bill['date_from'] = [] - raw_bill['date_to'] = [] - raw_bill['charge'] = [] - raw_bill['usage'] = [] - - for bill in bills_object: - raw_bill['date_from'].append(bill.date_from) - raw_bill['date_to'].append(bill.date_to) - raw_bill['usage'].append(float(bill.usage)) - raw_bill['charge'].append(float(bill.charge)) - annual_bill = bill_prior_proj_rough_annual(raw_bill, analysis_date) - else: - annual_bill = {} - objs = BillsOverview.objects.filter( - building_id=building_id, - ) - if objs: - for index in range(analysis_date['proforma_duration']): - if index < len(objs): - obj = objs[index] - store_year = str(obj.year) - if utility_type == 'electricity': - annual_bill[store_year] = obj.electricity - elif utility_type == 'gas': - annual_bill[store_year] = obj.gas - elif utility_type == 'oil': - annual_bill[store_year] = obj.oil - elif utility_type == 'water': - annual_bill[store_year] = obj.water - else: - store_year = str(int(store_year) + 1) - annual_bill[store_year] = 0 - else: - for year in range(analysis_date['proforma_duration']): - store_year = str(analysis_date['proforma_start'].year + year) - annual_bill[store_year] = 0 - for year in annual_bill: - annual_bill[year] = float("{0:.2f}".format(annual_bill[year])) - annual_bill = {str(key): value for key, value in annual_bill.items()} - return annual_bill - - def get_if_user_input(building_id): """Check if utility charge input was user or from bills. @@ -419,6 +354,45 @@ class BillsOverviewView(View): model_bills = Bills utility = ['electricity', 'gas', 'oil', 'water'] + def get_raw_bill(self, building_id): + """Fetch all the bills in the database. + + Fetch the raw bill from the database and return them as a dictionary for each utility. The return value is + a dictionary with utility type as key and the bill as value. + + Args: + building_id: id of the building. + + Returns: + raw_bill: Dictionary with key as a utility type and value as the bill. The bill in turn is a dictionary + with keys as bill date from, bill date to, energy usage and charge. + """ + utility_objs = {} + raw_bill = {} + for util in self.utility: + objs = Bills.objects.filter( + building_id=building_id, + utility_type=util, + ) + utility_objs[util] = objs + if objs: + date_from = [] + date_to = [] + usage = [] + charge = [] + for obj in objs: + date_from.append(obj.date_from) + date_to.append(obj.date_to) + usage.append(float(obj.usage)) + charge.append(float(obj.charge)) + raw_bill[util] = { + 'date_from': date_from, + 'date_to': date_to, + 'usage': usage, + 'charge': charge, + } + return raw_bill + def get(self, request, building_id): """Handle HTTP GET request. @@ -452,15 +426,21 @@ class BillsOverviewView(View): result['water_user'] = True for obj in objs: store_year = str(obj.year) - result['electricity'][store_year] = float("{0:.2f}".format(obj.electricity)) - result['gas'][store_year] = float("{0:.2f}".format(obj.gas)) - result['oil'][store_year] = float("{0:.2f}".format(obj.oil)) - result['water'][store_year] = float("{0:.2f}".format(obj.water)) + # Limit number of decimal places only if a value exists else keep it as None. + result['electricity'][store_year] = (float("{0:.2f}".format(obj.electricity)) if obj.electricity else None) + result['gas'][store_year] = (float("{0:.2f}".format(obj.gas)) if obj.gas else None) + result['oil'][store_year] = (float("{0:.2f}".format(obj.oil)) if obj.oil else None) + result['water'][store_year] = (float("{0:.2f}".format(obj.water)) if obj.water else None) result['electricity_user'] = obj.electricity_is_user_input result['gas_user'] = obj.gas_is_user_input result['oil_user'] = obj.oil_is_user_input result['water_user'] = obj.water_is_user_input - total_annual_charge.append(obj.electricity + obj.gas + obj.oil + obj.water) + # Calculate total charge for a year. Consider None as 0 for this purpose. + total = 0 + for util in self.utility: + if result[util][store_year]: + total += result[util][store_year] + total_annual_charge.append(total) result['total_annual_charge'] = total_annual_charge return JsonResponse({'instance': result}) @@ -497,8 +477,49 @@ class BillsOverviewView(View): return JsonResponse({'instance': projected_bills}) analysis_date = get_analysis_date(building_id) if put['Estimation Model'] == 'Rough Estimation': + # Fetch all bills from the database. + raw_bill = self.get_raw_bill(building_id) + # Project the charge for utilities whose atleast 12 months bills are available. + projected_bills = monthly_bill(raw_bill, analysis_date) for util in self.utility: - projected_bills[util] = get_total_charge(util, analysis_date, building_id) + # Check if the utility bill is present. + if projected_bills[util]: + # Convert the key to string as JsonResponse doesn't take non-string keys. + # Limit the value to have 2 decimal places. + projected_bills[util] = { + str(key): float("{0:.2f}".format(value)) for key, value in projected_bills[util].items() + } + # If bill is not available for a utility. + else: + annual_bill = {} + # Check database if manual inputs for annual charge was taken previously. + objs = BillsOverview.objects.filter( + building_id=building_id, + ) + if objs: + for index in range(analysis_date['proforma_duration']): + # If manual input was taken, fetch that value for that utility. + if index < len(objs): + obj = objs[index] + store_year = str(obj.year) + if util == 'electricity': + annual_bill[store_year] = obj.electricity + elif util == 'gas': + annual_bill[store_year] = obj.gas + elif util == 'oil': + annual_bill[store_year] = obj.oil + elif util == 'water': + annual_bill[store_year] = obj.water + # If no manual input, set it None. + else: + store_year = str(int(store_year) + 1) + annual_bill[store_year] = None + # If no manual inputs have been input for this building, set all to None. + else: + for year in range(analysis_date['proforma_duration']): + store_year = str(analysis_date['proforma_start'].year + year) + annual_bill[store_year] = None + projected_bills[util] = annual_bill e_user, g_user, o_user, w_user = get_if_user_input(building_id) projected_bills['electricity_user'] = e_user projected_bills['gas_user'] = g_user @@ -508,10 +529,9 @@ class BillsOverviewView(View): for year in range(analysis_date['proforma_duration']): total = 0 store_year = str(analysis_date['proforma_start'].year + year) - total += float("{0:.2f}".format(projected_bills['electricity'][store_year])) - total += float("{0:.2f}".format(projected_bills['gas'][store_year])) - total += float("{0:.2f}".format(projected_bills['oil'][store_year])) - total += float("{0:.2f}".format(projected_bills['water'][store_year])) + for util in self.utility: + if projected_bills[util][store_year]: + total += float("{0:.2f}".format(projected_bills[util][store_year])) total_annual_charge.append(total) projected_bills['total_annual_charge'] = total_annual_charge else: @@ -542,6 +562,11 @@ class BillsOverviewView(View): g_search = 'gas-value-' + store_year o_search = 'oil-value-' + store_year w_search = 'water-value-' + store_year + searching_key = {} + for util in self.utility: + searching_key[util] = util + '-value-' + store_year + if not post[searching_key[util]]: + post[searching_key[util]] = None self.model_bills_overview.objects.create( building_id=building_id, year=int(store_year),