From 4a1b70ddbaefa5b516162b1bfa95f5856118e743 Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Tue, 30 May 2017 11:12:41 -0400 Subject: [PATCH 01/17] Change all var to either const or let. Perform django form validation in backend. Catch and display form validation errors. Make database update query as update_or_create. --- blocnote/apps/financialInputs/forms.py | 17 ++++- blocnote/apps/financialInputs/old_views.py | 38 +++++++----- .../static/financialInputs/scripts/app.js | 62 ++++++++++++++----- 3 files changed, 85 insertions(+), 32 deletions(-) diff --git a/blocnote/apps/financialInputs/forms.py b/blocnote/apps/financialInputs/forms.py index bca424d..0920ce6 100644 --- a/blocnote/apps/financialInputs/forms.py +++ b/blocnote/apps/financialInputs/forms.py @@ -1,10 +1,11 @@ """Forms to render and validate for financial-inputs endpoint.""" from django.forms import ModelForm from blocnote.apps.financialInputs.models import FinancingOverview +from blocnote.apps.financialInputs.models import CustomerPreference class ProformaInputsForm(ModelForm): - """Define the form to input/display proforma information.""" + """Define the form to validate proforma information.""" class Meta: """Choose the model and the relevant fields for the form.""" @@ -19,3 +20,17 @@ class ProformaInputsForm(ModelForm): 'anticipated_commissioning_date', 'anticipated_construction_period', ] + + +class CustomerPreferenceForm(ModelForm): + """Define the form to validate customer preference form.""" + + class Meta: + """Choose the model and the relevant fields for the form.""" + + model = CustomerPreference + fields = [ + 'downpayment', + 'expected_payback', + 'expected_net_noi_dscr', + ] diff --git a/blocnote/apps/financialInputs/old_views.py b/blocnote/apps/financialInputs/old_views.py index 2387603..7989c22 100644 --- a/blocnote/apps/financialInputs/old_views.py +++ b/blocnote/apps/financialInputs/old_views.py @@ -12,9 +12,9 @@ from bpfin.financials.financial_lib import organize_bill_overview from bpfin.financials.financial_lib import Income_Statement_Table -from .models import Fund, FinancingOverview, Bills, BillsOverview, CustomerPreference, EstimationAlgorithm +from .models import FinancingOverview, Bills, BillsOverview, CustomerPreference, EstimationAlgorithm from .models import Liabilities, CashBalance, IncomeStatement, LoanOptions, DefaultLoan, Lender, GrowthRate -from .forms import ProformaInputsForm +from .forms import CustomerPreferenceForm def get_analysis_date(building_id): @@ -477,7 +477,8 @@ class BillsOverviewView(View): class CustomerPreferenceView(View): """Create and update customer preference table.""" - model = CustomerPreference + customer_preference_model = CustomerPreference + customer_preference_form = CustomerPreferenceForm def put(self, request, building_id): """Create/Update customer preference table. @@ -493,21 +494,26 @@ class CustomerPreferenceView(View): JsonResponse: Return a status that says ok. """ put = json.loads(request.body.decode()) - obj = self.model.objects.filter(building_id=building_id) - if obj: - obj.update( + form = self.customer_preference_form({ + 'downpayment': put['Affordable-Downpayment'], + 'expected_payback': put['Expected-Payback'], + 'expected_net_noi_dscr': put['Expected-NOI-DSCR'], + }) + if form.is_valid(): + self.customer_preference_model.objects.update_or_create( building_id=building_id, - downpayment=put['Affordable-Downpayment'], - expected_payback=put['Expected-Payback'], - expected_net_noi_dscr=put['Expected-NOI-DSCR'] + defaults={ + 'building_id': building_id, + 'downpayment': put['Affordable-Downpayment'], + 'expected_payback': put['Expected-Payback'], + 'expected_net_noi_dscr': put['Expected-NOI-DSCR'], + } ) else: - self.model.objects.create( - building_id=building_id, - downpayment=put['Affordable-Downpayment'], - expected_payback=put['Expected-Payback'], - expected_net_noi_dscr=put['Expected-NOI-DSCR'] - ) + 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): @@ -527,7 +533,7 @@ class CustomerPreferenceView(View): present, else says false. If table is present, instance also contains the table values. """ - obj = get_model_object(self.model, building_id) + obj = get_model_object(self.customer_preference_model, building_id) instance = {} if obj: instance['downpayment'] = obj.downpayment diff --git a/blocnote/apps/financialInputs/static/financialInputs/scripts/app.js b/blocnote/apps/financialInputs/static/financialInputs/scripts/app.js index a6b4f08..16f3e6c 100644 --- a/blocnote/apps/financialInputs/static/financialInputs/scripts/app.js +++ b/blocnote/apps/financialInputs/static/financialInputs/scripts/app.js @@ -398,9 +398,13 @@ function billsOverviewFormSubmit(form) { } // Watch customer preference to display/erase error/success mesaages. -var customerPreference = document.querySelector('#Customer-Preference'); +const customerPreference = document.querySelector('#Customer-Preference'); customerPreference.onchange = function() { document.querySelector('#customer-preference-warning-message').innerHTML = ''; + let table = document.querySelector('#customer-preference-table'); + table.querySelector('#downpayment-error').innerHTML = ''; + table.querySelector('#expected_payback-error').innerHTML = ''; + table.querySelector('#expected_net_noi_dscr-error').innerHTML = ''; } /** @@ -408,7 +412,7 @@ customerPreference.onchange = function() { */ function customerPreferenceForm(form) { /* Handle customer preference form submission */ - formData = new FormData(form); + const formData = new FormData(form); const result = {}; for (const [key, value] of formData.entries()) { result[key] = value; @@ -422,11 +426,20 @@ function customerPreferenceForm(form) { 'X-CSRFToken': Cookies.get('csrftoken') }) }).then(res => { - if (!res.payload.err) { + if (!res.err) { document.querySelector('#customer-preference-warning-message').innerHTML = ` Saved `; } + else { + res.err.responseBody.then((errorDict) => { + for (let key in errorDict) { + document.querySelector('#'+key+'-error').innerHTML = ` + ${errorDict[key][0]} + `; + } + }) + } }); return false; } @@ -435,17 +448,17 @@ function customerPreferenceForm(form) { * Create the customer preference table. Display values if previously filled else display defaults. */ function createCustomerPreferenceTable(instance) { - const customerPreferenceForm = document.querySelector('#Customer-Preference'); - var downpayment = 0; - var expectedPayback = 999; - var expectedNetNOIDSCR = 1.15 + let customerPreferenceForm = document.querySelector('#Customer-Preference'); + let downpayment = 0; + let expectedPayback = 999; + let expectedNetNOIDSCR = 1.15 if (instance) { - var downpayment = instance['downpayment']; - var expectedPayback = instance['expected_payback']; - var expectedNetNOIDSCR = instance['expected_net_noi_dscr'] + downpayment = instance['downpayment']; + expectedPayback = instance['expected_payback']; + expectedNetNOIDSCR = instance['expected_net_noi_dscr'] } - var text = ` + let text = ` @@ -456,15 +469,27 @@ function createCustomerPreferenceTable(instance) { - + - + - +
Affordable Downpayment + +
+
+
Expected PaybackMonths + Months +
+
+
Expected Net NOI DSCR + +
+
+
@@ -482,7 +507,14 @@ function getCustomerPreferenceTable() { 'Content-Type': 'application/json' }, }).then(res => { - createCustomerPreferenceTable(res.payload.instance); + if (!res.err) { + createCustomerPreferenceTable(res.payload.instance); + } + else { + document.querySelector('#customer-preference-warning-message').innerHTML = ` + There was an error loading the table. + `; + } }); } -- GitLab From 800c0d6b8f82ce4df7ad1f7a1e71aab8251a4968 Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Thu, 1 Jun 2017 15:51:09 -0400 Subject: [PATCH 02/17] Import customer preference form. --- blocnote/apps/financialInputs/old_views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blocnote/apps/financialInputs/old_views.py b/blocnote/apps/financialInputs/old_views.py index 8a810c8..feae813 100644 --- a/blocnote/apps/financialInputs/old_views.py +++ b/blocnote/apps/financialInputs/old_views.py @@ -13,7 +13,7 @@ from bpfin.lib.back_end_call import monthly_bill, prior_income_statement_table from .models import FinancingOverview, Bills, BillsOverview, CustomerPreference, EstimationAlgorithm from .models import Liabilities, CashBalance, IncomeStatement, LoanOptions, DefaultLoan, Lender, GrowthRate - +from .forms import CustomerPreferenceForm def get_analysis_date(building_id): """Fetch the proforma start date and duration from the database.""" -- GitLab From 563d81013f2c937b6ebab3e8aa0ad9193001da2a Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Thu, 1 Jun 2017 16:08:42 -0400 Subject: [PATCH 03/17] Move customer preference js code to new file. --- .../scripts/customerPreference.js | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 blocnote/apps/financialInputs/static/financialInputs/scripts/customerPreference.js diff --git a/blocnote/apps/financialInputs/static/financialInputs/scripts/customerPreference.js b/blocnote/apps/financialInputs/static/financialInputs/scripts/customerPreference.js new file mode 100644 index 0000000..b82b3fc --- /dev/null +++ b/blocnote/apps/financialInputs/static/financialInputs/scripts/customerPreference.js @@ -0,0 +1,124 @@ +'use strict'; +getCustomerPreferenceTable(); + +// Watch customer preference to display/erase error/success mesaages. +const customerPreference = document.querySelector('#Customer-Preference'); +customerPreference.onchange = function () { + document.querySelector('#customer-preference-warning-message').innerHTML = ''; + let table = document.querySelector('#customer-preference-table'); + table.querySelector('#downpayment-error').innerHTML = ''; + table.querySelector('#expected_payback-error').innerHTML = ''; + table.querySelector('#expected_net_noi_dscr-error').innerHTML = ''; +} + +/** + * Handle customer preference form submit. Make a HTTP PUT request. + */ +function customerPreferenceForm(form) { + /* Handle customer preference form submission */ + const formData = new FormData(form); + const result = {}; + for (const [key, value] of formData.entries()) { + result[key] = value; + } + request('customer-preference/', { + 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.err) { + document.querySelector('#customer-preference-warning-message').innerHTML = ` + Saved + `; + } + else { + res.err.responseBody.then((errorDict) => { + Object.keys(errorDict).forEach(function (key) { + document.querySelector('#'+key+'-error').innerHTML = ` + ${errorDict[key][0]} + `; + }); + }); + } + }); + return false; +} + +/** + * Create the customer preference table. Display values if previously filled else display defaults. + */ +function createCustomerPreferenceTable(instance) { + let customerPreferenceForm = document.querySelector('#Customer-Preference'); + let downpayment = 0; + let expectedPayback = 999; + let expectedNetNOIDSCR = 1.15 + + if (instance) { + downpayment = instance['downpayment']; + expectedPayback = instance['expected_payback']; + expectedNetNOIDSCR = instance['expected_net_noi_dscr'] + } + // let text + customerPreferenceForm.innerHTML = ` + + + + + + + + + + + + + + + + + + + + + +
PreferenceValue
Affordable Downpayment + +
+
+
Expected Payback + Months +
+
+
Expected Net NOI DSCR + +
+
+
+ + `; + // customerPreferenceForm.innerHTML = text; +} + +/**Make HTTP GET request to obtain customer preference table data if present. */ +function getCustomerPreferenceTable() { + request(`customer-preference/`, { + method: 'GET', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json' + }, + }).then(res => { + if (!res.err) { + createCustomerPreferenceTable(res.payload.instance); + } + else { + document.querySelector('#customer-preference-warning-message').innerHTML = ` + There was an error loading the table. + `; + } + }); +} -- GitLab From d842941b322271cfbb298fbfe929564c8fb6c8cc Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Thu, 1 Jun 2017 16:09:38 -0400 Subject: [PATCH 04/17] Removal of customer preference code from app js. --- .../static/financialInputs/scripts/app.js | 123 +----------------- 1 file changed, 1 insertion(+), 122 deletions(-) diff --git a/blocnote/apps/financialInputs/static/financialInputs/scripts/app.js b/blocnote/apps/financialInputs/static/financialInputs/scripts/app.js index 4fa8a3e..f6b9fd4 100644 --- a/blocnote/apps/financialInputs/static/financialInputs/scripts/app.js +++ b/blocnote/apps/financialInputs/static/financialInputs/scripts/app.js @@ -10,7 +10,7 @@ for (var utility_index in utilities) { } loadBillsOverview(); getIncomeStatementTable(); -getCustomerPreferenceTable(); + getLiabilitiesTable(); getCashBalanceForm(); getLoanOptionsTable(); @@ -417,127 +417,6 @@ function billsOverviewFormSubmit(form) { return false; } -// Watch customer preference to display/erase error/success mesaages. -const customerPreference = document.querySelector('#Customer-Preference'); -customerPreference.onchange = function() { - document.querySelector('#customer-preference-warning-message').innerHTML = ''; - let table = document.querySelector('#customer-preference-table'); - table.querySelector('#downpayment-error').innerHTML = ''; - table.querySelector('#expected_payback-error').innerHTML = ''; - table.querySelector('#expected_net_noi_dscr-error').innerHTML = ''; -} - -/** - * Handle customer preference form submit. Make a HTTP PUT request. - */ -function customerPreferenceForm(form) { - /* Handle customer preference form submission */ - const formData = new FormData(form); - const result = {}; - for (const [key, value] of formData.entries()) { - result[key] = value; - } - request('customer-preference/', { - 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.err) { - document.querySelector('#customer-preference-warning-message').innerHTML = ` - Saved - `; - } - else { - res.err.responseBody.then((errorDict) => { - for (let key in errorDict) { - document.querySelector('#'+key+'-error').innerHTML = ` - ${errorDict[key][0]} - `; - } - }) - } - }); - return false; -} - -/** - * Create the customer preference table. Display values if previously filled else display defaults. - */ -function createCustomerPreferenceTable(instance) { - let customerPreferenceForm = document.querySelector('#Customer-Preference'); - let downpayment = 0; - let expectedPayback = 999; - let expectedNetNOIDSCR = 1.15 - - if (instance) { - downpayment = instance['downpayment']; - expectedPayback = instance['expected_payback']; - expectedNetNOIDSCR = instance['expected_net_noi_dscr'] - } - let text = ` - - - - - - - - - - - - - - - - - - - - - -
PreferenceValue
Affordable Downpayment - -
-
-
Expected Payback - Months -
-
-
Expected Net NOI DSCR - -
-
-
- - `; - customerPreferenceForm.innerHTML = text; -} - -/**Make HTTP GET request to obtain customer preference table data if present. */ -function getCustomerPreferenceTable() { - request(`customer-preference/`, { - method: 'GET', - credentials: 'same-origin', - headers: { - 'Content-Type': 'application/json' - }, - }).then(res => { - if (!res.err) { - createCustomerPreferenceTable(res.payload.instance); - } - else { - document.querySelector('#customer-preference-warning-message').innerHTML = ` - There was an error loading the table. - `; - } - }); -} - /** * Load the Mortgage and Liabilities table. * This function loads the mortgage and liabilities table with the given inputList. If inputList is empty, it loads a -- GitLab From 0875dcddc7a84a2e05d28b957c6efa3466c5c8c7 Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Thu, 1 Jun 2017 16:46:31 -0400 Subject: [PATCH 05/17] Update urls to route to the new customer preference file. --- blocnote/apps/financialInputs/urls.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/blocnote/apps/financialInputs/urls.py b/blocnote/apps/financialInputs/urls.py index cf298f6..f27b683 100644 --- a/blocnote/apps/financialInputs/urls.py +++ b/blocnote/apps/financialInputs/urls.py @@ -2,6 +2,7 @@ from django.conf.urls import url from . import old_views from .views import proforma_input +from .views import customer_preference app_name = 'financial-inputs' urlpatterns = [ @@ -9,7 +10,7 @@ urlpatterns = [ 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'^customer-preference/$', customer_preference.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'), -- GitLab From c6267df6f48f778131189ce4500deaa6837fe827 Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Thu, 1 Jun 2017 16:47:14 -0400 Subject: [PATCH 06/17] Remove all operations for customer preferene from old views. --- blocnote/apps/financialInputs/old_views.py | 72 +--------------------- 1 file changed, 1 insertion(+), 71 deletions(-) diff --git a/blocnote/apps/financialInputs/old_views.py b/blocnote/apps/financialInputs/old_views.py index feae813..9fa87df 100644 --- a/blocnote/apps/financialInputs/old_views.py +++ b/blocnote/apps/financialInputs/old_views.py @@ -10,10 +10,9 @@ from django.views import View from bpfin.lib.back_end_call import monthly_bill, prior_income_statement_table -from .models import FinancingOverview, Bills, BillsOverview, CustomerPreference, EstimationAlgorithm +from .models import FinancingOverview, Bills, BillsOverview, EstimationAlgorithm from .models import Liabilities, CashBalance, IncomeStatement, LoanOptions, DefaultLoan, Lender, GrowthRate -from .forms import CustomerPreferenceForm def get_analysis_date(building_id): """Fetch the proforma start date and duration from the database.""" @@ -504,75 +503,6 @@ class BillsOverviewView(View): return JsonResponse({}) -class CustomerPreferenceView(View): - """Create and update customer preference table.""" - - customer_preference_model = CustomerPreference - customer_preference_form = CustomerPreferenceForm - - def put(self, request, building_id): - """Create/Update customer preference table. - - Create a customer preference table if not present for this building - else update existing table with form data received from frontend. - - Args: - request: HTTP PUT request. - building_id: id of the building. - - Returns: - JsonResponse: Return a status that says ok. - """ - put = json.loads(request.body.decode()) - form = self.customer_preference_form({ - 'downpayment': put['Affordable-Downpayment'], - 'expected_payback': put['Expected-Payback'], - 'expected_net_noi_dscr': put['Expected-NOI-DSCR'], - }) - if form.is_valid(): - self.customer_preference_model.objects.update_or_create( - building_id=building_id, - defaults={ - 'building_id': building_id, - 'downpayment': put['Affordable-Downpayment'], - 'expected_payback': put['Expected-Payback'], - 'expected_net_noi_dscr': put['Expected-NOI-DSCR'], - } - ) - else: - 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): - """Fetch customer preference table. - - Check database if the customer preference table exists for this - building. If it does, return that data as a dictionary, else return - status saying false. - - Args: - request: HTTP GET request. - building_id: id of the building. - - Returns: - JsonResponse: Return instance as a JSON. Instance is a dictionary - that contains a status which is true of the table is - present, else says false. If table is present, - instance also contains the table values. - """ - obj = get_model_object(self.customer_preference_model, building_id) - instance = {} - if obj: - instance['downpayment'] = obj.downpayment - instance['expected_payback'] = obj.expected_payback - instance['expected_net_noi_dscr'] = obj.expected_net_noi_dscr - return JsonResponse({'instance': instance}) - return JsonResponse({}) - - class LiabilitiesTable(View): """Store and load Mortgage and Liability information for a building id.""" -- GitLab From a77b443bae5a824ac9544169475590b3cb4bbf3a Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Thu, 1 Jun 2017 16:47:55 -0400 Subject: [PATCH 07/17] Add customer preference js code to index.html --- .../apps/financialInputs/templates/financialInputs/index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/blocnote/apps/financialInputs/templates/financialInputs/index.html b/blocnote/apps/financialInputs/templates/financialInputs/index.html index 064a913..edf4892 100644 --- a/blocnote/apps/financialInputs/templates/financialInputs/index.html +++ b/blocnote/apps/financialInputs/templates/financialInputs/index.html @@ -56,4 +56,5 @@ + {% endblock %} -- GitLab From 2a7bf704a3fbacdf80d742274c145f8bf912deff Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Thu, 1 Jun 2017 16:49:17 -0400 Subject: [PATCH 08/17] Update customer preference js code to be cleaner and improved comments. --- .../scripts/customerPreference.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/blocnote/apps/financialInputs/static/financialInputs/scripts/customerPreference.js b/blocnote/apps/financialInputs/static/financialInputs/scripts/customerPreference.js index b82b3fc..6546363 100644 --- a/blocnote/apps/financialInputs/static/financialInputs/scripts/customerPreference.js +++ b/blocnote/apps/financialInputs/static/financialInputs/scripts/customerPreference.js @@ -12,12 +12,16 @@ customerPreference.onchange = function () { } /** - * Handle customer preference form submit. Make a HTTP PUT request. + * Handle customer preference form submit. Make a HTTP PUT request. If there was an error, display them else show + * saved. + * + * @param {any} form : form with the inputs filled in form html. + * @returns : false so that the document does not reload. */ function customerPreferenceForm(form) { /* Handle customer preference form submission */ const formData = new FormData(form); - const result = {}; + let result = {}; for (const [key, value] of formData.entries()) { result[key] = value; } @@ -50,6 +54,8 @@ function customerPreferenceForm(form) { /** * Create the customer preference table. Display values if previously filled else display defaults. + * + * @param {any} instance : Data received from the backend. This can be empty. */ function createCustomerPreferenceTable(instance) { let customerPreferenceForm = document.querySelector('#Customer-Preference'); @@ -62,7 +68,6 @@ function createCustomerPreferenceTable(instance) { expectedPayback = instance['expected_payback']; expectedNetNOIDSCR = instance['expected_net_noi_dscr'] } - // let text customerPreferenceForm.innerHTML = ` @@ -100,10 +105,12 @@ function createCustomerPreferenceTable(instance) {
`; - // customerPreferenceForm.innerHTML = text; } -/**Make HTTP GET request to obtain customer preference table data if present. */ +/** + * Make HTTP GET request to obtain customer preference table data if present. + * + */ function getCustomerPreferenceTable() { request(`customer-preference/`, { method: 'GET', -- GitLab From 08756c1569c4ed6ea7900a583251c41306bdcebf Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Thu, 1 Jun 2017 16:50:01 -0400 Subject: [PATCH 09/17] Create the customer preference file in views that has all the backend code for customer preference. --- .../views/customer_preference.py | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 blocnote/apps/financialInputs/views/customer_preference.py diff --git a/blocnote/apps/financialInputs/views/customer_preference.py b/blocnote/apps/financialInputs/views/customer_preference.py new file mode 100644 index 0000000..ed51ac8 --- /dev/null +++ b/blocnote/apps/financialInputs/views/customer_preference.py @@ -0,0 +1,73 @@ +"""Define the views for Customer Preference table.""" +import json +from django.views import View +from django.http import JsonResponse +from blocnote.apps.financialInputs.models import CustomerPreference +from blocnote.apps.financialInputs.forms import CustomerPreferenceForm + + +class CustomerPreferenceView(View): + """Create and update customer preference table.""" + + customer_preference_model = CustomerPreference + customer_preference_form = CustomerPreferenceForm + + def put(self, request, building_id): + """Create/Update customer preference table. + + Create a customer preference table if not present for this building else update existing table with form data + received from frontend. + + Args: + request: HTTP PUT request. + building_id: id of the building. + + Returns: + JsonResponse: Return a status that says ok if success else return status 400 with errors if form is + invalid. + """ + put = json.loads(request.body.decode()) + form = self.customer_preference_form({ + 'downpayment': put['Affordable-Downpayment'], + 'expected_payback': put['Expected-Payback'], + 'expected_net_noi_dscr': put['Expected-NOI-DSCR'], + }) + if form.is_valid(): + self.customer_preference_model.objects.update_or_create( + building_id=building_id, + defaults={ + 'building_id': building_id, + 'downpayment': put['Affordable-Downpayment'], + 'expected_payback': put['Expected-Payback'], + 'expected_net_noi_dscr': put['Expected-NOI-DSCR'], + } + ) + else: + 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): + """Fetch customer preference table. + + Check database if the customer preference table exists for this building. If it does, return that data as a + dictionary, else return empty. + + Args: + request: HTTP GET request. + building_id: id of the building. + + Returns: + instance: Dictionary with all data if record present for the building else returns empty. + """ + obj = self.customer_preference_model.objects.filter(building_id=building_id) + instance = {} + if obj: + obj = obj[0] + instance['downpayment'] = obj.downpayment + instance['expected_payback'] = obj.expected_payback + instance['expected_net_noi_dscr'] = obj.expected_net_noi_dscr + return JsonResponse({'instance': instance}) + return JsonResponse({}) -- GitLab From 76d81bd33fa9cfde69df5e8071c4902ff81ef15b Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Fri, 9 Jun 2017 17:15:28 -0400 Subject: [PATCH 10/17] Change indent in js file from 4 to 2. --- .../scripts/customerPreference.js | 113 +++++++++--------- 1 file changed, 57 insertions(+), 56 deletions(-) diff --git a/blocnote/apps/financialInputs/static/financialInputs/scripts/customerPreference.js b/blocnote/apps/financialInputs/static/financialInputs/scripts/customerPreference.js index 6546363..ca55e4b 100644 --- a/blocnote/apps/financialInputs/static/financialInputs/scripts/customerPreference.js +++ b/blocnote/apps/financialInputs/static/financialInputs/scripts/customerPreference.js @@ -1,15 +1,16 @@ 'use strict'; + getCustomerPreferenceTable(); // Watch customer preference to display/erase error/success mesaages. const customerPreference = document.querySelector('#Customer-Preference'); customerPreference.onchange = function () { - document.querySelector('#customer-preference-warning-message').innerHTML = ''; - let table = document.querySelector('#customer-preference-table'); - table.querySelector('#downpayment-error').innerHTML = ''; - table.querySelector('#expected_payback-error').innerHTML = ''; - table.querySelector('#expected_net_noi_dscr-error').innerHTML = ''; -} + document.querySelector('#customer-preference-warning-message').innerHTML = ''; + let table = document.querySelector('#customer-preference-table'); + table.querySelector('#downpayment-error').innerHTML = ''; + table.querySelector('#expected_payback-error').innerHTML = ''; + table.querySelector('#expected_net_noi_dscr-error').innerHTML = ''; +}; /** * Handle customer preference form submit. Make a HTTP PUT request. If there was an error, display them else show @@ -19,37 +20,37 @@ customerPreference.onchange = function () { * @returns : false so that the document does not reload. */ function customerPreferenceForm(form) { - /* Handle customer preference form submission */ - const formData = new FormData(form); - let result = {}; - for (const [key, value] of formData.entries()) { - result[key] = value; - } - request('customer-preference/', { - 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.err) { - document.querySelector('#customer-preference-warning-message').innerHTML = ` + /* Handle customer preference form submission */ + const formData = new FormData(form); + let result = {}; + for (const [key, value] of formData.entries()) { + result[key] = value; + } + request('customer-preference/', { + 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.err) { + document.querySelector('#customer-preference-warning-message').innerHTML = ` Saved `; - } - else { - res.err.responseBody.then((errorDict) => { - Object.keys(errorDict).forEach(function (key) { - document.querySelector('#'+key+'-error').innerHTML = ` + } + else { + res.err.responseBody.then((errorDict) => { + Object.keys(errorDict).forEach(function (key) { + document.querySelector('#' + key + '-error').innerHTML = ` ${errorDict[key][0]} `; - }); - }); - } }); - return false; + }); + } + }); + return false; } /** @@ -58,17 +59,17 @@ function customerPreferenceForm(form) { * @param {any} instance : Data received from the backend. This can be empty. */ function createCustomerPreferenceTable(instance) { - let customerPreferenceForm = document.querySelector('#Customer-Preference'); - let downpayment = 0; - let expectedPayback = 999; - let expectedNetNOIDSCR = 1.15 + let customerPreferenceForm = document.querySelector('#Customer-Preference'); + let downpayment = 0; + let expectedPayback = 999; + let expectedNetNOIDSCR = 1.15; - if (instance) { - downpayment = instance['downpayment']; - expectedPayback = instance['expected_payback']; - expectedNetNOIDSCR = instance['expected_net_noi_dscr'] - } - customerPreferenceForm.innerHTML = ` + if (instance) { + downpayment = instance['downpayment']; + expectedPayback = instance['expected_payback']; + expectedNetNOIDSCR = instance['expected_net_noi_dscr']; + } + customerPreferenceForm.innerHTML = ` @@ -112,20 +113,20 @@ function createCustomerPreferenceTable(instance) { * */ function getCustomerPreferenceTable() { - request(`customer-preference/`, { - method: 'GET', - credentials: 'same-origin', - headers: { - 'Content-Type': 'application/json' - }, - }).then(res => { - if (!res.err) { - createCustomerPreferenceTable(res.payload.instance); - } - else { - document.querySelector('#customer-preference-warning-message').innerHTML = ` + request('customer-preference/', { + method: 'GET', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json' + }, + }).then(res => { + if (!res.err) { + createCustomerPreferenceTable(res.payload.instance); + } + else { + document.querySelector('#customer-preference-warning-message').innerHTML = ` There was an error loading the table. `; - } - }); + } + }); } -- GitLab From 6a4027d45a39e767c4b4a945cc17061f7dade0b8 Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Fri, 9 Jun 2017 17:16:22 -0400 Subject: [PATCH 11/17] Update gitignore to contain some other files. --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 4db2aa8..0597f96 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,5 @@ node_modules .idea .vscode/ /static -.coverage +*.coverage +*.swp -- GitLab From 27596470682cbd951fa50a65c9091905c09510f8 Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Fri, 9 Jun 2017 17:31:00 -0400 Subject: [PATCH 12/17] Refactor code to be more generic. --- .../views/customer_preference.py | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/blocnote/apps/financialInputs/views/customer_preference.py b/blocnote/apps/financialInputs/views/customer_preference.py index ed51ac8..8e61cb9 100644 --- a/blocnote/apps/financialInputs/views/customer_preference.py +++ b/blocnote/apps/financialInputs/views/customer_preference.py @@ -27,21 +27,12 @@ class CustomerPreferenceView(View): invalid. """ put = json.loads(request.body.decode()) - form = self.customer_preference_form({ - 'downpayment': put['Affordable-Downpayment'], - 'expected_payback': put['Expected-Payback'], - 'expected_net_noi_dscr': put['Expected-NOI-DSCR'], - }) + form = self.customer_preference_form(put) if form.is_valid(): + put['building_id'] = building_id self.customer_preference_model.objects.update_or_create( building_id=building_id, - defaults={ - 'building_id': building_id, - 'downpayment': put['Affordable-Downpayment'], - 'expected_payback': put['Expected-Payback'], - 'expected_net_noi_dscr': put['Expected-NOI-DSCR'], - } - ) + defaults=put) else: error_dict = {} for field, error in form.errors.items(): @@ -62,12 +53,16 @@ class CustomerPreferenceView(View): Returns: instance: Dictionary with all data if record present for the building else returns empty. """ + fields = [ + 'downpayment', + 'expected_payback', + 'expected_net_noi_dscr', + ] obj = self.customer_preference_model.objects.filter(building_id=building_id) instance = {} if obj: obj = obj[0] - instance['downpayment'] = obj.downpayment - instance['expected_payback'] = obj.expected_payback - instance['expected_net_noi_dscr'] = obj.expected_net_noi_dscr + for field in fields: + instance[field] = obj.__dict__[field] return JsonResponse({'instance': instance}) return JsonResponse({}) -- GitLab From 6ee406d176afc8c26a646b6b2e45f76a0a171d0b Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Fri, 9 Jun 2017 17:32:14 -0400 Subject: [PATCH 13/17] Edit code to have customer preference form field names to be consistent with backend. --- .../static/financialInputs/scripts/customerPreference.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/blocnote/apps/financialInputs/static/financialInputs/scripts/customerPreference.js b/blocnote/apps/financialInputs/static/financialInputs/scripts/customerPreference.js index ca55e4b..b6967d3 100644 --- a/blocnote/apps/financialInputs/static/financialInputs/scripts/customerPreference.js +++ b/blocnote/apps/financialInputs/static/financialInputs/scripts/customerPreference.js @@ -81,7 +81,7 @@ function createCustomerPreferenceTable(instance) { @@ -89,7 +89,7 @@ function createCustomerPreferenceTable(instance) { @@ -97,7 +97,7 @@ function createCustomerPreferenceTable(instance) { -- GitLab From a5c44493db2ee5291d9eca074fc2297761620654 Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Fri, 16 Jun 2017 10:58:07 -0400 Subject: [PATCH 14/17] Change multi-line import to single line in financialInputs/forms. --- blocnote/apps/financialInputs/forms.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/blocnote/apps/financialInputs/forms.py b/blocnote/apps/financialInputs/forms.py index 0920ce6..ce532fc 100644 --- a/blocnote/apps/financialInputs/forms.py +++ b/blocnote/apps/financialInputs/forms.py @@ -1,7 +1,6 @@ """Forms to render and validate for financial-inputs endpoint.""" from django.forms import ModelForm -from blocnote.apps.financialInputs.models import FinancingOverview -from blocnote.apps.financialInputs.models import CustomerPreference +from blocnote.apps.financialInputs.models import FinancingOverview, CustomerPreference class ProformaInputsForm(ModelForm): -- GitLab From 23e9bac6679905cdf807af3b5683ef4bd72630be Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Fri, 16 Jun 2017 11:01:40 -0400 Subject: [PATCH 15/17] Modify multi-line imports to single line import in financialInputs/old_views. --- blocnote/apps/financialInputs/old_views.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/blocnote/apps/financialInputs/old_views.py b/blocnote/apps/financialInputs/old_views.py index 6341556..9298d3d 100644 --- a/blocnote/apps/financialInputs/old_views.py +++ b/blocnote/apps/financialInputs/old_views.py @@ -7,12 +7,13 @@ from django.http import JsonResponse from django.db import connections from django.views import View -from bpfin.back_end_call.back_end_inputs import monthly_bill -from bpfin.back_end_call.back_end_inputs import form_prior_income_table as prior_income_statement_table +from bpfin.back_end_call.back_end_inputs import monthly_bill, form_prior_income_table as prior_income_statement_table -from .models import FinancingOverview, Bills, BillsOverview, EstimationAlgorithm -from .models import Liabilities, CashBalance, IncomeStatement, LoanOptions, DefaultLoan, Lender, GrowthRate +from .models import ( + FinancingOverview, Bills, BillsOverview, EstimationAlgorithm, Liabilities, CashBalance, IncomeStatement, + LoanOptions, DefaultLoan, Lender, GrowthRate +) def get_analysis_date(building_id): -- GitLab From de812f78dafbcdab7ebd7f2acb2f1e026e28649b Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Fri, 16 Jun 2017 11:03:33 -0400 Subject: [PATCH 16/17] Fix some indentation in customerPreference js file. --- .../static/financialInputs/scripts/customerPreference.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blocnote/apps/financialInputs/static/financialInputs/scripts/customerPreference.js b/blocnote/apps/financialInputs/static/financialInputs/scripts/customerPreference.js index b6967d3..d4011be 100644 --- a/blocnote/apps/financialInputs/static/financialInputs/scripts/customerPreference.js +++ b/blocnote/apps/financialInputs/static/financialInputs/scripts/customerPreference.js @@ -45,7 +45,7 @@ function customerPreferenceForm(form) { Object.keys(errorDict).forEach(function (key) { document.querySelector('#' + key + '-error').innerHTML = ` ${errorDict[key][0]} - `; + `; }); }); } @@ -126,7 +126,7 @@ function getCustomerPreferenceTable() { else { document.querySelector('#customer-preference-warning-message').innerHTML = ` There was an error loading the table. - `; + `; } }); } -- GitLab From 43c1b21ab9f934a3c1b502202585803a74a6efe0 Mon Sep 17 00:00:00 2001 From: Adarsh Murthy Date: Fri, 16 Jun 2017 11:04:59 -0400 Subject: [PATCH 17/17] Fix closing paranthesis issue in financialInputs/views/customer_preference. --- blocnote/apps/financialInputs/views/customer_preference.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/blocnote/apps/financialInputs/views/customer_preference.py b/blocnote/apps/financialInputs/views/customer_preference.py index 8e61cb9..b1a6bb5 100644 --- a/blocnote/apps/financialInputs/views/customer_preference.py +++ b/blocnote/apps/financialInputs/views/customer_preference.py @@ -32,7 +32,8 @@ class CustomerPreferenceView(View): put['building_id'] = building_id self.customer_preference_model.objects.update_or_create( building_id=building_id, - defaults=put) + defaults=put + ) else: error_dict = {} for field, error in form.errors.items(): -- GitLab
Affordable Downpayment - +
Expected Payback - Months + Months
Expected Net NOI DSCR - +