diff --git a/cloud/endagaweb/forms/dashboard_forms.py b/cloud/endagaweb/forms/dashboard_forms.py index 2f9a6ddc..097fb625 100644 --- a/cloud/endagaweb/forms/dashboard_forms.py +++ b/cloud/endagaweb/forms/dashboard_forms.py @@ -368,3 +368,46 @@ def __init__(self, *args, **kwargs): self.helper.form_action = '/dashboard/staff/tower-monitoring' self.helper.add_input(Submit('submit', 'Select')) self.helper.layout = Layout('tower') + + +class NetworkBalanceLimit(forms.Form): + + """Crispy form to set Network balance limit and transaction. + set min_value =0.01 so that it will not accept 0 value""" + + max_balance_title = 'Maximum account balance of an imsi within a network.' + max_balance = forms.CharField(required=False, label="Maximum Balance Limit", + max_length=10, + widget=forms.TextInput(attrs = {'title': max_balance_title})) + max_unsuccessful_transaction_title ='Maximum consecutive failure ' \ + 'transactions an imsi can perform ' \ + 'within 24 hrs.' + max_unsuccessful_transaction = forms.CharField(required=False, max_length=3, + label='Maximum Permissible ' + 'Unsuccessful Transactions', + widget=forms.TextInput + (attrs={'title': max_unsuccessful_transaction_title})) + + def __init__(self, *args, **kwargs): + super(NetworkBalanceLimit, self).__init__(*args, **kwargs) + self.helper = FormHelper() + self.helper.form_id = 'id-NetworkBalanceLimitForm' + self.helper.form_method = 'post' + self.helper.form_action = '/dashboard/network/balance-limit' + self.helper.form_class = 'col-xs-12 col-sm-8 col-md-12 col-xl-8' + self.helper.add_input(Submit('submit', 'Save')) + self.helper.layout = Layout('max_balance', 'max_unsuccessful_transaction') + + def clean_network_balance(self): + cleaned_data = super(NetworkBalanceLimit, self).clean() + max_balance = self.cleaned_data.get('max_balance', None) + max_unsuccessful_transaction = self.cleaned_data.get( + 'max_unsuccessful_transaction', None) + if max_balance == "" and max_unsuccessful_transaction == "": + raise forms.ValidationError('Error : please provide value.') + if max_balance != "": + if float(max_balance) <= 0: + raise forms.ValidationError( + 'Error : enter positive and non-zero value for ' + 'maximum balance Limit.') + return cleaned_data diff --git a/cloud/endagaweb/models.py b/cloud/endagaweb/models.py index 65b0780f..496fb441 100644 --- a/cloud/endagaweb/models.py +++ b/cloud/endagaweb/models.py @@ -978,6 +978,9 @@ class Network(models.Model): # Network environments let you specify things like "prod", "test", "dev", # etc so they can be filtered out of alerts. For internal use. environment = models.TextField(default="default") + # Added for Network Balance Limit + max_balance = models.BigIntegerField(default=10000) + max_failure_transaction = models.PositiveIntegerField(blank=True, default=3) class Meta: permissions = ( diff --git a/cloud/endagaweb/templates/dashboard/network_detail/denomination.html b/cloud/endagaweb/templates/dashboard/network_detail/denomination.html index 3e7582f0..9ca473a3 100644 --- a/cloud/endagaweb/templates/dashboard/network_detail/denomination.html +++ b/cloud/endagaweb/templates/dashboard/network_detail/denomination.html @@ -71,8 +71,10 @@ Start Amount *
- + +
@@ -83,8 +85,10 @@ End Amount *
- + +
@@ -95,8 +99,10 @@ Validity (days)*
- + +
diff --git a/cloud/endagaweb/templates/dashboard/network_detail/nav.html b/cloud/endagaweb/templates/dashboard/network_detail/nav.html index d2c2d396..9a5a1d98 100644 --- a/cloud/endagaweb/templates/dashboard/network_detail/nav.html +++ b/cloud/endagaweb/templates/dashboard/network_detail/nav.html @@ -43,5 +43,11 @@ {% else %}{% url 'network-edit' %} {% endif %}">Edit + diff --git a/cloud/endagaweb/templates/dashboard/network_detail/network-balancelimit.html b/cloud/endagaweb/templates/dashboard/network_detail/network-balancelimit.html new file mode 100644 index 00000000..cc12ee73 --- /dev/null +++ b/cloud/endagaweb/templates/dashboard/network_detail/network-balancelimit.html @@ -0,0 +1,114 @@ +{% extends "dashboard/layout.html" %} +{% comment %} +Copyright (c) 2016-present, Facebook, Inc. +All rights reserved. + +This source code is licensed under the BSD-style license found in the +LICENSE file in the root directory of this source tree. An additional grant +of patent rights can be found in the PATENTS file in the same directory. +{% endcomment %} +{% load apptags %} +{% load humanize %} +{% load crispy_forms_tags %} + + +{% block title %} +{% if network.name %} +{% tmpl_const "SITENAME" %} | "{{ network.name }}" +{% else %} +{% tmpl_const "SITENAME" %} | Network +{% endif %} +{% endblock %} + + +{% block pagestyle %} + +{% endblock %} + + +{% block content %} + + +{% include "dashboard/network_detail/header.html" with network=network %} + + +
+ {% include "dashboard/network_detail/nav.html" with active_tab='security'%} + +
+
+
+ {% if user_profile.user.is_staff %} + {% crispy network_balance_limit_form %} + {% endif %} +

