From b0118e9ff9e97839fd5932a4d1a6470ed70cedaf Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Fri, 26 May 2017 08:58:55 -0400 Subject: [PATCH 01/21] Refactor proforma inputs. The views is a new file in the views folder. It does an update_r_create rather than a delete and create operation which was more costly. Form for the same is used to validate form data sent from frontend. Changes in frontend include using javascript date object rather than the user defined function. Errors from django form validations are caught and displayed for the respective input field. --- blocnote/apps/financialInputs/forms.py | 21 +++ .../{views.py => old_views.py} | 87 +-------- .../static/financialInputs/scripts/app.js | 175 ------------------ .../templates/financialInputs/headerForm.html | 51 ----- .../templates/financialInputs/index.html | 1 + .../financialInputs/proFormaForm.html | 14 ++ blocnote/apps/financialInputs/urls.py | 21 ++- .../apps/financialInputs/views/__init__.py | 0 .../financialInputs/views/proforma_input.py | 124 +++++++++++++ 9 files changed, 172 insertions(+), 322 deletions(-) create mode 100644 blocnote/apps/financialInputs/forms.py rename blocnote/apps/financialInputs/{views.py => old_views.py} (92%) delete mode 100644 blocnote/apps/financialInputs/templates/financialInputs/headerForm.html create mode 100644 blocnote/apps/financialInputs/views/__init__.py create mode 100644 blocnote/apps/financialInputs/views/proforma_input.py diff --git a/blocnote/apps/financialInputs/forms.py b/blocnote/apps/financialInputs/forms.py new file mode 100644 index 0000000..bca424d --- /dev/null +++ b/blocnote/apps/financialInputs/forms.py @@ -0,0 +1,21 @@ +"""Forms to render and validate for financial-inputs endpoint.""" +from django.forms import ModelForm +from blocnote.apps.financialInputs.models import FinancingOverview + + +class ProformaInputsForm(ModelForm): + """Define the form to input/display proforma information.""" + + class Meta: + """Choose the model and the relevant fields for the form.""" + + model = FinancingOverview + fields = [ + 'fund', + 'pro_forma_start_date', + 'pro_forma_duration', + 'analysis_date', + 'anticipated_construction_start_date', + 'anticipated_commissioning_date', + 'anticipated_construction_period', + ] diff --git a/blocnote/apps/financialInputs/views.py b/blocnote/apps/financialInputs/old_views.py similarity index 92% rename from blocnote/apps/financialInputs/views.py rename to blocnote/apps/financialInputs/old_views.py index 76770bd..2387603 100644 --- a/blocnote/apps/financialInputs/views.py +++ b/blocnote/apps/financialInputs/old_views.py @@ -14,6 +14,7 @@ from bpfin.financials.financial_lib import Income_Statement_Table from .models import Fund, FinancingOverview, Bills, BillsOverview, CustomerPreference, EstimationAlgorithm from .models import Liabilities, CashBalance, IncomeStatement, LoanOptions, DefaultLoan, Lender, GrowthRate +from .forms import ProformaInputsForm def get_analysis_date(building_id): @@ -105,92 +106,6 @@ class Index(View): return render(request, 'financialInputs/index.html', context=context) -class BlocNoteHeader(View): - """This class handles header creation and update.""" - - model = FinancingOverview - - def handle_form(self, put, building_id): - """Handle form submit. - - Take the header form passed by the frontend and make an entry in the database. - - Args: - put: This is the data sent in the PUT request by frontend. - building_id: id of the building. - """ - self.model.objects.filter(building_id=building_id).delete() - self.model.objects.create( - building_id=building_id, - fund_id=put['fund'], - pro_forma_start_date=put['pro_forma_start_date'], - pro_forma_duration=put['pro_forma_duration'], - analysis_date=put['analysis_date'], - anticipated_construction_start_date=put['anticipated_construction_start_date'], - anticipated_commissioning_date=put['anticipated_commissioning_date'], - anticipated_construction_period=put['anticipated_construction_period'], - ) - - def put(self, request, building_id): - """PUT route for header. - - Handle the PUT request for the header form. Store all the data received into the database. If storing was - successfull, send success message else send a failure message. - - Args: - request: HTTP PUT request. - building_id: id of the building. - - Returns: - JsonResponse: If success, returns a message saying successful else return message saying it failed. - """ - put = json.loads(request.body.decode()) - result = {} - try: - self.handle_form(put, building_id) - except: - result['err'] = 'Sorry, the data could not be saved.' - return JsonResponse(result) - - def get(self, request, building_id): - """HTTP GET request. - - Fetch the financing overview data from the database and send to the frontend. Send the list of lenders - regardless of whether a financing overview entry has been made or not. - - Args: - request: HTTP GET request. - building_id: id of the building. - - Returns: - JsonResponse: Result with the financing overview data. - """ - financing_overview_objs = self.model.objects.filter(building_id=building_id) - - # Fetch all the funds. - funds_obj = Fund.objects.all() - funds = [] - for fund_obj in funds_obj: - funds.append((fund_obj.id, fund_obj.Name)) - result = {} - - # Check if the financing overview entry exists in the database. - if financing_overview_objs: - financing_overview_obj = financing_overview_objs[0] - result = { - 'present': True, - 'fund': financing_overview_obj.fund.id, - 'pro_forma_start_date': financing_overview_obj.pro_forma_start_date, - 'pro_forma_duration': financing_overview_obj.pro_forma_duration, - 'analysis_date': financing_overview_obj.analysis_date, - 'anticipated_construction_start_date': financing_overview_obj.anticipated_construction_start_date, - 'anticipated_commissioning_date': financing_overview_obj.anticipated_commissioning_date, - 'anticipated_construction_period': financing_overview_obj.anticipated_construction_period, - } - result['funds'] = funds - return JsonResponse({'result': result}) - - class BillsTable(View): """Create the Energy Bills tables. diff --git a/blocnote/apps/financialInputs/static/financialInputs/scripts/app.js b/blocnote/apps/financialInputs/static/financialInputs/scripts/app.js index fd36648..a6b4f08 100644 --- a/blocnote/apps/financialInputs/static/financialInputs/scripts/app.js +++ b/blocnote/apps/financialInputs/static/financialInputs/scripts/app.js @@ -8,7 +8,6 @@ const todaysDate = { for (var utility_index in utilities) { loadInitialBillsTable(utilities[utility_index]); } -getBillProjectionDatesForm(); loadBillsOverview(); getIncomeStatementTable(); getCustomerPreferenceTable(); @@ -16,180 +15,6 @@ getLiabilitiesTable(); getCashBalanceForm(); getLoanOptionsTable(); -/** - * proformaForm will watch the form and if it changes, it will remove the response message is it was displayed. - */ -var proformaForm = document.querySelector('#pro-forma-form'); -proformaForm.onchange = function() { - var resMsg = document.querySelector('#pro-forma-form-save-msg'); - resMsg.innerHTML = ``; -} - -/** - * The following 2 functions display a warning message saying if fund is changed, it will affect the loan options. - * This message is displayed when the mouse is over the fund select box. - */ -var fund = document.querySelector('#id_fund'); -/** - * This is to watch if fund value is changed. If it did, it would affect loan options. - */ -var didFundChange = false; -fund.onmouseenter = function() { - var errorDiv = document.querySelector('#show-error'); - errorDiv.innerHTML = `Changing fund will affect loan options`; -} - -fund.onmouseleave = function() { - var errorDiv = document.querySelector('#show-error'); - errorDiv.innerHTML = ""; -} - -fund.onchange = function() { - didFundChange = true; -} - -/** - * HTTP GET request to fetch the proforma form information from the database if preent. It would receive the list of - * funds along with. - */ -function getBillProjectionDatesForm() { - request(`finance-overview`, { - method: 'GET', - credentials: 'same-origin', - headers: { - 'Content-Type': 'application/json' - }, - }).then(res => { - fundDropBox = document.querySelector('#id_fund-select'); - var funds = res.payload.result.funds; - for (var fundIndex = 0; fundIndex < funds.length; fundIndex++) { - fundDropBox.innerHTML += ` - - `; - if (res.payload.result.present) { - document.querySelector('#pro-forma-date-input').value = res.payload.result.pro_forma_start_date; - document.querySelector('#pro-forma-duration-input').value = res.payload.result.pro_forma_duration; - document.querySelector('#analysis-date-input').value = res.payload.result.analysis_date; - document.querySelector('#id_fund-select').value = res.payload.result.fund; - document.querySelector('#anticipated-construction-start-date-input').value = res.payload.result.anticipated_construction_start_date; - document.querySelector('#anticipated-commissioning-date-input').value = res.payload.result.anticipated_commissioning_date; - document.querySelector('#anticipated-construction-period-input').value = res.payload.result.anticipated_construction_period; - } - } - }); -} - -/** - * Handle submition of the header form. Validate commissioning date is greater - * than construction start date. Create result dictionary containing the form - * data and convert into JSON to send to the backend. Upon success, load the - * Bills overview table as the Pro Forma year changes the start year of the - * Bills overview table. - */ -function billProjectionDatesForm(form) { - var proFormaStartDate = document.querySelector('#pro-forma-date-input').value; - var proFormaDuration = document.querySelector('#pro-forma-duration-input').value; - var analysisDate = document.querySelector('#analysis-date-input').value; - var fund = document.querySelector('#id_fund-select').value; - var anticipatedConstructionStartDate = document.querySelector('#anticipated-construction-start-date-input').value; - var anticipatedCommissioningDate = document.querySelector('#anticipated-commissioning-date-input').value; - var anticipatedConstructionPeriod = document.querySelector('#anticipated-construction-period-input').value; - startYear = anticipatedConstructionStartDate.split('-') - endDate = anticipatedCommissioningDate.split('-'); - var anticipatedConstructionStartYear = startYear[0]; - var anticipatedConstructionStartMonth = startYear[1]; - var anticipatedConstructionStartDay = startYear[2]; - var anticipatedCommissioningStartYear = endDate[0]; - var anticipatedCommissioningStartMonth = endDate[1]; - var anticipatedCommissioningStartDay = endDate[2]; - var anticipatedConstructionStartDateDict = { - 'day': anticipatedConstructionStartDay, - 'month': anticipatedConstructionStartMonth, - 'year': anticipatedConstructionStartYear, - } - var anticipatedCommissioningDateDict = { - 'day': anticipatedCommissioningStartDay, - 'month': anticipatedCommissioningStartMonth, - 'year': anticipatedCommissioningStartYear, - } - var proFormaStartYear = Number(proFormaStartDate.split('-')[0]); - var isProFormaDateCorrect = true; - - /** - * Usually proforma start year is 3 years before current year. If the entered date is less than 3, confirm with - * user if that value is correct. - */ - if (todaysDate.year - proFormaStartYear < 3) { - isProFormaDateCorrect = confirm('ARE YOU SURE THE PROFORMA DATE IS CORRECT?'); - } - if (isProFormaDateCorrect) { - // Ensure that commissioning date is after start date. - var validDate = validateDate(anticipatedConstructionStartDateDict, anticipatedCommissioningDateDict); - if (!validDate) { - document.querySelector('#pro-forma-form-save-msg').innerHTML = ` - - Anticipated Commissioning date has to be after Anticipated Construction start date - - `; - } - else { - result = { - 'pro_forma_start_date': proFormaStartDate, - 'pro_forma_duration': proFormaDuration, - 'analysis_date': analysisDate, - 'fund': fund, - 'anticipated_construction_start_date': anticipatedConstructionStartDate, - 'anticipated_commissioning_date': anticipatedCommissioningDate, - 'anticipated_construction_period': anticipatedConstructionPeriod, - } - request('finance-overview/', { - method: 'PUT', - credentials: 'same-origin', - body: JSON.stringify(result), - headers: new Headers({ - 'Content-Type': 'application/json', - 'X-CSRFToken': Cookies.get('csrftoken') - }) - }).then(res => { - if (!res.payload.err) { - // Display response message. Add that loan options changed if fund was changed. Reset didFundChange to false. - responseMessage = 'Saved'; - if (didFundChange) { - responseMessage += ' Loan Options table is reloaded.'; - } - var resMsg = document.querySelector('#pro-forma-form-save-msg'); - resMsg.innerHTML = `${responseMessage}`; - /** - * delete-loan-options request to the backend to delete loan options for this building id if previosly stored. - * This ensures that the loan options table is up to date with the latest fund. Clear the loan options table - * and reload with new fund's default loan options. - */ - if (didFundChange) { - didFundChange = false; - request(`loan-options/?loans=delete-loan-options`, { - method: 'GET', - credentials: 'same-origin', - headers: { - 'Content-Type': 'application/json' - }, - }).then(res => { - var tableBody = document.querySelector('#loan-options-table tbody'); - tableBody.innerHTML = ``; - }); - } - getLoanOptionsTable(); - } - else { - // Display error message. - var resMsg = document.querySelector('#pro-forma-form-save-msg'); - resMsg.innerHTML = `${res.payload.err}`; - } - }); - } - } - return false; -} - /** Validate that commissioning date is after the construction start date. */ function validateDate(startDate, endDate) { var startDateYear = startDate.year; diff --git a/blocnote/apps/financialInputs/templates/financialInputs/headerForm.html b/blocnote/apps/financialInputs/templates/financialInputs/headerForm.html deleted file mode 100644 index 51a687a..0000000 --- a/blocnote/apps/financialInputs/templates/financialInputs/headerForm.html +++ /dev/null @@ -1,51 +0,0 @@ -
- {% csrf_token %} -
-
-
- {{ form.pro_forma_start_date.label_tag }} -
-
- {{ form.pro_forma_start_date }} -
-
- {{ form.pro_forma_duration.label_tag }} -
-
- {{ form.pro_forma_duration }} (years) -
-
-
-
-
-
- {{ form.analysis_date.label_tag }} -
-
- {{ form.analysis_date }} -
-
- Select Fund: {{ form.fund }} -
-
-
-
-
-
-
- {{ form.anticipated_construction_start_date.label_tag }} - {{ form.anticipated_construction_start_date }} - - {{ form.anticipated_commissioning_date.label_tag }} - {{ form.anticipated_commissioning_date }} -
-
-
-
- {{ form.anticipated_construction_period.label_tag }} - {{ form.anticipated_construction_period }} weeks -
- -
-
-
diff --git a/blocnote/apps/financialInputs/templates/financialInputs/index.html b/blocnote/apps/financialInputs/templates/financialInputs/index.html index a208ffd..0ee9162 100644 --- a/blocnote/apps/financialInputs/templates/financialInputs/index.html +++ b/blocnote/apps/financialInputs/templates/financialInputs/index.html @@ -55,4 +55,5 @@ + {% endblock %} diff --git a/blocnote/apps/financialInputs/templates/financialInputs/proFormaForm.html b/blocnote/apps/financialInputs/templates/financialInputs/proFormaForm.html index f3d7122..9ec108e 100644 --- a/blocnote/apps/financialInputs/templates/financialInputs/proFormaForm.html +++ b/blocnote/apps/financialInputs/templates/financialInputs/proFormaForm.html @@ -5,10 +5,14 @@
Pro Forma Start date +
+
Pro Forma Duration (years) +
+
@@ -17,11 +21,15 @@
Analysis Date +
+
Fund +
+
@@ -32,10 +40,14 @@
Anticipated Construction Start Date +
+
Anticipated Commissioning Date +
+
@@ -44,6 +56,8 @@
Anticipated Construction Period (weeks) +
+
diff --git a/blocnote/apps/financialInputs/urls.py b/blocnote/apps/financialInputs/urls.py index ce55b44..e09fa58 100644 --- a/blocnote/apps/financialInputs/urls.py +++ b/blocnote/apps/financialInputs/urls.py @@ -1,15 +1,16 @@ from django.conf.urls import url -from . import views +from . import old_views +from .views import proforma_input urlpatterns = [ - url(r'^$', views.Index.as_view(), name='index'), - url(r'^finance-overview/$', views.BlocNoteHeader.as_view(), name='header'), - 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'^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'), - url(r'^loan-options/$', views.LoanOptionsTable.as_view(), name='loan_options'), + url(r'^$', old_views.Index.as_view(), name='index'), + url(r'^finance-overview/$', proforma_input.ProformaInputs.as_view(), name='header_new'), + url(r'^bills/$', old_views.BillsTable.as_view(), name='bills'), + url(r'^bills-overview/$', old_views.BillsOverviewView.as_view(), name='bills_overview'), + url(r'^customer-preference/$', old_views.CustomerPreferenceView.as_view(), name='customer_preference'), + url(r'^liabilities/$', old_views.LiabilitiesTable.as_view(), name='liabilities'), + url(r'^cash-balance/$', old_views.CashBalanceView.as_view(), name='cash_balance'), + url(r'^income-statement/$', old_views.IncomeStatementTable.as_view(), name='income_statement'), + url(r'^loan-options/$', old_views.LoanOptionsTable.as_view(), name='loan_options'), ] diff --git a/blocnote/apps/financialInputs/views/__init__.py b/blocnote/apps/financialInputs/views/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/blocnote/apps/financialInputs/views/proforma_input.py b/blocnote/apps/financialInputs/views/proforma_input.py new file mode 100644 index 0000000..ecc6b4e --- /dev/null +++ b/blocnote/apps/financialInputs/views/proforma_input.py @@ -0,0 +1,124 @@ +"""Route for Proforma Inputs.""" +import json +from django.views import View +from django.http import JsonResponse +from blocnote.apps.financialInputs.models import FinancingOverview +from blocnote.apps.financialInputs.models import Fund + +from blocnote.apps.financialInputs import forms + + +class ProformaInputs(View): + """This class handles Proforma inputs storing/updating. + + Proforma or projection information consists of the start date from which projection should begin and a duration, + which determines how far to project from the start date. The start date is typically 3-5 years before current. + Apart from this, other relevant information are analysis date which is the current date, fund which basically + indicates what fund would be used for this building, anticipated construction start date, anticipated commissioni- + ng date and anticipated construction period which may or may not be the difference between the latter two inputs. + """ + + fund_model = Fund + financing_model = FinancingOverview + proforma_inputs_form = forms.ProformaInputsForm + + def handle_form(self, put, building_id): + """Handle form submit. + + Take the proforma inputs passed by the frontend and store in database if a record doesn't exist for this + building else update the record. + + Args: + put: This is the data sent in the PUT request by frontend. + building_id: id of the building. + """ + self.financing_model.objects.update_or_create( + building_id=building_id, + defaults={ + 'building_id': building_id, + 'fund_id': put['fund'], + 'pro_forma_start_date': put['pro_forma_start_date'], + 'pro_forma_duration': put['pro_forma_duration'], + 'analysis_date': put['analysis_date'], + 'anticipated_construction_start_date': put['anticipated_construction_start_date'], + 'anticipated_commissioning_date': put['anticipated_commissioning_date'], + 'anticipated_construction_period': put['anticipated_construction_period'], + } + ) + + def put(self, request, building_id): + """HTTP PUT request. + + Receive the financing overview inputs from the frontend. Validate this information and then create new entry + if not already existing for this building or update existing entry. + + Args: + resquest: HTTP PUT request. + building_id: id of the building. + + Returns: + error: error message with status 500 if saving into database fails. + Otherwise a status 200. + """ + put = json.loads(request.body.decode()) + form = self.proforma_inputs_form({ + 'fund': put['fund'], + 'pro_forma_start_date': put['pro_forma_start_date'], + 'pro_forma_duration': put['pro_forma_duration'], + 'analysis_date': put['analysis_date'], + 'anticipated_construction_start_date': put['anticipated_construction_start_date'], + 'anticipated_commissioning_date': put['anticipated_commissioning_date'], + 'anticipated_construction_period': put['anticipated_construction_period'], + }) + if form.is_valid(): + try: + self.handle_form(put, building_id) + except Exception as err: + print('Error saving to database.') + print(err.args[0]) + return JsonResponse({'error': 'Could not save because of database issue'}, status=500) + else: + error_dict = {} + for field, error in form.errors.items(): + error_dict[field] = error + print(error_dict) + return JsonResponse(error_dict, status=400) + return JsonResponse({}) + + def get(self, request, building_id): + """HTTP GET request. + + Fetch the financing overview data from the database and send to the frontend. Send the list of lenders + regardless of whether a financing overview entry has been made or not. + + Args: + request: HTTP GET request. + building_id: id of the building. + + Returns: + JsonResponse: Result with the financing overview data. + """ + financing_overview_objs = self.financing_model.objects.filter(building_id=building_id) + + # Fetch all the funds. + funds_obj = self.fund_model.objects.all() + funds = [] + for fund_obj in funds_obj: + funds.append((fund_obj.id, fund_obj.Name)) + instance = {} + + # Check if the financing overview entry exists in the database. + if financing_overview_objs: + financing_overview_obj = financing_overview_objs[0] + financing_overview_data = { + 'fund': financing_overview_obj.fund.id, + 'pro_forma_start_date': financing_overview_obj.pro_forma_start_date, + 'pro_forma_duration': financing_overview_obj.pro_forma_duration, + 'analysis_date': financing_overview_obj.analysis_date, + 'anticipated_construction_start_date': financing_overview_obj.anticipated_construction_start_date, + 'anticipated_commissioning_date': financing_overview_obj.anticipated_commissioning_date, + 'anticipated_construction_period': financing_overview_obj.anticipated_construction_period, + } + instance['financing_overview_data'] = financing_overview_data + instance['funds'] = funds + return JsonResponse({'instance': instance}) -- GitLab From b9f8c6e5d7fb800b0126f5f6662c42b77f180d86 Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Wed, 31 May 2017 14:36:14 -0400 Subject: [PATCH 02/21] Remove useless function handle_form. --- .../financialInputs/views/proforma_input.py | 44 ++++++------------- 1 file changed, 13 insertions(+), 31 deletions(-) diff --git a/blocnote/apps/financialInputs/views/proforma_input.py b/blocnote/apps/financialInputs/views/proforma_input.py index ecc6b4e..1a1db96 100644 --- a/blocnote/apps/financialInputs/views/proforma_input.py +++ b/blocnote/apps/financialInputs/views/proforma_input.py @@ -22,30 +22,6 @@ class ProformaInputs(View): financing_model = FinancingOverview proforma_inputs_form = forms.ProformaInputsForm - def handle_form(self, put, building_id): - """Handle form submit. - - Take the proforma inputs passed by the frontend and store in database if a record doesn't exist for this - building else update the record. - - Args: - put: This is the data sent in the PUT request by frontend. - building_id: id of the building. - """ - self.financing_model.objects.update_or_create( - building_id=building_id, - defaults={ - 'building_id': building_id, - 'fund_id': put['fund'], - 'pro_forma_start_date': put['pro_forma_start_date'], - 'pro_forma_duration': put['pro_forma_duration'], - 'analysis_date': put['analysis_date'], - 'anticipated_construction_start_date': put['anticipated_construction_start_date'], - 'anticipated_commissioning_date': put['anticipated_commissioning_date'], - 'anticipated_construction_period': put['anticipated_construction_period'], - } - ) - def put(self, request, building_id): """HTTP PUT request. @@ -71,17 +47,23 @@ class ProformaInputs(View): 'anticipated_construction_period': put['anticipated_construction_period'], }) if form.is_valid(): - try: - self.handle_form(put, building_id) - except Exception as err: - print('Error saving to database.') - print(err.args[0]) - return JsonResponse({'error': 'Could not save because of database issue'}, status=500) + self.financing_model.objects.update_or_create( + building_id=building_id, + defaults={ + 'building_id': building_id, + 'fund_id': put['fund'], + 'pro_forma_start_date': put['pro_forma_start_date'], + 'pro_forma_duration': put['pro_forma_duration'], + 'analysis_date': put['analysis_date'], + 'anticipated_construction_start_date': put['anticipated_construction_start_date'], + 'anticipated_commissioning_date': put['anticipated_commissioning_date'], + 'anticipated_construction_period': put['anticipated_construction_period'], + } + ) else: error_dict = {} for field, error in form.errors.items(): error_dict[field] = error - print(error_dict) return JsonResponse(error_dict, status=400) return JsonResponse({}) -- GitLab From 60bba470711872ac7ea7f2cc0607849b330e0f27 Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Wed, 31 May 2017 14:39:29 -0400 Subject: [PATCH 03/21] Remove blank line. Add some comments. --- blocnote/apps/financialInputs/views/proforma_input.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/blocnote/apps/financialInputs/views/proforma_input.py b/blocnote/apps/financialInputs/views/proforma_input.py index 1a1db96..6b99ab3 100644 --- a/blocnote/apps/financialInputs/views/proforma_input.py +++ b/blocnote/apps/financialInputs/views/proforma_input.py @@ -4,7 +4,6 @@ from django.views import View from django.http import JsonResponse from blocnote.apps.financialInputs.models import FinancingOverview from blocnote.apps.financialInputs.models import Fund - from blocnote.apps.financialInputs import forms @@ -46,6 +45,7 @@ class ProformaInputs(View): 'anticipated_commissioning_date': put['anticipated_commissioning_date'], 'anticipated_construction_period': put['anticipated_construction_period'], }) + # validate the received form. if form.is_valid(): self.financing_model.objects.update_or_create( building_id=building_id, @@ -61,6 +61,7 @@ class ProformaInputs(View): } ) else: + # construct an error dictionary to send to frontend if form is not valid. error_dict = {} for field, error in form.errors.items(): error_dict[field] = error -- GitLab From 290d6c82d8c66c302f5807c96d986eb29abf9864 Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Wed, 31 May 2017 14:46:49 -0400 Subject: [PATCH 04/21] Create new javascript file to manage the proforma inputs form frontend. Use strict to ensure that all variables are declared. Use only const or let instead of var. Use the javascript date object to compare dates and perform validations. Display input specific errors next to it. Check for error on GET and display error message if there is an error. --- .../financialInputs/scripts/proformaInputs.js | 172 ++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 blocnote/apps/financialInputs/static/financialInputs/scripts/proformaInputs.js diff --git a/blocnote/apps/financialInputs/static/financialInputs/scripts/proformaInputs.js b/blocnote/apps/financialInputs/static/financialInputs/scripts/proformaInputs.js new file mode 100644 index 0000000..e52dac3 --- /dev/null +++ b/blocnote/apps/financialInputs/static/financialInputs/scripts/proformaInputs.js @@ -0,0 +1,172 @@ +'use strict' +getBillProjectionDatesForm(); +const ERROR_TAGS = [ + 'pro_forma_start_date-error', + 'pro_forma_duration-error', + 'analysis_date-error', + 'fund-error', + 'anticipated_construction_start_date-error', + 'anticipated_commissioning_date-error', + 'anticipated_construction_period-error' +] +/** + * proformaForm will watch the form and if it changes, it will remove the response message is it was displayed. + */ +let proformaForm = document.querySelector('#pro-forma-form'); +proformaForm.onchange = function() { + document.querySelector('#pro-forma-form-save-msg').innerHTML = ''; + for (index in ERROR_TAGS) { + document.querySelector('#'+ERROR_TAGS[index]).innerHTML = ''; + } +} + +/** + * The following 2 functions display a warning message saying if fund is changed, it will affect the loan options. + * This message is displayed when the mouse is over the fund select box. + */ +let fund = document.querySelector('#id_fund'); +/** + * This is to watch if fund value is changed. If it did, it would affect loan options. + */ +let didFundChange = false; +fund.onmouseenter = function() { + document.querySelector('#show-error').innerHTML = ` + Changing fund will affect loan options + `; +} + +fund.onmouseleave = function() { + document.querySelector('#show-error').innerHTML = ``; +} + +fund.onchange = function() { + didFundChange = true; +} + +/** + * HTTP GET request to fetch the proforma form information from the database if preent. It would receive the list of + * funds along with. + */ +function getBillProjectionDatesForm() { + request(`finance-overview`, { + method: 'GET', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json' + }, + }).then(res => { + if (!res.err) { + let fundDropBox = document.querySelector('#id_fund-select'); + const funds = res.payload.instance.funds; + // Load fund dropdown box with the list of funds received. + for (let fundIndex = 0; fundIndex < funds.length; fundIndex++) { + fundDropBox.innerHTML += ` + + `; + } + // Load all the values if previously filled. + if (res.payload.instance.financing_overview_data) { + const financingOverviewData = res.payload.instance.financing_overview_data; + proformaForm.querySelector('#pro-forma-date-input').value = financingOverviewData.pro_forma_start_date; + proformaForm.querySelector('#pro-forma-duration-input').value = financingOverviewData.pro_forma_duration; + proformaForm.querySelector('#analysis-date-input').value = financingOverviewData.analysis_date; + proformaForm.querySelector('#id_fund-select').value = financingOverviewData.fund; + proformaForm.querySelector('#anticipated-construction-start-date-input').value = financingOverviewData.anticipated_construction_start_date; + proformaForm.querySelector('#anticipated-commissioning-date-input').value = financingOverviewData.anticipated_commissioning_date; + proformaForm.querySelector('#anticipated-construction-period-input').value = financingOverviewData.anticipated_construction_period; + } + } + else { + // Display error message if error on load. + document.querySelector('#pro-forma-form-save-msg').innerHTML = ` + Sorry, there was an error loading. + `; + } + }); +} + +/** + * Handle submition of the Proforma form. Validate commissioning date is greater than construction start date. Create + * result dictionary containing the form data and convert into JSON to send to the backend. Upon success, load the + * loan options table with the saved fund if fund changed or saving this form for the first time. + */ +function billProjectionDatesForm(form) { + const proFormaStartDate = proformaForm.querySelector('#pro-forma-date-input').value; + const proFormaDuration = proformaForm.querySelector('#pro-forma-duration-input').value; + const analysisDate = proformaForm.querySelector('#analysis-date-input').value; + const fund = proformaForm.querySelector('#id_fund-select').value; + const anticipatedConstructionStartDate = proformaForm.querySelector('#anticipated-construction-start-date-input').value; + const anticipatedCommissioningDate = proformaForm.querySelector('#anticipated-commissioning-date-input').value; + const anticipatedConstructionPeriod = proformaForm.querySelector('#anticipated-construction-period-input').value; + const constructionStartDate = new Date(anticipatedCommissioningDate); + const constructionCommissioningDate = new Date(anticipatedConstructionStartDate) + // Make sure construction commision date is afer construction start date. + if (constructionStartDate < constructionCommissioningDate) { + document.querySelector('#pro-forma-form-save-msg').innerHTML = ` + + Anticipated Commissioning date has to be after Anticipated Construction start date + + `; + } + else { + result = { + 'pro_forma_start_date': proFormaStartDate, + 'pro_forma_duration': proFormaDuration, + 'analysis_date': analysisDate, + 'fund': fund, + 'anticipated_construction_start_date': anticipatedConstructionStartDate, + 'anticipated_commissioning_date': anticipatedCommissioningDate, + 'anticipated_construction_period': anticipatedConstructionPeriod, + } + request('finance-overview/', { + method: 'PUT', + credentials: 'same-origin', + body: JSON.stringify(result), + headers: new Headers({ + 'Content-Type': 'application/json', + 'X-CSRFToken': Cookies.get('csrftoken') + }) + }).then(res => { + let displayMessage = document.querySelector('#pro-forma-form-save-msg'); + if (!res.err) { + // Display response message. Add that loan options changed if fund was changed. Reset didFundChange to false. + responseMessage = 'Saved. '; + if (didFundChange) { + responseMessage += 'Loan Options table is reloaded.'; + } + displayMessage.innerHTML = `${responseMessage}`; + /** + * delete-loan-options request to the backend to delete loan options for this building id if previosly stored. + * This ensures that the loan options table is up to date with the latest fund. Clear the loan options table + * and reload with new fund's default loan options. + */ + if (didFundChange) { + didFundChange = false; + request(`loan-options/?loans=delete-loan-options`, { + method: 'GET', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json' + }, + }).then(res => { + let tableBody = document.querySelector('#loan-options-table tbody'); + tableBody.innerHTML = ``; + }); + getLoanOptionsTable(); + } + } + else { + res.err.responseBody.then((error) => { + // Display error message. + errors = [] + for (key in error) { + document.querySelector('#'+key+'-error').innerHTML = ` + ${error[key][0]} + `; + } + }); + } + }); + } + return false; +} -- GitLab From 8d2d7eea04c7367693e0de5def54979cd5142555 Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Thu, 1 Jun 2017 11:36:44 -0400 Subject: [PATCH 05/21] Remove proforma form import in old views. Change comments in proforma view to show proper error status code. --- blocnote/apps/financialInputs/old_views.py | 1 - blocnote/apps/financialInputs/views/proforma_input.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/blocnote/apps/financialInputs/old_views.py b/blocnote/apps/financialInputs/old_views.py index 1f27921..3858428 100644 --- a/blocnote/apps/financialInputs/old_views.py +++ b/blocnote/apps/financialInputs/old_views.py @@ -12,7 +12,6 @@ from bpfin.lib.back_end_call import monthly_bill, prior_income_statement_table from .models import Fund, FinancingOverview, Bills, BillsOverview, CustomerPreference, EstimationAlgorithm from .models import Liabilities, CashBalance, IncomeStatement, LoanOptions, DefaultLoan, Lender, GrowthRate -from .forms import ProformaInputsForm def get_analysis_date(building_id): diff --git a/blocnote/apps/financialInputs/views/proforma_input.py b/blocnote/apps/financialInputs/views/proforma_input.py index 6b99ab3..dc501f1 100644 --- a/blocnote/apps/financialInputs/views/proforma_input.py +++ b/blocnote/apps/financialInputs/views/proforma_input.py @@ -32,7 +32,7 @@ class ProformaInputs(View): building_id: id of the building. Returns: - error: error message with status 500 if saving into database fails. + error: error message with status 400 if form validation fails. Otherwise a status 200. """ put = json.loads(request.body.decode()) -- GitLab From b1a88eaae8a49fd3c7d8b02504a7c42ac4ffebef Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Thu, 1 Jun 2017 15:20:59 -0400 Subject: [PATCH 06/21] Replace some of the for to forEach. Style changes. Compress some of the code. --- .../financialInputs/scripts/proformaInputs.js | 163 ++++++++---------- 1 file changed, 75 insertions(+), 88 deletions(-) diff --git a/blocnote/apps/financialInputs/static/financialInputs/scripts/proformaInputs.js b/blocnote/apps/financialInputs/static/financialInputs/scripts/proformaInputs.js index e52dac3..72bf445 100644 --- a/blocnote/apps/financialInputs/static/financialInputs/scripts/proformaInputs.js +++ b/blocnote/apps/financialInputs/static/financialInputs/scripts/proformaInputs.js @@ -1,4 +1,4 @@ -'use strict' +'use strict'; getBillProjectionDatesForm(); const ERROR_TAGS = [ 'pro_forma_start_date-error', @@ -7,17 +7,17 @@ const ERROR_TAGS = [ 'fund-error', 'anticipated_construction_start_date-error', 'anticipated_commissioning_date-error', - 'anticipated_construction_period-error' -] + 'anticipated_construction_period-error', +]; /** * proformaForm will watch the form and if it changes, it will remove the response message is it was displayed. */ let proformaForm = document.querySelector('#pro-forma-form'); -proformaForm.onchange = function() { +proformaForm.onchange = function () { document.querySelector('#pro-forma-form-save-msg').innerHTML = ''; - for (index in ERROR_TAGS) { - document.querySelector('#'+ERROR_TAGS[index]).innerHTML = ''; - } + ERROR_TAGS.forEach(function (tag) { + document.querySelector('#' + tag).innerHTML = ''; + }); } /** @@ -28,20 +28,20 @@ let fund = document.querySelector('#id_fund'); /** * This is to watch if fund value is changed. If it did, it would affect loan options. */ -let didFundChange = false; -fund.onmouseenter = function() { +let didFundChange = false +fund.onmouseenter = function () { document.querySelector('#show-error').innerHTML = ` Changing fund will affect loan options `; } -fund.onmouseleave = function() { +fund.onmouseleave = function () { document.querySelector('#show-error').innerHTML = ``; } fund.onchange = function() { didFundChange = true; -} +}; /** * HTTP GET request to fetch the proforma form information from the database if preent. It would receive the list of @@ -53,33 +53,30 @@ function getBillProjectionDatesForm() { credentials: 'same-origin', headers: { 'Content-Type': 'application/json' - }, - }).then(res => { + } + }).then( res => { if (!res.err) { - let fundDropBox = document.querySelector('#id_fund-select'); + let fundDropBox = document.querySelector('#fund'); const funds = res.payload.instance.funds; // Load fund dropdown box with the list of funds received. - for (let fundIndex = 0; fundIndex < funds.length; fundIndex++) { + funds.forEach(function (fund) { fundDropBox.innerHTML += ` - + `; - } + }); // Load all the values if previously filled. if (res.payload.instance.financing_overview_data) { const financingOverviewData = res.payload.instance.financing_overview_data; - proformaForm.querySelector('#pro-forma-date-input').value = financingOverviewData.pro_forma_start_date; - proformaForm.querySelector('#pro-forma-duration-input').value = financingOverviewData.pro_forma_duration; - proformaForm.querySelector('#analysis-date-input').value = financingOverviewData.analysis_date; - proformaForm.querySelector('#id_fund-select').value = financingOverviewData.fund; - proformaForm.querySelector('#anticipated-construction-start-date-input').value = financingOverviewData.anticipated_construction_start_date; - proformaForm.querySelector('#anticipated-commissioning-date-input').value = financingOverviewData.anticipated_commissioning_date; - proformaForm.querySelector('#anticipated-construction-period-input').value = financingOverviewData.anticipated_construction_period; + Object.keys(financingOverviewData).forEach(function (key) { + let data = financingOverviewData[key]; + proformaForm.querySelector('#' + key).value = data; + }); + } } - } else { // Display error message if error on load. document.querySelector('#pro-forma-form-save-msg').innerHTML = ` - Sorry, there was an error loading. + Sorry, there was an error loading. `; } }); @@ -89,84 +86,74 @@ function getBillProjectionDatesForm() { * Handle submition of the Proforma form. Validate commissioning date is greater than construction start date. Create * result dictionary containing the form data and convert into JSON to send to the backend. Upon success, load the * loan options table with the saved fund if fund changed or saving this form for the first time. + * + * @param {any} form : Proforma inputs form filled. + * @returns : False so that page does not reload. */ function billProjectionDatesForm(form) { - const proFormaStartDate = proformaForm.querySelector('#pro-forma-date-input').value; - const proFormaDuration = proformaForm.querySelector('#pro-forma-duration-input').value; - const analysisDate = proformaForm.querySelector('#analysis-date-input').value; - const fund = proformaForm.querySelector('#id_fund-select').value; - const anticipatedConstructionStartDate = proformaForm.querySelector('#anticipated-construction-start-date-input').value; - const anticipatedCommissioningDate = proformaForm.querySelector('#anticipated-commissioning-date-input').value; - const anticipatedConstructionPeriod = proformaForm.querySelector('#anticipated-construction-period-input').value; - const constructionStartDate = new Date(anticipatedCommissioningDate); - const constructionCommissioningDate = new Date(anticipatedConstructionStartDate) + const formData = new FormData(form); + let result = {}; + for (let pair of formData.entries()) { + result[pair[0]] = pair[1]; + } + const constructionStartDate = new Date(result.anticipated_construction_start_date); + const constructionCommissioningDate = new Date(result.anticipated_commissioning_date); // Make sure construction commision date is afer construction start date. - if (constructionStartDate < constructionCommissioningDate) { + if (constructionStartDate > constructionCommissioningDate) { document.querySelector('#pro-forma-form-save-msg').innerHTML = ` Anticipated Commissioning date has to be after Anticipated Construction start date `; + return false; } - else { - result = { - 'pro_forma_start_date': proFormaStartDate, - 'pro_forma_duration': proFormaDuration, - 'analysis_date': analysisDate, - 'fund': fund, - 'anticipated_construction_start_date': anticipatedConstructionStartDate, - 'anticipated_commissioning_date': anticipatedCommissioningDate, - 'anticipated_construction_period': anticipatedConstructionPeriod, - } - request('finance-overview/', { - method: 'PUT', - credentials: 'same-origin', - body: JSON.stringify(result), - headers: new Headers({ - 'Content-Type': 'application/json', - 'X-CSRFToken': Cookies.get('csrftoken') + request('finance-overview/', { + method: 'PUT', + credentials: 'same-origin', + body: JSON.stringify(result), + headers: new Headers({ + 'Content-Type': 'application/json', + 'X-CSRFToken': Cookies.get('csrftoken') }) - }).then(res => { - let displayMessage = document.querySelector('#pro-forma-form-save-msg'); - if (!res.err) { - // Display response message. Add that loan options changed if fund was changed. Reset didFundChange to false. - responseMessage = 'Saved. '; - if (didFundChange) { - responseMessage += 'Loan Options table is reloaded.'; + }).then( res => { + let displayMessage = document.querySelector('#pro-forma-form-save-msg'); + if (!res.err) { + // Display response message. Add that loan options changed if fund was changed. Reset didFundChange to false. + let responseMessage = 'Saved. '; + if (didFundChange) { + responseMessage += 'Loan Options table is reloaded.'; } - displayMessage.innerHTML = `${responseMessage}`; - /** - * delete-loan-options request to the backend to delete loan options for this building id if previosly stored. - * This ensures that the loan options table is up to date with the latest fund. Clear the loan options table - * and reload with new fund's default loan options. - */ - if (didFundChange) { - didFundChange = false; - request(`loan-options/?loans=delete-loan-options`, { - method: 'GET', - credentials: 'same-origin', - headers: { - 'Content-Type': 'application/json' - }, - }).then(res => { + displayMessage.innerHTML = `${responseMessage}`; + /** + * delete-loan-options request to the backend to delete loan options for this building id if previosly stored. + * This ensures that the loan options table is up to date with the latest fund. Clear the loan options table + * and reload with new fund's default loan options. + */ + if (didFundChange) { + didFundChange = false; + request(`loan-options/?loans=delete-loan-options`, { + method: 'GET', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json' + } + }).then( res => { let tableBody = document.querySelector('#loan-options-table tbody'); tableBody.innerHTML = ``; }); - getLoanOptionsTable(); - } + getLoanOptionsTable(); } - else { - res.err.responseBody.then((error) => { - // Display error message. - errors = [] - for (key in error) { - document.querySelector('#'+key+'-error').innerHTML = ` + } + else { + res.err.responseBody.then((error) => { + // Display error message. + Object.keys(error).forEach(function (key) { + document.querySelector('#' + key + '-error').innerHTML = ` ${error[key][0]} `; - } - }); - } - }); - } + }) + }); + } + }); return false; } -- GitLab From 9ec90d4cf1708519c7bc914bd757efded9058dc5 Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Thu, 1 Jun 2017 15:22:14 -0400 Subject: [PATCH 07/21] Make changes to the input field to have both name and id to be same as the field names on backend so that we can use the formdata. --- .../templates/financialInputs/proFormaForm.html | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/blocnote/apps/financialInputs/templates/financialInputs/proFormaForm.html b/blocnote/apps/financialInputs/templates/financialInputs/proFormaForm.html index 9ec108e..b83ed05 100644 --- a/blocnote/apps/financialInputs/templates/financialInputs/proFormaForm.html +++ b/blocnote/apps/financialInputs/templates/financialInputs/proFormaForm.html @@ -4,13 +4,13 @@
Pro Forma Start date - +
Pro Forma Duration (years) - +
@@ -20,13 +20,13 @@
Analysis Date - +
Fund -
@@ -39,13 +39,13 @@
Anticipated Construction Start Date - +
Anticipated Commissioning Date - +
@@ -55,7 +55,7 @@
Anticipated Construction Period (weeks) - +
-- GitLab From 3f385b48ebae9c910bef2418028aaedec6f2b809 Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Thu, 1 Jun 2017 15:22:49 -0400 Subject: [PATCH 08/21] Reorder the import statements. --- blocnote/apps/financialInputs/views/proforma_input.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/blocnote/apps/financialInputs/views/proforma_input.py b/blocnote/apps/financialInputs/views/proforma_input.py index dc501f1..dbbe690 100644 --- a/blocnote/apps/financialInputs/views/proforma_input.py +++ b/blocnote/apps/financialInputs/views/proforma_input.py @@ -1,10 +1,11 @@ """Route for Proforma Inputs.""" import json -from django.views import View + from django.http import JsonResponse -from blocnote.apps.financialInputs.models import FinancingOverview -from blocnote.apps.financialInputs.models import Fund +from django.views import View + from blocnote.apps.financialInputs import forms +from blocnote.apps.financialInputs.models import FinancingOverview, Fund class ProformaInputs(View): -- GitLab From e5375f7c64abf089ecc7213dd6ef144b7c0d3409 Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Thu, 1 Jun 2017 15:24:46 -0400 Subject: [PATCH 09/21] Fix some indentation issues. --- .../static/financialInputs/scripts/proformaInputs.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blocnote/apps/financialInputs/static/financialInputs/scripts/proformaInputs.js b/blocnote/apps/financialInputs/static/financialInputs/scripts/proformaInputs.js index 72bf445..1b48758 100644 --- a/blocnote/apps/financialInputs/static/financialInputs/scripts/proformaInputs.js +++ b/blocnote/apps/financialInputs/static/financialInputs/scripts/proformaInputs.js @@ -70,9 +70,9 @@ function getBillProjectionDatesForm() { Object.keys(financingOverviewData).forEach(function (key) { let data = financingOverviewData[key]; proformaForm.querySelector('#' + key).value = data; - }); - } + }); } + } else { // Display error message if error on load. document.querySelector('#pro-forma-form-save-msg').innerHTML = ` -- GitLab From 884364daad14ee2068e410c56424f36f62bfaace Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Thu, 1 Jun 2017 15:26:52 -0400 Subject: [PATCH 10/21] Fix some indentation issues. --- .../static/financialInputs/scripts/proformaInputs.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blocnote/apps/financialInputs/static/financialInputs/scripts/proformaInputs.js b/blocnote/apps/financialInputs/static/financialInputs/scripts/proformaInputs.js index 1b48758..a2f42bc 100644 --- a/blocnote/apps/financialInputs/static/financialInputs/scripts/proformaInputs.js +++ b/blocnote/apps/financialInputs/static/financialInputs/scripts/proformaInputs.js @@ -114,7 +114,7 @@ function billProjectionDatesForm(form) { headers: new Headers({ 'Content-Type': 'application/json', 'X-CSRFToken': Cookies.get('csrftoken') - }) + }) }).then( res => { let displayMessage = document.querySelector('#pro-forma-form-save-msg'); if (!res.err) { @@ -122,7 +122,7 @@ function billProjectionDatesForm(form) { let responseMessage = 'Saved. '; if (didFundChange) { responseMessage += 'Loan Options table is reloaded.'; - } + } displayMessage.innerHTML = `${responseMessage}`; /** * delete-loan-options request to the backend to delete loan options for this building id if previosly stored. -- GitLab From 19b2c45b40dc570dc9245a3d749f885d8e74bd46 Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Tue, 6 Jun 2017 09:48:34 -0400 Subject: [PATCH 11/21] Add first test for financial-overview route. --- blocnote/apps/financialInputs/tests.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/blocnote/apps/financialInputs/tests.py b/blocnote/apps/financialInputs/tests.py index 7ce503c..8921f38 100644 --- a/blocnote/apps/financialInputs/tests.py +++ b/blocnote/apps/financialInputs/tests.py @@ -1,3 +1,27 @@ +"""Tests for all the views in financialInputs.""" +import json + from django.test import TestCase -# Create your tests here. +from .models import Fund + + +class ProformaInputsViewTest(TestCase): + """Test the proforma_inputs view for GET and PUT routes.""" + + def test_financial_inputs_view_1(self): + """Test the GET route. + + Test GET route when database is completely empty for a building. + """ + response = self.client.get('/buildings/3000/financial-inputs/finance-overview/') + response_content = json.loads(response.content) + expected_response_content = { + 'instance': { + 'funds': [], + }, + } + self.assertEqual(response.status_code, 200) + self.assertTrue('instance' in response_content) + self.assertEqual(response_content, expected_response_content) + -- GitLab From a67cd52758730b1554c021af4b34bf19cbdddabf Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Tue, 6 Jun 2017 11:33:00 -0400 Subject: [PATCH 12/21] More tests. --- blocnote/apps/financialInputs/tests.py | 248 ++++++++++++++++++++++++- 1 file changed, 244 insertions(+), 4 deletions(-) diff --git a/blocnote/apps/financialInputs/tests.py b/blocnote/apps/financialInputs/tests.py index 8921f38..054671b 100644 --- a/blocnote/apps/financialInputs/tests.py +++ b/blocnote/apps/financialInputs/tests.py @@ -3,25 +3,265 @@ import json from django.test import TestCase -from .models import Fund +from .models import Fund, FinancingOverview +PROFORMA_START_DATE = '2014-01-01' +ANALYSIS_DATE = '2017-06-06' +CONSTRUCTION_START_DATE = '2017-07-01' +COMMISSIONING_DATE = '2017-08-01' class ProformaInputsViewTest(TestCase): """Test the proforma_inputs view for GET and PUT routes.""" - def test_financial_inputs_view_1(self): + def setUp(self): + """Create 3 funds as it is building independent.""" + Fund.objects.create(Name='Fund1') + Fund.objects.create(Name='Fund2') + Fund.objects.create(Name='Fund3') + + def test_finance_overview_get_1(self): """Test the GET route. - Test GET route when database is completely empty for a building. + Test GET route when database is completely empty for a building except for the funds. This should return + a response with just the funds as a list of tuples with its id and name. This funds is in a dictionary called + instance. + """ + response = self.client.get('/buildings/3000/financial-inputs/finance-overview/') + response_content = json.loads(response.content) + expected_response_content = { + 'instance': { + 'funds': [ + (1, 'Fund1'), + (2, 'Fund2'), + (3, 'Fund3'), + ], + }, + } + self.assertEqual(response.status_code, 200) + self.assertTrue('instance' in response_content) + self.assertEqual(response_content, expected_response_content) + + def test_finance_overview_get_2(self): + """Test GET route. + + Create financing overview record for the building and then perform a GET request. This should return a response + as a dictionary with funds as a list of tuples with fund id and name and the rest of the data for a key called + financing_overview_data. """ + fund = Fund.objects.get(Name='Fund2') + FinancingOverview.objects.create( + building_id=3000, + fund=fund, + pro_forma_start_date=PROFORMA_START_DATE, + pro_forma_duration=25, + analysis_date=ANALYSIS_DATE, + anticipated_construction_start_date=CONSTRUCTION_START_DATE, + anticipated_commissioning_date=COMMISSIONING_DATE, + anticipated_construction_period=4 + ) response = self.client.get('/buildings/3000/financial-inputs/finance-overview/') response_content = json.loads(response.content) expected_response_content = { 'instance': { - 'funds': [], + 'funds': [ + (1, 'Fund1'), + (2, 'Fund2'), + (3, 'Fund3'), + ], + 'financing_overview_data': { + 'fund': 2, + 'pro_forma_start_date': PROFORMA_START_DATE, + 'pro_forma_duration': 25, + 'analysis_date': ANALYSIS_DATE, + 'anticipated_construction_start_date': CONSTRUCTION_START_DATE, + 'anticipated_commissioning_date': COMMISSIONING_DATE, + 'anticipated_construction_period': 4, + }, }, } self.assertEqual(response.status_code, 200) self.assertTrue('instance' in response_content) self.assertEqual(response_content, expected_response_content) + def test_finance_overview_put_1(self): + """Test the PUT route. + + Test PUT route when empty content is sent. This should do nothing. + """ + response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps({})) + response_content = json.loads(reponse.content) + expected_response_content = { + 'error': 'Empty form was received.', + } + self.assertEqual(response.status_code, 400) + self.assertTrue('error' in response_content) + self.assertEqual(response_content, expected_response_content) + + def test_finance_overview_put_2(self): + """Test the PUT route. + + Test PUT route when correct content is sent. This should do nothing. + """ + content = { + 'fund': 1, + 'pro_forma_start_date': PROFORMA_START_DATE, + 'pro_forma_duration': 25, + 'analysis_date': ANALYSIS_DATE, + 'anticipated_construction_start_date': CONSTRUCTION_START_DATE, + 'anticipated_commissioning_date': COMMISSIONING_DATE, + 'anticipated_construction_period': 4, + } + response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.content, {}) + + def test_finance_overview_put_3(self): + """Test PUT route. + + Test the PUT route with construction start date as empty. + """ + content = { + 'fund': 1, + 'pro_forma_start_date': PROFORMA_START_DATE, + 'pro_forma_duration': 25, + 'analysis_date': ANALYSIS_DATE, + 'anticipated_construction_start_date': '', + 'anticipated_commissioning_date': COMMISSIONING_DATE, + 'anticipated_construction_period': 4, + } + response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) + response_content = json.loads(reponse.content) + self.assertEqual(response.status_code, 400) + self.assertTrue('anticipated_construction_start_date' in response_content) + + def test_finance_overview_put_4(self): + """Test PUT route. + + Test the PUT route with commissioning date as empty. + """ + content = { + 'fund': 1, + 'pro_forma_start_date': PROFORMA_START_DATE, + 'pro_forma_duration': 25, + 'analysis_date': ANALYSIS_DATE, + 'anticipated_construction_start_date': CONSTRUCTION_START_DATE, + 'anticipated_commissioning_date': '', + 'anticipated_construction_period': 4, + } + response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) + response_content = json.loads(reponse.content) + self.assertEqual(response.status_code, 400) + self.assertTrue('anticipated_commissioning_date' in response_content) + + def test_finance_overview_put_5(self): + """Test PUT route. + + Test the PUT route with proforma start date as empty. + """ + content = { + 'fund': 1, + 'pro_forma_start_date': '', + 'pro_forma_duration': 25, + 'analysis_date': ANALYSIS_DATE, + 'anticipated_construction_start_date': CONSTRUCTION_START_DATE, + 'anticipated_commissioning_date': COMMISSIONING_DATE, + 'anticipated_construction_period': 4, + } + response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) + response_content = json.loads(reponse.content) + self.assertEqual(response.status_code, 400) + self.assertTrue('pro_forma_start_date' in response_content) + + def test_finance_overview_put_6(self): + """Test PUT route. + + Test the PUT route with proforma duration as empty. + """ + content = { + 'fund': 1, + 'pro_forma_start_date': PROFORMA_START_DATE, + 'pro_forma_duration': '', + 'analysis_date': ANALYSIS_DATE, + 'anticipated_construction_start_date': CONSTRUCTION_START_DATE, + 'anticipated_commissioning_date': COMMISSIONING_DATE, + 'anticipated_construction_period': 4, + } + response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) + response_content = json.loads(reponse.content) + self.assertEqual(response.status_code, 400) + self.assertTrue('pro_forma_duration' in response_content) + + def test_finance_overview_put_7(self): + """Test PUT route. + + Test the PUT route with analysis date as empty. + """ + content = { + 'fund': 1, + 'pro_forma_start_date': PROFORMA_START_DATE, + 'pro_forma_duration': 25, + 'analysis_date': '', + 'anticipated_construction_start_date': CONSTRUCTION_START_DATE, + 'anticipated_commissioning_date': COMMISSIONING_DATE, + 'anticipated_construction_period': 4, + } + response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) + response_content = json.loads(reponse.content) + self.assertEqual(response.status_code, 400) + self.assertTrue('analysis_date' in response_content) + + def test_finance_overview_put_8(self): + """Test PUT route. + + Test the PUT route with construction period as empty. + """ + content = { + 'fund': 1, + 'pro_forma_start_date': PROFORMA_START_DATE, + 'pro_forma_duration': 25, + 'analysis_date': ANALYSIS_DATE, + 'anticipated_construction_start_date': CONSTRUCTION_START_DATE, + 'anticipated_commissioning_date': COMMISSIONING_DATE, + 'anticipated_construction_period': '', + } + response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) + response_content = json.loads(reponse.content) + self.assertEqual(response.status_code, 400) + self.assertTrue('anticipated_construction_period' in response_content) + + def test_finance_overview_put_9(self): + """Test PUT route. + + Test the PUT route with fund as empty. + """ + content = { + 'fund': '', + 'pro_forma_start_date': PROFORMA_START_DATE, + 'pro_forma_duration': 25, + 'analysis_date': ANALYSIS_DATE, + 'anticipated_construction_start_date': CONSTRUCTION_START_DATE, + 'anticipated_commissioning_date': COMMISSIONING_DATE, + 'anticipated_construction_period': 4, + } + response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) + response_content = json.loads(reponse.content) + self.assertEqual(response.status_code, 400) + self.assertTrue('fund' in response_content) + + def test_finance_overview_put_10(self): + """Test PUT route. + + Test the PUT route with fund as missing. + """ + content = { + 'pro_forma_start_date': PROFORMA_START_DATE, + 'pro_forma_duration': 25, + 'analysis_date': ANALYSIS_DATE, + 'anticipated_construction_start_date': CONSTRUCTION_START_DATE, + 'anticipated_commissioning_date': COMMISSIONING_DATE, + 'anticipated_construction_period': 4, + } + response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) + response_content = json.loads(reponse.content) + self.assertEqual(response.status_code, 400) + self.assertTrue('error' in response_content) -- GitLab From 6a95c8c0e4bd238c70a868c117454df9f077a01e Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Wed, 7 Jun 2017 16:05:02 -0400 Subject: [PATCH 13/21] Add proforma inputs to settings for coverage. --- blocnote/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blocnote/settings.py b/blocnote/settings.py index bed7ab2..91909c0 100644 --- a/blocnote/settings.py +++ b/blocnote/settings.py @@ -82,7 +82,7 @@ TEST_RUNNER = 'django_nose.NoseTestSuiteRunner' # Tell nose to measure coverage on the 'foo' and 'bar' apps NOSE_ARGS = [ '--with-coverage', - '--cover-package=blocnote.apps.budgetSimulator', + '--cover-package=blocnote.apps.budgetSimulator,blocnote.apps.financialInputs', ] WSGI_APPLICATION = 'blocnote.wsgi.application' -- GitLab From 2691b817cb9d822e5c9f0d2f3fe1f7cb9b666b73 Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Wed, 7 Jun 2017 16:06:00 -0400 Subject: [PATCH 14/21] Update tests to get rid of errors. --- blocnote/apps/financialInputs/tests.py | 96 ++++++++++---------------- 1 file changed, 37 insertions(+), 59 deletions(-) diff --git a/blocnote/apps/financialInputs/tests.py b/blocnote/apps/financialInputs/tests.py index 054671b..29b10c9 100644 --- a/blocnote/apps/financialInputs/tests.py +++ b/blocnote/apps/financialInputs/tests.py @@ -10,17 +10,18 @@ ANALYSIS_DATE = '2017-06-06' CONSTRUCTION_START_DATE = '2017-07-01' COMMISSIONING_DATE = '2017-08-01' + class ProformaInputsViewTest(TestCase): """Test the proforma_inputs view for GET and PUT routes.""" def setUp(self): """Create 3 funds as it is building independent.""" - Fund.objects.create(Name='Fund1') - Fund.objects.create(Name='Fund2') - Fund.objects.create(Name='Fund3') + Fund.objects.create(id=1, Name='Fund1') + Fund.objects.create(id=2, Name='Fund2') + Fund.objects.create(id=3, Name='Fund3') def test_finance_overview_get_1(self): - """Test the GET route. + """Test the GET route when database is empty. Test GET route when database is completely empty for a building except for the funds. This should return a response with just the funds as a list of tuples with its id and name. This funds is in a dictionary called @@ -31,9 +32,9 @@ class ProformaInputsViewTest(TestCase): expected_response_content = { 'instance': { 'funds': [ - (1, 'Fund1'), - (2, 'Fund2'), - (3, 'Fund3'), + [1, 'Fund1'], + [2, 'Fund2'], + [3, 'Fund3'], ], }, } @@ -42,7 +43,7 @@ class ProformaInputsViewTest(TestCase): self.assertEqual(response_content, expected_response_content) def test_finance_overview_get_2(self): - """Test GET route. + """Test GET route with proper financing overview data. Create financing overview record for the building and then perform a GET request. This should return a response as a dictionary with funds as a list of tuples with fund id and name and the rest of the data for a key called @@ -60,22 +61,22 @@ class ProformaInputsViewTest(TestCase): anticipated_construction_period=4 ) response = self.client.get('/buildings/3000/financial-inputs/finance-overview/') - response_content = json.loads(response.content) + response_content = response.json() expected_response_content = { 'instance': { 'funds': [ - (1, 'Fund1'), - (2, 'Fund2'), - (3, 'Fund3'), + [1, 'Fund1'], + [2, 'Fund2'], + [3, 'Fund3'], ], 'financing_overview_data': { 'fund': 2, 'pro_forma_start_date': PROFORMA_START_DATE, - 'pro_forma_duration': 25, + 'pro_forma_duration': '25', 'analysis_date': ANALYSIS_DATE, 'anticipated_construction_start_date': CONSTRUCTION_START_DATE, 'anticipated_commissioning_date': COMMISSIONING_DATE, - 'anticipated_construction_period': 4, + 'anticipated_construction_period': '4', }, }, } @@ -84,21 +85,21 @@ class ProformaInputsViewTest(TestCase): self.assertEqual(response_content, expected_response_content) def test_finance_overview_put_1(self): - """Test the PUT route. + """Test the PUT route when empty content is sent. Test PUT route when empty content is sent. This should do nothing. """ response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps({})) - response_content = json.loads(reponse.content) + response_content = json.loads(response.content) expected_response_content = { - 'error': 'Empty form was received.', + 'error': 'Missing data in form', } self.assertEqual(response.status_code, 400) self.assertTrue('error' in response_content) self.assertEqual(response_content, expected_response_content) def test_finance_overview_put_2(self): - """Test the PUT route. + """Test the PUT route when correct content is sent. Test PUT route when correct content is sent. This should do nothing. """ @@ -112,14 +113,12 @@ class ProformaInputsViewTest(TestCase): 'anticipated_construction_period': 4, } response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) + response_content = response.json() self.assertEqual(response.status_code, 200) - self.assertEqual(response.content, {}) + self.assertEqual(response_content, {}) def test_finance_overview_put_3(self): - """Test PUT route. - - Test the PUT route with construction start date as empty. - """ + """Test PUT route when construction start date is empty.""" content = { 'fund': 1, 'pro_forma_start_date': PROFORMA_START_DATE, @@ -130,15 +129,12 @@ class ProformaInputsViewTest(TestCase): 'anticipated_construction_period': 4, } response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) - response_content = json.loads(reponse.content) + response_content = json.loads(response.content) self.assertEqual(response.status_code, 400) self.assertTrue('anticipated_construction_start_date' in response_content) def test_finance_overview_put_4(self): - """Test PUT route. - - Test the PUT route with commissioning date as empty. - """ + """Test PUT route when commissioning date is empty.""" content = { 'fund': 1, 'pro_forma_start_date': PROFORMA_START_DATE, @@ -149,15 +145,12 @@ class ProformaInputsViewTest(TestCase): 'anticipated_construction_period': 4, } response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) - response_content = json.loads(reponse.content) + response_content = json.loads(response.content) self.assertEqual(response.status_code, 400) self.assertTrue('anticipated_commissioning_date' in response_content) def test_finance_overview_put_5(self): - """Test PUT route. - - Test the PUT route with proforma start date as empty. - """ + """Test PUT route when proforma start date is empty.""" content = { 'fund': 1, 'pro_forma_start_date': '', @@ -168,15 +161,12 @@ class ProformaInputsViewTest(TestCase): 'anticipated_construction_period': 4, } response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) - response_content = json.loads(reponse.content) + response_content = json.loads(response.content) self.assertEqual(response.status_code, 400) self.assertTrue('pro_forma_start_date' in response_content) def test_finance_overview_put_6(self): - """Test PUT route. - - Test the PUT route with proforma duration as empty. - """ + """Test PUT route when proforma duration is empty.""" content = { 'fund': 1, 'pro_forma_start_date': PROFORMA_START_DATE, @@ -187,15 +177,12 @@ class ProformaInputsViewTest(TestCase): 'anticipated_construction_period': 4, } response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) - response_content = json.loads(reponse.content) + response_content = json.loads(response.content) self.assertEqual(response.status_code, 400) self.assertTrue('pro_forma_duration' in response_content) def test_finance_overview_put_7(self): - """Test PUT route. - - Test the PUT route with analysis date as empty. - """ + """Test PUT route when analysis date is empty.""" content = { 'fund': 1, 'pro_forma_start_date': PROFORMA_START_DATE, @@ -206,15 +193,12 @@ class ProformaInputsViewTest(TestCase): 'anticipated_construction_period': 4, } response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) - response_content = json.loads(reponse.content) + response_content = json.loads(response.content) self.assertEqual(response.status_code, 400) self.assertTrue('analysis_date' in response_content) def test_finance_overview_put_8(self): - """Test PUT route. - - Test the PUT route with construction period as empty. - """ + """Test PUT route when construction period is empty.""" content = { 'fund': 1, 'pro_forma_start_date': PROFORMA_START_DATE, @@ -225,15 +209,12 @@ class ProformaInputsViewTest(TestCase): 'anticipated_construction_period': '', } response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) - response_content = json.loads(reponse.content) + response_content = json.loads(response.content) self.assertEqual(response.status_code, 400) self.assertTrue('anticipated_construction_period' in response_content) def test_finance_overview_put_9(self): - """Test PUT route. - - Test the PUT route with fund as empty. - """ + """Test PUT route with fund as empty.""" content = { 'fund': '', 'pro_forma_start_date': PROFORMA_START_DATE, @@ -244,15 +225,12 @@ class ProformaInputsViewTest(TestCase): 'anticipated_construction_period': 4, } response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) - response_content = json.loads(reponse.content) + response_content = json.loads(response.content) self.assertEqual(response.status_code, 400) self.assertTrue('fund' in response_content) def test_finance_overview_put_10(self): - """Test PUT route. - - Test the PUT route with fund as missing. - """ + """Test PUT route when fund is missing.""" content = { 'pro_forma_start_date': PROFORMA_START_DATE, 'pro_forma_duration': 25, @@ -262,6 +240,6 @@ class ProformaInputsViewTest(TestCase): 'anticipated_construction_period': 4, } response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) - response_content = json.loads(reponse.content) + response_content = json.loads(response.content) self.assertEqual(response.status_code, 400) self.assertTrue('error' in response_content) -- GitLab From 85ba2cc06abbaa460763674fa122fd794353ba3b Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Wed, 7 Jun 2017 16:06:30 -0400 Subject: [PATCH 15/21] Update proforma_input to pass tests. --- .../financialInputs/views/proforma_input.py | 66 ++++++++++--------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/blocnote/apps/financialInputs/views/proforma_input.py b/blocnote/apps/financialInputs/views/proforma_input.py index dbbe690..7516b72 100644 --- a/blocnote/apps/financialInputs/views/proforma_input.py +++ b/blocnote/apps/financialInputs/views/proforma_input.py @@ -21,6 +21,7 @@ class ProformaInputs(View): fund_model = Fund financing_model = FinancingOverview proforma_inputs_form = forms.ProformaInputsForm + form_length = 7 def put(self, request, building_id): """HTTP PUT request. @@ -37,37 +38,42 @@ class ProformaInputs(View): Otherwise a status 200. """ put = json.loads(request.body.decode()) - form = self.proforma_inputs_form({ - 'fund': put['fund'], - 'pro_forma_start_date': put['pro_forma_start_date'], - 'pro_forma_duration': put['pro_forma_duration'], - 'analysis_date': put['analysis_date'], - 'anticipated_construction_start_date': put['anticipated_construction_start_date'], - 'anticipated_commissioning_date': put['anticipated_commissioning_date'], - 'anticipated_construction_period': put['anticipated_construction_period'], - }) - # validate the received form. - if form.is_valid(): - self.financing_model.objects.update_or_create( - building_id=building_id, - defaults={ - 'building_id': building_id, - 'fund_id': put['fund'], - 'pro_forma_start_date': put['pro_forma_start_date'], - 'pro_forma_duration': put['pro_forma_duration'], - 'analysis_date': put['analysis_date'], - 'anticipated_construction_start_date': put['anticipated_construction_start_date'], - 'anticipated_commissioning_date': put['anticipated_commissioning_date'], - 'anticipated_construction_period': put['anticipated_construction_period'], - } - ) + if len(list(put.keys())) == self.form_length: + if put['fund'] is '': + return JsonResponse({'fund': 'Fund cannot be empty.'}, status=400) + form = self.proforma_inputs_form({ + 'fund': put['fund'], + 'pro_forma_start_date': put['pro_forma_start_date'], + 'pro_forma_duration': put['pro_forma_duration'], + 'analysis_date': put['analysis_date'], + 'anticipated_construction_start_date': put['anticipated_construction_start_date'], + 'anticipated_commissioning_date': put['anticipated_commissioning_date'], + 'anticipated_construction_period': put['anticipated_construction_period'], + }) + # validate the received form. + if form.is_valid(): + self.financing_model.objects.update_or_create( + building_id=building_id, + defaults={ + 'building_id': building_id, + 'fund_id': put['fund'], + 'pro_forma_start_date': put['pro_forma_start_date'], + 'pro_forma_duration': put['pro_forma_duration'], + 'analysis_date': put['analysis_date'], + 'anticipated_construction_start_date': put['anticipated_construction_start_date'], + 'anticipated_commissioning_date': put['anticipated_commissioning_date'], + 'anticipated_construction_period': put['anticipated_construction_period'], + } + ) + else: + # construct an error dictionary to send to frontend if form is not valid. + error_dict = {} + for field, error in form.errors.items(): + error_dict[field] = error + return JsonResponse(error_dict, status=400) + return JsonResponse({}) else: - # construct an error dictionary to send to frontend if form is not valid. - error_dict = {} - for field, error in form.errors.items(): - error_dict[field] = error - return JsonResponse(error_dict, status=400) - return JsonResponse({}) + return JsonResponse({'error': 'Missing data in form'}, status=400) def get(self, request, building_id): """HTTP GET request. -- GitLab From c151fbeeabe9f53aefec1af13fb5495b281d61b8 Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Thu, 8 Jun 2017 16:19:26 -0400 Subject: [PATCH 16/21] Change indent in js file to 2. --- .../financialInputs/scripts/proformaInputs.js | 201 +++++++++--------- 1 file changed, 101 insertions(+), 100 deletions(-) diff --git a/blocnote/apps/financialInputs/static/financialInputs/scripts/proformaInputs.js b/blocnote/apps/financialInputs/static/financialInputs/scripts/proformaInputs.js index a2f42bc..25c3322 100644 --- a/blocnote/apps/financialInputs/static/financialInputs/scripts/proformaInputs.js +++ b/blocnote/apps/financialInputs/static/financialInputs/scripts/proformaInputs.js @@ -1,22 +1,23 @@ 'use strict'; + getBillProjectionDatesForm(); const ERROR_TAGS = [ - 'pro_forma_start_date-error', - 'pro_forma_duration-error', - 'analysis_date-error', - 'fund-error', - 'anticipated_construction_start_date-error', - 'anticipated_commissioning_date-error', - 'anticipated_construction_period-error', + 'pro_forma_start_date-error', + 'pro_forma_duration-error', + 'analysis_date-error', + 'fund-error', + 'anticipated_construction_start_date-error', + 'anticipated_commissioning_date-error', + 'anticipated_construction_period-error', ]; /** * proformaForm will watch the form and if it changes, it will remove the response message is it was displayed. */ let proformaForm = document.querySelector('#pro-forma-form'); proformaForm.onchange = function () { - document.querySelector('#pro-forma-form-save-msg').innerHTML = ''; - ERROR_TAGS.forEach(function (tag) { - document.querySelector('#' + tag).innerHTML = ''; + document.querySelector('#pro-forma-form-save-msg').innerHTML = ''; + ERROR_TAGS.forEach(function (tag) { + document.querySelector('#' + tag).innerHTML = ''; }); } @@ -30,17 +31,17 @@ let fund = document.querySelector('#id_fund'); */ let didFundChange = false fund.onmouseenter = function () { - document.querySelector('#show-error').innerHTML = ` + document.querySelector('#show-error').innerHTML = ` Changing fund will affect loan options `; } fund.onmouseleave = function () { - document.querySelector('#show-error').innerHTML = ``; + document.querySelector('#show-error').innerHTML = ``; } -fund.onchange = function() { - didFundChange = true; +fund.onchange = function () { + didFundChange = true; }; /** @@ -48,38 +49,38 @@ fund.onchange = function() { * funds along with. */ function getBillProjectionDatesForm() { - request(`finance-overview`, { - method: 'GET', - credentials: 'same-origin', - headers: { - 'Content-Type': 'application/json' - } - }).then( res => { - if (!res.err) { - let fundDropBox = document.querySelector('#fund'); - const funds = res.payload.instance.funds; - // Load fund dropdown box with the list of funds received. - funds.forEach(function (fund) { - fundDropBox.innerHTML += ` + request(`finance-overview`, { + method: 'GET', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json' + } + }).then(res => { + if (!res.err) { + let fundDropBox = document.querySelector('#fund_id'); + const funds = res.payload.instance.funds; + // Load fund dropdown box with the list of funds received. + funds.forEach(function (fund) { + fundDropBox.innerHTML += ` `; - }); - // Load all the values if previously filled. - if (res.payload.instance.financing_overview_data) { - const financingOverviewData = res.payload.instance.financing_overview_data; - Object.keys(financingOverviewData).forEach(function (key) { - let data = financingOverviewData[key]; - proformaForm.querySelector('#' + key).value = data; - }); - } - } - else { - // Display error message if error on load. - document.querySelector('#pro-forma-form-save-msg').innerHTML = ` + }); + // Load all the values if previously filled. + if (res.payload.instance.financing_overview_data) { + const financingOverviewData = res.payload.instance.financing_overview_data; + Object.keys(financingOverviewData).forEach(function (key) { + let data = financingOverviewData[key]; + proformaForm.querySelector('#' + key).value = data; + }); + } + } + else { + // Display error message if error on load. + document.querySelector('#pro-forma-form-save-msg').innerHTML = ` Sorry, there was an error loading. `; - } - }); + } + }); } /** @@ -91,69 +92,69 @@ function getBillProjectionDatesForm() { * @returns : False so that page does not reload. */ function billProjectionDatesForm(form) { - const formData = new FormData(form); - let result = {}; - for (let pair of formData.entries()) { - result[pair[0]] = pair[1]; - } - const constructionStartDate = new Date(result.anticipated_construction_start_date); - const constructionCommissioningDate = new Date(result.anticipated_commissioning_date); - // Make sure construction commision date is afer construction start date. - if (constructionStartDate > constructionCommissioningDate) { - document.querySelector('#pro-forma-form-save-msg').innerHTML = ` + const formData = new FormData(form); + let result = {}; + for (let pair of formData.entries()) { + result[pair[0]] = pair[1]; + } + const constructionStartDate = new Date(result.anticipated_construction_start_date); + const constructionCommissioningDate = new Date(result.anticipated_commissioning_date); + // Make sure construction commision date is afer construction start date. + if (constructionStartDate > constructionCommissioningDate) { + document.querySelector('#pro-forma-form-save-msg').innerHTML = ` Anticipated Commissioning date has to be after Anticipated Construction start date `; - return false; + return false; + } + request('finance-overview/', { + method: 'PUT', + credentials: 'same-origin', + body: JSON.stringify(result), + headers: new Headers({ + 'Content-Type': 'application/json', + 'X-CSRFToken': Cookies.get('csrftoken') + }) + }).then(res => { + let displayMessage = document.querySelector('#pro-forma-form-save-msg'); + if (!res.err) { + // Display response message. Add that loan options changed if fund was changed. Reset didFundChange to false. + let responseMessage = 'Saved. '; + if (didFundChange) { + responseMessage += 'Loan Options table is reloaded.'; + } + displayMessage.innerHTML = `${responseMessage}`; + /** + * delete-loan-options request to the backend to delete loan options for this building id if previosly stored. + * This ensures that the loan options table is up to date with the latest fund. Clear the loan options table + * and reload with new fund's default loan options. + */ + if (didFundChange) { + didFundChange = false; + request(`loan-options/?loans=delete-loan-options`, { + method: 'GET', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json' + } + }).then(res => { + let tableBody = document.querySelector('#loan-options-table tbody'); + tableBody.innerHTML = ``; + }); + getLoanOptionsTable(); + } } - request('finance-overview/', { - method: 'PUT', - credentials: 'same-origin', - body: JSON.stringify(result), - headers: new Headers({ - 'Content-Type': 'application/json', - 'X-CSRFToken': Cookies.get('csrftoken') - }) - }).then( res => { - let displayMessage = document.querySelector('#pro-forma-form-save-msg'); - if (!res.err) { - // Display response message. Add that loan options changed if fund was changed. Reset didFundChange to false. - let responseMessage = 'Saved. '; - if (didFundChange) { - responseMessage += 'Loan Options table is reloaded.'; - } - displayMessage.innerHTML = `${responseMessage}`; - /** - * delete-loan-options request to the backend to delete loan options for this building id if previosly stored. - * This ensures that the loan options table is up to date with the latest fund. Clear the loan options table - * and reload with new fund's default loan options. - */ - if (didFundChange) { - didFundChange = false; - request(`loan-options/?loans=delete-loan-options`, { - method: 'GET', - credentials: 'same-origin', - headers: { - 'Content-Type': 'application/json' - } - }).then( res => { - let tableBody = document.querySelector('#loan-options-table tbody'); - tableBody.innerHTML = ``; - }); - getLoanOptionsTable(); - } - } - else { - res.err.responseBody.then((error) => { - // Display error message. - Object.keys(error).forEach(function (key) { - document.querySelector('#' + key + '-error').innerHTML = ` + else { + res.err.responseBody.then((error) => { + // Display error message. + Object.keys(error).forEach(function (key) { + document.querySelector('#' + key + '-error').innerHTML = ` ${error[key][0]} `; - }) - }); - } - }); - return false; + }) + }); + } + }); + return false; } -- GitLab From 6a2cc42f78adde4f473ec51a49f8e0baef22d343 Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Thu, 8 Jun 2017 16:20:25 -0400 Subject: [PATCH 17/21] Change name and id of fund to fund_id to make everything easier. --- .../financialInputs/templates/financialInputs/proFormaForm.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blocnote/apps/financialInputs/templates/financialInputs/proFormaForm.html b/blocnote/apps/financialInputs/templates/financialInputs/proFormaForm.html index b83ed05..ccc94e4 100644 --- a/blocnote/apps/financialInputs/templates/financialInputs/proFormaForm.html +++ b/blocnote/apps/financialInputs/templates/financialInputs/proFormaForm.html @@ -26,7 +26,7 @@
Fund -
-- GitLab From b54116925ee8baefc0411d64d50844733fb1d91d Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Thu, 8 Jun 2017 16:21:18 -0400 Subject: [PATCH 18/21] Edit tests to check with fund_id instead of fund. --- blocnote/apps/financialInputs/tests.py | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/blocnote/apps/financialInputs/tests.py b/blocnote/apps/financialInputs/tests.py index 29b10c9..882b7aa 100644 --- a/blocnote/apps/financialInputs/tests.py +++ b/blocnote/apps/financialInputs/tests.py @@ -70,7 +70,7 @@ class ProformaInputsViewTest(TestCase): [3, 'Fund3'], ], 'financing_overview_data': { - 'fund': 2, + 'fund_id': 2, 'pro_forma_start_date': PROFORMA_START_DATE, 'pro_forma_duration': '25', 'analysis_date': ANALYSIS_DATE, @@ -91,12 +91,8 @@ class ProformaInputsViewTest(TestCase): """ response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps({})) response_content = json.loads(response.content) - expected_response_content = { - 'error': 'Missing data in form', - } self.assertEqual(response.status_code, 400) self.assertTrue('error' in response_content) - self.assertEqual(response_content, expected_response_content) def test_finance_overview_put_2(self): """Test the PUT route when correct content is sent. @@ -104,7 +100,7 @@ class ProformaInputsViewTest(TestCase): Test PUT route when correct content is sent. This should do nothing. """ content = { - 'fund': 1, + 'fund_id': 1, 'pro_forma_start_date': PROFORMA_START_DATE, 'pro_forma_duration': 25, 'analysis_date': ANALYSIS_DATE, @@ -120,7 +116,7 @@ class ProformaInputsViewTest(TestCase): def test_finance_overview_put_3(self): """Test PUT route when construction start date is empty.""" content = { - 'fund': 1, + 'fund_id': 1, 'pro_forma_start_date': PROFORMA_START_DATE, 'pro_forma_duration': 25, 'analysis_date': ANALYSIS_DATE, @@ -136,7 +132,7 @@ class ProformaInputsViewTest(TestCase): def test_finance_overview_put_4(self): """Test PUT route when commissioning date is empty.""" content = { - 'fund': 1, + 'fund_id': 1, 'pro_forma_start_date': PROFORMA_START_DATE, 'pro_forma_duration': 25, 'analysis_date': ANALYSIS_DATE, @@ -152,7 +148,7 @@ class ProformaInputsViewTest(TestCase): def test_finance_overview_put_5(self): """Test PUT route when proforma start date is empty.""" content = { - 'fund': 1, + 'fund_id': 1, 'pro_forma_start_date': '', 'pro_forma_duration': 25, 'analysis_date': ANALYSIS_DATE, @@ -168,7 +164,7 @@ class ProformaInputsViewTest(TestCase): def test_finance_overview_put_6(self): """Test PUT route when proforma duration is empty.""" content = { - 'fund': 1, + 'fund_id': 1, 'pro_forma_start_date': PROFORMA_START_DATE, 'pro_forma_duration': '', 'analysis_date': ANALYSIS_DATE, @@ -184,7 +180,7 @@ class ProformaInputsViewTest(TestCase): def test_finance_overview_put_7(self): """Test PUT route when analysis date is empty.""" content = { - 'fund': 1, + 'fund_id': 1, 'pro_forma_start_date': PROFORMA_START_DATE, 'pro_forma_duration': 25, 'analysis_date': '', @@ -200,7 +196,7 @@ class ProformaInputsViewTest(TestCase): def test_finance_overview_put_8(self): """Test PUT route when construction period is empty.""" content = { - 'fund': 1, + 'fund_id': 1, 'pro_forma_start_date': PROFORMA_START_DATE, 'pro_forma_duration': 25, 'analysis_date': ANALYSIS_DATE, @@ -216,7 +212,7 @@ class ProformaInputsViewTest(TestCase): def test_finance_overview_put_9(self): """Test PUT route with fund as empty.""" content = { - 'fund': '', + 'fund_id': '', 'pro_forma_start_date': PROFORMA_START_DATE, 'pro_forma_duration': 25, 'analysis_date': ANALYSIS_DATE, -- GitLab From f691455f9c2ee87c34a7065dd2c95e3f7e4fd631 Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Thu, 8 Jun 2017 16:22:00 -0400 Subject: [PATCH 19/21] Change code to be concise. --- .../financialInputs/views/proforma_input.py | 81 +++++++++---------- 1 file changed, 36 insertions(+), 45 deletions(-) diff --git a/blocnote/apps/financialInputs/views/proforma_input.py b/blocnote/apps/financialInputs/views/proforma_input.py index 7516b72..ddedc1e 100644 --- a/blocnote/apps/financialInputs/views/proforma_input.py +++ b/blocnote/apps/financialInputs/views/proforma_input.py @@ -1,6 +1,6 @@ """Route for Proforma Inputs.""" import json - +import copy from django.http import JsonResponse from django.views import View @@ -38,42 +38,29 @@ class ProformaInputs(View): Otherwise a status 200. """ put = json.loads(request.body.decode()) - if len(list(put.keys())) == self.form_length: - if put['fund'] is '': - return JsonResponse({'fund': 'Fund cannot be empty.'}, status=400) - form = self.proforma_inputs_form({ - 'fund': put['fund'], - 'pro_forma_start_date': put['pro_forma_start_date'], - 'pro_forma_duration': put['pro_forma_duration'], - 'analysis_date': put['analysis_date'], - 'anticipated_construction_start_date': put['anticipated_construction_start_date'], - 'anticipated_commissioning_date': put['anticipated_commissioning_date'], - 'anticipated_construction_period': put['anticipated_construction_period'], - }) - # validate the received form. - if form.is_valid(): - self.financing_model.objects.update_or_create( - building_id=building_id, - defaults={ - 'building_id': building_id, - 'fund_id': put['fund'], - 'pro_forma_start_date': put['pro_forma_start_date'], - 'pro_forma_duration': put['pro_forma_duration'], - 'analysis_date': put['analysis_date'], - 'anticipated_construction_start_date': put['anticipated_construction_start_date'], - 'anticipated_commissioning_date': put['anticipated_commissioning_date'], - 'anticipated_construction_period': put['anticipated_construction_period'], - } - ) - else: - # construct an error dictionary to send to frontend if form is not valid. - error_dict = {} - for field, error in form.errors.items(): - error_dict[field] = error - return JsonResponse(error_dict, status=400) - return JsonResponse({}) + # Django form validation does not care if foreign key is missing so this check is done here. + if 'fund_id' not in put: + return JsonResponse({'error': 'Fund missing from form'}, status=400) + if put['fund_id'] == '': + return JsonResponse({'fund': 'Fund cannot be empty.'}, status=400) + + # Create form from the inputs received. + form = self.proforma_inputs_form(put) + + # Validate form. + if form.is_valid(): + put['building_id'] = building_id + self.financing_model.objects.update_or_create( + building_id=building_id, + defaults=put, + ) else: - return JsonResponse({'error': 'Missing data in form'}, status=400) + # construct an error dictionary to send to frontend if form is not valid. + error_dict = {} + for field, error in form.errors.items(): + error_dict[field] = error + return JsonResponse(error_dict, status=400) + return JsonResponse({}) def get(self, request, building_id): """HTTP GET request. @@ -90,6 +77,14 @@ class ProformaInputs(View): """ financing_overview_objs = self.financing_model.objects.filter(building_id=building_id) + unwanted_keys = [ + '_state', + 'id', + 'building_id', + 'required_noi_dscr', + 'requrired_cash_dscr', + ] + # Fetch all the funds. funds_obj = self.fund_model.objects.all() funds = [] @@ -100,15 +95,11 @@ class ProformaInputs(View): # Check if the financing overview entry exists in the database. if financing_overview_objs: financing_overview_obj = financing_overview_objs[0] - financing_overview_data = { - 'fund': financing_overview_obj.fund.id, - 'pro_forma_start_date': financing_overview_obj.pro_forma_start_date, - 'pro_forma_duration': financing_overview_obj.pro_forma_duration, - 'analysis_date': financing_overview_obj.analysis_date, - 'anticipated_construction_start_date': financing_overview_obj.anticipated_construction_start_date, - 'anticipated_commissioning_date': financing_overview_obj.anticipated_commissioning_date, - 'anticipated_construction_period': financing_overview_obj.anticipated_construction_period, - } + financing_overview_data = {} + obj_dict = financing_overview_obj.__dict__ + for key in obj_dict: + if key not in unwanted_keys: + financing_overview_data[key] = obj_dict[key] instance['financing_overview_data'] = financing_overview_data instance['funds'] = funds return JsonResponse({'instance': instance}) -- GitLab From 84646948ae08b574bf44495ebbc4b3c28fa2263a Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Thu, 8 Jun 2017 16:52:01 -0400 Subject: [PATCH 20/21] Update js code according to linter suggestions. --- .../financialInputs/scripts/proformaInputs.js | 116 +++++++++--------- 1 file changed, 59 insertions(+), 57 deletions(-) diff --git a/blocnote/apps/financialInputs/static/financialInputs/scripts/proformaInputs.js b/blocnote/apps/financialInputs/static/financialInputs/scripts/proformaInputs.js index 25c3322..dbdc284 100644 --- a/blocnote/apps/financialInputs/static/financialInputs/scripts/proformaInputs.js +++ b/blocnote/apps/financialInputs/static/financialInputs/scripts/proformaInputs.js @@ -1,6 +1,5 @@ 'use strict'; -getBillProjectionDatesForm(); const ERROR_TAGS = [ 'pro_forma_start_date-error', 'pro_forma_duration-error', @@ -11,70 +10,70 @@ const ERROR_TAGS = [ 'anticipated_construction_period-error', ]; /** - * proformaForm will watch the form and if it changes, it will remove the response message is it was displayed. + * proformaForm will watch the form and if it changes, it will remove the response message is it + * was displayed. */ -let proformaForm = document.querySelector('#pro-forma-form'); -proformaForm.onchange = function () { +const proformaForm = document.querySelector('#pro-forma-form'); +proformaForm.onchange = function resetErrors() { document.querySelector('#pro-forma-form-save-msg').innerHTML = ''; - ERROR_TAGS.forEach(function (tag) { - document.querySelector('#' + tag).innerHTML = ''; + ERROR_TAGS.forEach((tag) => { + document.querySelector(`#${tag}`).innerHTML = ''; }); -} +}; /** - * The following 2 functions display a warning message saying if fund is changed, it will affect the loan options. - * This message is displayed when the mouse is over the fund select box. + * The following 2 functions display a warning message saying if fund is changed, it will affect + * the loan options. This message is displayed when the mouse is over the fund select box. */ -let fund = document.querySelector('#id_fund'); +const fund = document.querySelector('#id_fund'); /** * This is to watch if fund value is changed. If it did, it would affect loan options. */ -let didFundChange = false -fund.onmouseenter = function () { +let didFundChange = false; +fund.onmouseenter = function showFundWarning() { document.querySelector('#show-error').innerHTML = ` Changing fund will affect loan options `; -} +}; -fund.onmouseleave = function () { - document.querySelector('#show-error').innerHTML = ``; -} +fund.onmouseleave = function clearFundWarning() { + document.querySelector('#show-error').innerHTML = ''; +}; -fund.onchange = function () { +fund.onchange = function checkIfFundChanged() { didFundChange = true; }; /** - * HTTP GET request to fetch the proforma form information from the database if preent. It would receive the list of - * funds along with. + * HTTP GET request to fetch the proforma form information from the database if preent. It would + * receive the list of funds along with. */ function getBillProjectionDatesForm() { - request(`finance-overview`, { + request('finance-overview', { method: 'GET', credentials: 'same-origin', headers: { - 'Content-Type': 'application/json' - } - }).then(res => { + 'Content-Type': 'application/json', + }, + }).then((res) => { if (!res.err) { - let fundDropBox = document.querySelector('#fund_id'); + const fundDropBox = document.querySelector('#fund_id'); const funds = res.payload.instance.funds; // Load fund dropdown box with the list of funds received. - funds.forEach(function (fund) { + funds.forEach((thisFund) => { fundDropBox.innerHTML += ` - + `; }); // Load all the values if previously filled. if (res.payload.instance.financing_overview_data) { const financingOverviewData = res.payload.instance.financing_overview_data; - Object.keys(financingOverviewData).forEach(function (key) { - let data = financingOverviewData[key]; - proformaForm.querySelector('#' + key).value = data; + Object.keys(financingOverviewData).forEach((key) => { + const data = financingOverviewData[key]; + proformaForm.querySelector(`#${key}`).value = data; }); } - } - else { + } else { // Display error message if error on load. document.querySelector('#pro-forma-form-save-msg').innerHTML = ` Sorry, there was an error loading. @@ -83,20 +82,23 @@ function getBillProjectionDatesForm() { }); } +getBillProjectionDatesForm(); + /** - * Handle submition of the Proforma form. Validate commissioning date is greater than construction start date. Create - * result dictionary containing the form data and convert into JSON to send to the backend. Upon success, load the - * loan options table with the saved fund if fund changed or saving this form for the first time. + * Handle submition of the Proforma form. Validate commissioning date is greater than construction + * start date. Create result dictionary containing the form data and convert into JSON to send to + * the backend. Upon success, load the loan options table with the saved fund if fund changed or + * saving this form for the first time. * * @param {any} form : Proforma inputs form filled. * @returns : False so that page does not reload. */ function billProjectionDatesForm(form) { const formData = new FormData(form); - let result = {}; - for (let pair of formData.entries()) { - result[pair[0]] = pair[1]; - } + const result = {}; + formData.forEach((value, field) => { + result[field] = value; + }); const constructionStartDate = new Date(result.anticipated_construction_start_date); const constructionCommissioningDate = new Date(result.anticipated_commissioning_date); // Make sure construction commision date is afer construction start date. @@ -114,45 +116,45 @@ function billProjectionDatesForm(form) { body: JSON.stringify(result), headers: new Headers({ 'Content-Type': 'application/json', - 'X-CSRFToken': Cookies.get('csrftoken') - }) - }).then(res => { - let displayMessage = document.querySelector('#pro-forma-form-save-msg'); + 'X-CSRFToken': Cookies.get('csrftoken'), + }), + }).then((res) => { + const displayMessage = document.querySelector('#pro-forma-form-save-msg'); if (!res.err) { - // Display response message. Add that loan options changed if fund was changed. Reset didFundChange to false. + // Display response message. Add that loan options changed if fund was changed. Reset + // didFundChange to false. let responseMessage = 'Saved. '; if (didFundChange) { responseMessage += 'Loan Options table is reloaded.'; } displayMessage.innerHTML = `${responseMessage}`; /** - * delete-loan-options request to the backend to delete loan options for this building id if previosly stored. - * This ensures that the loan options table is up to date with the latest fund. Clear the loan options table - * and reload with new fund's default loan options. + * delete-loan-options request to the backend to delete loan options for this building id if + * previosly stored. This ensures that the loan options table is up to date with the latest + * fund. Clear the loan options table and reload with new fund's default loan options. */ if (didFundChange) { didFundChange = false; - request(`loan-options/?loans=delete-loan-options`, { + request('loan-options/?loans=delete-loan-options', { method: 'GET', credentials: 'same-origin', headers: { - 'Content-Type': 'application/json' - } - }).then(res => { - let tableBody = document.querySelector('#loan-options-table tbody'); - tableBody.innerHTML = ``; + 'Content-Type': 'application/json', + }, + }).then(() => { + const tableBody = document.querySelector('#loan-options-table tbody'); + tableBody.innerHTML = ''; }); getLoanOptionsTable(); } - } - else { + } else { res.err.responseBody.then((error) => { // Display error message. - Object.keys(error).forEach(function (key) { - document.querySelector('#' + key + '-error').innerHTML = ` + Object.keys(error).forEach((key) => { + document.querySelector(`#${key}-error`).innerHTML = ` ${error[key][0]} `; - }) + }); }); } }); -- GitLab From ca38bf49e7be90ea8a25fed2c839ad6f72d89604 Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Mon, 12 Jun 2017 17:24:11 -0400 Subject: [PATCH 21/21] Replace all json.loads(response.content) to response.content. --- blocnote/apps/financialInputs/tests.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/blocnote/apps/financialInputs/tests.py b/blocnote/apps/financialInputs/tests.py index 882b7aa..7d6d6c0 100644 --- a/blocnote/apps/financialInputs/tests.py +++ b/blocnote/apps/financialInputs/tests.py @@ -28,7 +28,7 @@ class ProformaInputsViewTest(TestCase): instance. """ response = self.client.get('/buildings/3000/financial-inputs/finance-overview/') - response_content = json.loads(response.content) + response_content = response.json() expected_response_content = { 'instance': { 'funds': [ @@ -90,7 +90,7 @@ class ProformaInputsViewTest(TestCase): Test PUT route when empty content is sent. This should do nothing. """ response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps({})) - response_content = json.loads(response.content) + response_content = response.json() self.assertEqual(response.status_code, 400) self.assertTrue('error' in response_content) @@ -125,7 +125,7 @@ class ProformaInputsViewTest(TestCase): 'anticipated_construction_period': 4, } response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) - response_content = json.loads(response.content) + response_content = response.json() self.assertEqual(response.status_code, 400) self.assertTrue('anticipated_construction_start_date' in response_content) @@ -141,7 +141,7 @@ class ProformaInputsViewTest(TestCase): 'anticipated_construction_period': 4, } response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) - response_content = json.loads(response.content) + response_content = response.json() self.assertEqual(response.status_code, 400) self.assertTrue('anticipated_commissioning_date' in response_content) @@ -157,7 +157,7 @@ class ProformaInputsViewTest(TestCase): 'anticipated_construction_period': 4, } response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) - response_content = json.loads(response.content) + response_content = response.json() self.assertEqual(response.status_code, 400) self.assertTrue('pro_forma_start_date' in response_content) @@ -173,7 +173,7 @@ class ProformaInputsViewTest(TestCase): 'anticipated_construction_period': 4, } response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) - response_content = json.loads(response.content) + response_content = response.json() self.assertEqual(response.status_code, 400) self.assertTrue('pro_forma_duration' in response_content) @@ -189,7 +189,7 @@ class ProformaInputsViewTest(TestCase): 'anticipated_construction_period': 4, } response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) - response_content = json.loads(response.content) + response_content = response.json() self.assertEqual(response.status_code, 400) self.assertTrue('analysis_date' in response_content) @@ -205,7 +205,7 @@ class ProformaInputsViewTest(TestCase): 'anticipated_construction_period': '', } response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) - response_content = json.loads(response.content) + response_content = response.json() self.assertEqual(response.status_code, 400) self.assertTrue('anticipated_construction_period' in response_content) @@ -221,7 +221,7 @@ class ProformaInputsViewTest(TestCase): 'anticipated_construction_period': 4, } response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) - response_content = json.loads(response.content) + response_content = response.json() self.assertEqual(response.status_code, 400) self.assertTrue('fund' in response_content) @@ -236,6 +236,6 @@ class ProformaInputsViewTest(TestCase): 'anticipated_construction_period': 4, } response = self.client.put('/buildings/3000/financial-inputs/finance-overview/', json.dumps(content)) - response_content = json.loads(response.content) + response_content = response.json() self.assertEqual(response.status_code, 400) self.assertTrue('error' in response_content) -- GitLab