diff --git a/blocnote/apps/financialInputs/migrations/0013_cashbalance.py b/blocnote/apps/financialInputs/migrations/0013_cashbalance.py new file mode 100644 index 0000000000000000000000000000000000000000..7fe295254e952dc6bd274b5b98bc2a3413ee6264 --- /dev/null +++ b/blocnote/apps/financialInputs/migrations/0013_cashbalance.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.6 on 2017-04-20 15:12 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('financialInputs', '0012_customerpreference'), + ] + + operations = [ + migrations.CreateModel( + name='CashBalance', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('building_id', models.IntegerField()), + ('date', models.DateField()), + ('is_from_balance_sheet', models.BooleanField(default=False)), + ('balance_amount', models.DecimalField(decimal_places=2, max_digits=10)), + ], + ), + ] diff --git a/blocnote/apps/financialInputs/migrations/0014_auto_20170421_0004.py b/blocnote/apps/financialInputs/migrations/0014_auto_20170421_0004.py new file mode 100644 index 0000000000000000000000000000000000000000..b737b5103ca1ff7f846671e37e117bc98853cd10 --- /dev/null +++ b/blocnote/apps/financialInputs/migrations/0014_auto_20170421_0004.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.6 on 2017-04-21 00:04 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('financialInputs', '0013_cashbalance'), + ] + + operations = [ + migrations.RenameField( + model_name='cashbalance', + old_name='date', + new_name='start_date', + ), + ] diff --git a/blocnote/apps/financialInputs/migrations/0016_merge_20170427_1611.py b/blocnote/apps/financialInputs/migrations/0016_merge_20170427_1611.py new file mode 100644 index 0000000000000000000000000000000000000000..ef9d47626f40036ec9f5fc0bd2c2201867807423 --- /dev/null +++ b/blocnote/apps/financialInputs/migrations/0016_merge_20170427_1611.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.6 on 2017-04-27 16:11 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('financialInputs', '0015_auto_20170424_2250'), + ('financialInputs', '0014_auto_20170421_0004'), + ] + + operations = [ + ] diff --git a/blocnote/apps/financialInputs/migrations/0017_auto_20170427_1900.py b/blocnote/apps/financialInputs/migrations/0017_auto_20170427_1900.py new file mode 100644 index 0000000000000000000000000000000000000000..a014e1d6c8c479d0b3dbf9e7f51f1755ea2105d3 --- /dev/null +++ b/blocnote/apps/financialInputs/migrations/0017_auto_20170427_1900.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.6 on 2017-04-27 19:00 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('financialInputs', '0016_merge_20170427_1611'), + ] + + operations = [ + migrations.RenameField( + model_name='cashbalance', + old_name='start_date', + new_name='statement_date', + ), + ] diff --git a/blocnote/apps/financialInputs/models.py b/blocnote/apps/financialInputs/models.py index 14e63987d192abb9720883ac08ba491f9bafbf93..8de7ff47b6acbb3515020345db0e29a10b9dc64a 100644 --- a/blocnote/apps/financialInputs/models.py +++ b/blocnote/apps/financialInputs/models.py @@ -71,3 +71,15 @@ class CustomerPreference(models.Model): downpayment = models.DecimalField(max_digits=10, decimal_places=2) expected_payback = models.DecimalField(max_digits=3, decimal_places=0) expected_net_noi_dscr = models.DecimalField(max_digits=5, decimal_places=2) + + +class CashBalance(models.Model): + """Store Balance amount information. + + Store balance amount information. Flag for amount coming from balance sheet or bank statement. + """ + + building_id = models.IntegerField() + statement_date = models.DateField() + is_from_balance_sheet = models.BooleanField(default=False) + balance_amount = 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 4f042d4faf16b607d16f61ac2bdff59e5c56d2fe..594149fdd0f94dad4e445cacc429d433af425cdd 100644 --- a/blocnote/apps/financialInputs/static/financialInputs/scripts/app.js +++ b/blocnote/apps/financialInputs/static/financialInputs/scripts/app.js @@ -4,6 +4,13 @@ for (var utility_index in utilities) { } loadBillsOverview(); getCustomerPreferenceTable(); +getCashBalanceForm(); +/**nextCashBalanceRowID is used to uniquely identify the row of the cash balance table. This does NOT represent the + * actual row number. It represents the total number of rows added. This does NOT get decremented on deleting + * a row. This is so that each new row has a new number in its id so that information can be obtained and sent + * to backend. + */ +var nextCashBalanceRowID = 0; /** * Handle submition of the header form. Validate commissioning date is greater @@ -324,11 +331,11 @@ function loadBillsOverview() { 'Content-Type': 'application/json' }, }).then(res => { - if(!res.err) { + if (!res.err) { const table = document.querySelector('#Energy-Bills-Overview'); var text = ``; text += createEstimateModelForm(); - if(res.payload.instance.present) { + if (res.payload.instance.present) { text += createBillsOverviewTable(res.payload.instance); } table.innerHTML = text; @@ -356,7 +363,7 @@ function billsOverviewFormCalculate(data) { 'X-CSRFToken': Cookies.get('csrftoken') }) }).then(res => { - if(res.payload.instance['err']) { + if (res.payload.instance['err']) { alert(res.payload.instance['msg']); return false; } @@ -424,12 +431,12 @@ function createCustomerPreferenceTable(instance) { var expectedNetNOIDSCR = instance['expected_net_noi_dscr'] } var text = ` - - - - - - + + + + + + @@ -449,9 +456,7 @@ function createCustomerPreferenceTable(instance) { customerPreferenceForm.innerHTML = text; } -/** - * Make HTTP GET request to obtain customer preference table data if present. - */ +/**Make HTTP GET request to obtain customer preference table data if present. */ function getCustomerPreferenceTable() { request(`customer-preference/`, { method: 'GET', @@ -463,3 +468,181 @@ function getCustomerPreferenceTable() { createCustomerPreferenceTable(res.payload.instance); }); } + +/**Send HTTP GET request to obtain all cash balance records. */ +function getCashBalanceForm() { + request(`cash-balance/`, { + method: 'GET', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json' + }, + }).then(res => { + loadCashBalanceTable(res.payload.instance); + }); +} + +/**Load cash balance table with initial values. Takes response from GET request to construct the table. */ +function loadCashBalanceTable(instance) { + table = document.querySelector('#cash-balance-table'); + if (instance.status) { + for (var record=0; record < instance.result.length; record++) { + balanceAmount = Number(instance.result[record].balance_amount); + date = instance.result[record].date.split('-'); + month = Number(date[1]); + day = Number(date[2]); + year = Number(date[0]); + isFromBalanceSheet = instance.result[record]['is_from_balance_sheet'] + addCashBalanceRow(balanceAmount, month, day, year, isFromBalanceSheet); + } + } + else { + addCashBalanceRow(0, 1, 1, 1980, false); + } +} + +/** + * Return check box to indicate if a record is from balance sheet or not. Takes a boolean as argument which + * is true if the record is from balance, else not. This function returns a checked checkbox if it is from balance + * sheet, else an unchecked checkbox. + */ +function getCashBalanceCheckBox(isFromBalanceSheet) { + var check = ""; + if (isFromBalanceSheet) { + check = "checked"; + } + var text = ` + + `; + return text; +} + +/**Delete a given row in the cash balance table. Takes in the row index as argument. */ +function deleteCashBalanceRow(row) { + table = document.querySelector('#cash-balance-table'); + table.deleteRow(row); + for (rowInd = 1; rowInd < table.rows.length; rowInd++) { + row = table.rows.item(rowInd).cells; + row.item(0).innerHTML = rowInd; + } + return false; +} + +/** + * Add a row to the cash balance table. Take balance amount, date and boolean that represents if a record is from + * balance sheet or not. + */ +function addCashBalanceRow(balance, month, day, year, isFromBalanceSheet) { + table = document.querySelector('#cash-balance-table'); + var rowCount = table.rows.length; + var row = table.insertRow(rowCount); + var cell = row.insertCell(0); + cell.innerHTML += `${rowCount}`; + cell = row.insertCell(1); + cell.innerHTML += ` + + `; + cell = row.insertCell(2); + cell.innerHTML += ` + ${createDateComponent(month, day, year)} + `; + cell = row.insertCell(3); + cell.innerHTML += getCashBalanceCheckBox(isFromBalanceSheet); + cell = row.insertCell(4) + cell.innerHTML += ` + + `; + nextCashBalanceRowID += 1; + return false; +} + +/**Make PUT request with data from the cash balance table. */ +function submitCashBalanceForm(form) { + var myResult = []; + table = document.querySelector('#cash-balance-table'); + var rowCount = table.rows.length; + for (rowIndex = 1; rowIndex < rowCount; rowIndex++) { + record = {}; + record['balance'] = table.rows[rowIndex].cells[1].children[0].value; + record['date-month'] = table.rows[rowIndex].cells[2].children[0].value; + record['date-day'] = table.rows[rowIndex].cells[2].children[1].value; + record['date-year'] = table.rows[rowIndex].cells[2].children[2].value; + checkBox = table.rows[rowIndex].querySelectorAll('input[type="checkbox"]:checked'); + if (checkBox.length > 0) { + record['is-from-balance-sheet'] = 'on'; + } + myResult.push(record); + } + request('cash-balance/', { + method: 'PUT', + credentials: 'same-origin', + body: JSON.stringify(myResult), + headers: new Headers({ + 'Content-Type': 'application/json', + 'X-CSRFToken': Cookies.get('csrftoken') + }) + }); + return false; +} + +/**Create the select date component.*/ +function createDateComponent(mon, day, yr) { + months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; + selectMonth = ``; + selectDay = ``; + selectYear = ``; + var text = ` + + + + `; + + return text; +} diff --git a/blocnote/apps/financialInputs/templates/financialInputs/cashBalance.html b/blocnote/apps/financialInputs/templates/financialInputs/cashBalance.html new file mode 100644 index 0000000000000000000000000000000000000000..c6975d9052daa80faa1a39a19b64ea21281280c8 --- /dev/null +++ b/blocnote/apps/financialInputs/templates/financialInputs/cashBalance.html @@ -0,0 +1,24 @@ +

+ Cash Balance +

+ +
+ +
+
PreferenceValue
PreferenceValue
Affordable Downpayment
+ + + + + + + + + +
#Balance AmountDateBalance SheetOption
+ +
+
+ +
+
diff --git a/blocnote/apps/financialInputs/templates/financialInputs/index.html b/blocnote/apps/financialInputs/templates/financialInputs/index.html index 25a35b7f86cb464c6df236a10cc66dd4a95288b8..6a4a298da2bad4d967b762f3823b92a29109a9ec 100644 --- a/blocnote/apps/financialInputs/templates/financialInputs/index.html +++ b/blocnote/apps/financialInputs/templates/financialInputs/index.html @@ -22,6 +22,9 @@
{% include "financialInputs/billsOverview.html" %}
+
+ {% include "financialInputs/cashBalance.html" %} +
{% include "financialInputs/customerPreference.html" %}
diff --git a/blocnote/apps/financialInputs/urls.py b/blocnote/apps/financialInputs/urls.py index 72b7fbdf0574cdc3f8f53989fab4dc773ac15d5c..e84aa1cbd7823f01bd98b9802b5c198137efd3a3 100644 --- a/blocnote/apps/financialInputs/urls.py +++ b/blocnote/apps/financialInputs/urls.py @@ -8,4 +8,5 @@ urlpatterns = [ url(r'^bills/$', views.BillsTable.as_view(), name='bills'), url(r'^bills-overview/$', views.BillsOverviewView.as_view(), name='bills_overview'), url(r'^customer-preference/$', views.CustomerPreferenceView.as_view(), name='customer_preference'), + url(r'^cash-balance/$', views.CashBalanceView.as_view(), name='cash_balance'), ] diff --git a/blocnote/apps/financialInputs/views.py b/blocnote/apps/financialInputs/views.py index f99a8b55dfb0195e5a6c5bb391651f3a96535323..cb55f7bd60bf78dbfbf3a6da17ed03ae127739e5 100644 --- a/blocnote/apps/financialInputs/views.py +++ b/blocnote/apps/financialInputs/views.py @@ -4,9 +4,11 @@ from django.http import JsonResponse from django.db import connections 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 .models import FinancingOverview, Bills, BillsOverview, CustomerPreference, EstimationAlgorithm +from .models import FinancingOverview, Bills, BillsOverview, CustomerPreference, EstimationAlgorithm, CashBalance from .forms import BlocNoteHeaderForm @@ -602,3 +604,84 @@ class CustomerPreferenceView(View): instance['status'] = False return JsonResponse({'instance': instance}) + +class CashBalanceView(View): + """Display, store and use cash balance data.""" + + model = CashBalance + + def get(self, request, building_id): + """Handle HTTP GET request. + + Fetch cash balance data from database if present. If not, return false status. + + Args: + request: HTTP GET request. + building_id: id of the building. + """ + objs = self.model.objects.filter(building_id=building_id) + instance = {} + instance['result'] = [] + if objs: + instance['status'] = True + for obj in objs: + temp = {} + temp['date'] = obj.start_date + temp['is_from_balance_sheet'] = obj.is_from_balance_sheet + temp['balance_amount'] = obj.balance_amount + instance['result'].append(temp) + else: + instance['status'] = False + return JsonResponse({'instance': instance}) + + def get_record_list(self, put): + """Retrieve records from PUT request. + + Retrieve all cash balance records from PUT request and return a list of records which is a dictionary here. + + Args: + put: Decoded put request body which is a dictionary. + + Returns: + result: List of dictionaries which are the cash balance records. + """ + record_list = [] + for row in put: + record = {} + if 'is-from-balance-sheet' in row: + record['is_from_balance_sheet'] = True + else: + record['is_from_balance_sheet'] = False + record['balance'] = row['balance'] + record['month'] = int(row['date-month']) + record['day'] = int(row['date-day']) + record['year'] = int(row['date-year']) + record_list.append(record) + return record_list + + def put(self, request, building_id): + """Handle HTTP PUT request. + + Retrieve the list of records from the request. Delete existing records and create new records. + + Args: + request: HTTP PUT request. + building_id: id of the building. + + Returns: + JsonResponse: An instance with OK. + """ + put = json.loads(request.body.decode()) + record_list = self.get_record_list(put) + self.model.objects.filter( + building_id=building_id, + ).delete() + for record in record_list: + self.model.objects.create( + building_id=building_id, + start_date=date(record['year'], record['month'], record['day']), + is_from_balance_sheet=record['is_from_balance_sheet'], + balance_amount=record['balance'], + ) + return JsonResponse({'instance': 'OK'}) +