Network current maximum balance limit: {% currency network.max_balance %}

+

Maximum permissible unsuccessful transactions current limit: {{ network.max_failure_transaction }}

+
+
+ {% for message in messages %} +
{{ message }}
+ {% endfor %} +
+
+ +
+
+ {% endblock %} +{% block js %} + + + +{% endblock %} + diff --git a/cloud/endagaweb/tests/test_network_limit.py b/cloud/endagaweb/tests/test_network_limit.py new file mode 100644 index 00000000..86ba199f --- /dev/null +++ b/cloud/endagaweb/tests/test_network_limit.py @@ -0,0 +1,106 @@ +"""Tests for NetworkBalanceLimit form + +Copyright (c) 2016-present, Facebook, Inc. +All rights reserved. + +This source code is licensed under the BSD-style license found in the +LICENSE file in the root directory of this source tree. An additional grant +of patent rights can be found in the PATENTS file in the same directory. +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals +from django import test +from django.test import TestCase +from endagaweb import models + + +class TestBase(TestCase): + + @classmethod + def setUpClass(cls): + cls.username = 'testuser' + cls.password = 'testpw' + cls.user = models.User(username=cls.username, email='y@l.com') + cls.user.set_password(cls.password) + cls.user.save() + cls.user_profile = models.UserProfile.objects.get(user=cls.user) + cls.uuid = "59216199-d664-4b7a-a2db-6f26e9a5d208" + # Create a test client. + cls.client = test.Client() + + @classmethod + def tearDownClass(cls): + cls.user.delete() + cls.user_profile.delete() + + def tearDown(self): + self.logout() + + def login(self): + """Log the client in.""" + data = { + 'email': self.username, + 'password': self.password, + } + self.client.post('/auth/', data) + + def logout(self): + """Log the client out.""" + self.client.get('/logout') + + +class NetworkLimitUITest(TestBase): + """Testing Network Limit UI.""" + + def test_network_balance_limit_unauth_get_request(self): + self.logout() + response = self.client.get('/dashboard/network/balance-limit') + self.assertEqual(302, response.status_code) + + def test_network_balance_limit_auth_get_request(self): + self.login() + response = self.client.get('/dashboard/network/balance-limit') + self.assertEqual(200, response.status_code) + + def test_post_bad_response_with_invalid_input_limits(self): + self.login() + data = { + 'max_balances': 1, + 'max_unsuccessful_transaction': 2, + + } + response = self.client.post('/dashboard/network/balance-limit', data) + self.assertEqual(400, response.status_code) + + def test_post_bad_response_with_invalid_input_transactions(self): + self.login() + data = { + 'max_balance': 1, + 'max_unsuccessful_transactions': 2, + + } + response = self.client.post('/dashboard/network/balance-limit', data) + self.assertEqual(400, response.status_code) + + def test_post_response_redirect_status_code(self): + self.login() + data = { + 'max_balance': 4, + 'max_unsuccessful_transaction': 6, + + } + response = self.client.post('/dashboard/network/balance-limit', data) + self.assertEqual(302, response.status_code) + + def test_post_response_redirect_url(self): + self.login() + data = { + 'max_balance': 4, + 'max_unsuccessful_transaction': 6, + + } + response = self.client.post('/dashboard/network/balance-limit', data) + self.assertEqual('/dashboard/network/balance-limit', response.url) diff --git a/cloud/endagaweb/urls.py b/cloud/endagaweb/urls.py index d2b8d10c..1398e5cb 100644 --- a/cloud/endagaweb/urls.py +++ b/cloud/endagaweb/urls.py @@ -153,6 +153,10 @@ name='network-edit'), url(r'^dashboard/network/select/(?P[0-9]+)$', endagaweb.views.network.NetworkSelectView.as_view()), + # Added for network balance limit + url(r'^dashboard/network/balance-limit', + endagaweb.views.network.NetworkBalanceLimit.as_view(), + name='network_balance_limit'), # The activity table. url(r'^dashboard/activity', endagaweb.views.dashboard.ActivityView.as_view(), diff --git a/cloud/endagaweb/views/dashboard.py b/cloud/endagaweb/views/dashboard.py index 5dc78be4..29621558 100644 --- a/cloud/endagaweb/views/dashboard.py +++ b/cloud/endagaweb/views/dashboard.py @@ -554,6 +554,7 @@ def post(self, request, imsi=None): return HttpResponseBadRequest() error_text = 'Error: credit value must be between -10M and 10M.' try: + currency = network.subscriber_currency amount = parse_credits(request.POST['amount'], CURRENCIES[currency]).amount_raw diff --git a/cloud/endagaweb/views/network.py b/cloud/endagaweb/views/network.py index 318335c4..6cbe8ecc 100644 --- a/cloud/endagaweb/views/network.py +++ b/cloud/endagaweb/views/network.py @@ -28,6 +28,8 @@ from endagaweb.forms import dashboard_forms from endagaweb.views.dashboard import ProtectedView from endagaweb.views import django_tables +from endagaweb.forms import dashboard_forms as dform +from django.core import exceptions NUMBER_COUNTRIES = { @@ -651,3 +653,79 @@ def delete(self, request): extra_tags='alert alert-danger') return http.HttpResponse(json.dumps(response), content_type="application/json") + + +class NetworkBalanceLimit(ProtectedView): + """Edit basic network info (to add credit to Network).""" + + def get(self, request): + """Handles GET requests.""" + user_profile = models.UserProfile.objects.get(user=request.user) + network = user_profile.network + # Set the context with various stats. + context = { + 'networks': get_objects_for_user(request.user, 'view_network', + klass=models.Network), + 'user_profile': user_profile, + 'network': network, + 'currency': CURRENCIES[network.subscriber_currency], + 'network_balance_limit_form': dashboard_forms.NetworkBalanceLimit({ + 'max_balance': '', + 'max_unsuccessful_transaction': '', + + }), + } + # Render template. + edit_template = template.loader.get_template( + 'dashboard/network_detail/network-balancelimit.html') + html = edit_template.render(context, request) + return http.HttpResponse(html) + + def post(self, request): + """Handles POST requests.""" + user_profile = models.UserProfile.objects.get(user=request.user) + network = user_profile.network + success = [] + if 'max_balance' not in request.POST: + return http.HttpResponseBadRequest() + if 'max_unsuccessful_transaction' not in request.POST: + return http.HttpResponseBadRequest() + try: + form = dform.NetworkBalanceLimit(data=request.POST) + if form.is_valid(): + cleaned_field_data = form.clean_network_balance() + max_balance = cleaned_field_data.get("max_balance") + max_failure_transaction = cleaned_field_data.get("max_unsuccessful_transaction") + with transaction.atomic(): + try: + currency = network.subscriber_currency + if max_balance: + balance = float(max_balance) + max_network_amount = parse_credits(balance, + CURRENCIES[ + currency]).amount_raw + network.max_balance = max_network_amount + print("stored valued ", network.max_balance) + success.append( + 'Network maximum balance limit updated.') + if max_failure_transaction: + transaction_val = int(max_failure_transaction) + network.max_failure_transaction = transaction_val + success.append( + 'Network maximun permissible unsuccessful' + ' transactions limit updated.') + network.save() + except ValueError: + error_text = 'Error : please provide valid value.' + messages.error(request, error_text, + extra_tags="alert alert-danger") + return redirect( + urlresolvers.reverse('network_balance_limit')) + messages.success(request, + ''.join(success), + extra_tags="alert alert-success") + return redirect(urlresolvers.reverse('network_balance_limit')) + except exceptions.ValidationError as e: + tags = 'password alert alert-danger' + messages.error(request, ''.join(e.messages), extra_tags=tags) + return redirect(urlresolvers.reverse('network_balance_limit'))