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
+
+ Security
+
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'))