diff --git a/.gitignore b/.gitignore
index 4db2aa842187c3a007a4438a4de4a89579760a9a..0597f96a51d3664e616f11f90750a853eba575eb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,4 +17,5 @@ node_modules
.idea
.vscode/
/static
-.coverage
+*.coverage
+*.swp
diff --git a/blocnote/apps/financialInputs/forms.py b/blocnote/apps/financialInputs/forms.py
index bca424db326cd75f84eee2d40b93206690ad012c..ce532fc9d92b616b208f37d3c80da30493b1a4d9 100644
--- a/blocnote/apps/financialInputs/forms.py
+++ b/blocnote/apps/financialInputs/forms.py
@@ -1,10 +1,10 @@
"""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 FinancingOverview, 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 +19,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 c2a86ae9b4c89b96919e5e2bafec6427ff9c9607..9298d3ddc512ebb25733d95ffd9a6d3d67c2e149 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 Fund, FinancingOverview, Bills, BillsOverview, CustomerPreference, 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):
@@ -504,69 +505,6 @@ class BillsOverviewView(View):
return JsonResponse({})
-class CustomerPreferenceView(View):
- """Create and update customer preference table."""
-
- model = CustomerPreference
-
- 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())
- obj = self.model.objects.filter(building_id=building_id)
- if obj:
- obj.update(
- 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']
- )
- 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.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."""
diff --git a/blocnote/apps/financialInputs/static/financialInputs/scripts/app.js b/blocnote/apps/financialInputs/static/financialInputs/scripts/app.js
index c679f63f565bd025f39d56d915e6b73df1e40458..416d0b5c4ec60e827876cb18f74e08f7ef81c529 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,95 +417,6 @@ function billsOverviewFormSubmit(form) {
return false;
}
-// Watch customer preference to display/erase error/success mesaages.
-var customerPreference = document.querySelector('#Customer-Preference');
-customerPreference.onchange = function() {
- document.querySelector('#customer-preference-warning-message').innerHTML = '';
-}
-
-/**
- * Handle customer preference form submit. Make a HTTP PUT request.
- */
-function customerPreferenceForm(form) {
- /* Handle customer preference form submission */
- 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.payload.err) {
- document.querySelector('#customer-preference-warning-message').innerHTML = `
- Saved
- `;
- }
- });
- return false;
-}
-
-/**
- * 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
-
- if (instance) {
- var downpayment = instance['downpayment'];
- var expectedPayback = instance['expected_payback'];
- var expectedNetNOIDSCR = instance['expected_net_noi_dscr']
- }
- var text = `
-
-
- `;
- 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 => {
- createCustomerPreferenceTable(res.payload.instance);
- });
-}
-
/**
* 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
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 0000000000000000000000000000000000000000..d4011be5f8ef6138508be8dba8f92527603f88ac
--- /dev/null
+++ b/blocnote/apps/financialInputs/static/financialInputs/scripts/customerPreference.js
@@ -0,0 +1,132 @@
+'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. 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);
+ 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 = `
+ ${errorDict[key][0]}
+ `;
+ });
+ });
+ }
+ });
+ return false;
+}
+
+/**
+ * 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');
+ 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 = `
+
+
+ `;
+}
+
+/**
+ * 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.
+ `;
+ }
+ });
+}
diff --git a/blocnote/apps/financialInputs/templates/financialInputs/index.html b/blocnote/apps/financialInputs/templates/financialInputs/index.html
index 064a91370da324dd5c9e636745eb7de9fa07962e..edf4892314b507a29bad191a75285fa18b4fe616 100644
--- a/blocnote/apps/financialInputs/templates/financialInputs/index.html
+++ b/blocnote/apps/financialInputs/templates/financialInputs/index.html
@@ -56,4 +56,5 @@
+
{% endblock %}
diff --git a/blocnote/apps/financialInputs/urls.py b/blocnote/apps/financialInputs/urls.py
index cf298f6e6286245998e7498c284ea2ab9b44427f..f27b683542619dea2052549774b359ac0e0995c4 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'),
diff --git a/blocnote/apps/financialInputs/views/customer_preference.py b/blocnote/apps/financialInputs/views/customer_preference.py
new file mode 100644
index 0000000000000000000000000000000000000000..b1a6bb572b19771adefa05b93eeda9e3adff2b3c
--- /dev/null
+++ b/blocnote/apps/financialInputs/views/customer_preference.py
@@ -0,0 +1,69 @@
+"""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(put)
+ if form.is_valid():
+ put['building_id'] = building_id
+ self.customer_preference_model.objects.update_or_create(
+ building_id=building_id,
+ defaults=put
+ )
+ 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.
+ """
+ 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]
+ for field in fields:
+ instance[field] = obj.__dict__[field]
+ return JsonResponse({'instance': instance})
+ return JsonResponse({})