Browse Source

Merge branch 'devel' into separate_network

Conflicts:
	abonapp/templates/abonapp/group_list.html
	abonapp/templates/abonapp/peoples.html
	abonapp/views.py
	agent/commands/dhcp.py
	devapp/dev_types.py
	devapp/templates/devapp/devices_null_group.html
	djing/global_base_views.py
	docs/dev.md
	group_app/templates/group_app/group_list.html

 Изменения, которые будут включены в коммит:
	изменено:      abonapp/forms.py
	изменено:      abonapp/templates/abonapp/group_list.html
	изменено:      abonapp/templates/abonapp/peoples.html
	удалено:       abonapp/templatetags/__init__.py
	изменено:      abonapp/views.py
	изменено:      clientsideapp/templates/clientsideapp/ext.html
	изменено:      devapp/dev_types.py
	изменено:      devapp/forms.py
	изменено:      devapp/models.py
	изменено:      devapp/templates/devapp/devices.html
	изменено:      devapp/templates/devapp/devices_null_group.html
	изменено:      devapp/templates/devapp/manage_ports/list.html
	изменено:      devapp/views.py
	изменено:      djing/fields.py
	изменено:      djing/global_base_views.py
	изменено:      djing/local_settings.py.template
	изменено:      djing/settings.py
	переименовано: abonapp/templatetags/dpagination.py -> djing/templatetags/dpagination.py
	изменено:      docs/dev.md
	изменено:      group_app/templates/group_app/group_list.html
	изменено:      group_app/views.py
	изменено:      searchapp/views.py
	изменено:      tariff_app/templates/tariff_app/tarifs.html
	изменено:      tariff_app/views.py

 Изменения, которые не в индексе для коммита:
	изменено:      abonapp/views.py
	изменено:      ip_pool/views.py
devel
bashmak 8 years ago
parent
commit
402737dc0f
  1. 2
      abonapp/forms.py
  2. 5
      abonapp/templates/abonapp/group_list.html
  3. 8
      abonapp/templates/abonapp/peoples.html
  4. 0
      abonapp/templatetags/__init__.py
  5. 12
      abonapp/views.py
  6. 24
      clientsideapp/templates/clientsideapp/ext.html
  7. 1
      devapp/dev_types.py
  8. 14
      devapp/forms.py
  9. 10
      devapp/models.py
  10. 6
      devapp/templates/devapp/devices.html
  11. 7
      devapp/templates/devapp/devices_null_group.html
  12. 2
      devapp/templates/devapp/manage_ports/list.html
  13. 11
      devapp/views.py
  14. 6
      djing/fields.py
  15. 10
      djing/global_base_views.py
  16. 2
      djing/local_settings.py.template
  17. 1
      djing/settings.py
  18. 12
      djing/templatetags/dpagination.py
  19. 2
      docs/dev.md
  20. 3
      group_app/templates/group_app/group_list.html
  21. 6
      group_app/views.py
  22. 8
      searchapp/views.py
  23. 9
      tariff_app/templates/tariff_app/tarifs.html
  24. 15
      tariff_app/views.py

2
abonapp/forms.py

@ -15,7 +15,7 @@ def generate_random_chars(length=6, chars=digits, split=2, delimiter=''):
try:
models.Abon.objects.get(username=username)
return generate_random_username(length=length, chars=chars, split=split, delimiter=delimiter)
return generate_random_chars(length=length, chars=chars, split=split, delimiter=delimiter)
except models.Abon.DoesNotExist:
return username

5
abonapp/templates/abonapp/group_list.html

@ -1,5 +1,6 @@
{% extends 'base.html' %}
{% load i18n %}
{% load dpagination %}
{% block breadcrumb %}
<ol class="breadcrumb">
@ -9,7 +10,7 @@
{% endblock %}
{% block page-header %}
<h3>{% trans 'User groups' %}</h3>
{% trans 'User groups' %}
{% endblock %}
{% block main %}
@ -19,7 +20,7 @@
<tr>
<th width="50">#</th>
<th>
<a href="{% url 'abonapp:group_list' %}?order_by=title&dir={{ dir|default:'down' }}">
<a href="{% url 'abonapp:group_list' %}?{% url_order_by request order_by='title' %}">
{% trans 'Group title' %}
</a>
{% if order_by == 'title' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}

8
abonapp/templates/abonapp/peoples.html

@ -25,7 +25,7 @@
<tr>
<th>#</th>
<th class="col-xs-1">
<a href="{% url 'abonapp:people_list' group.pk %}?{% url_replace request order_by='username' dir=dir|default:'down' %}">
<a href="{% url 'abonapp:people_list' group.pk %}?{% url_order_by request order_by='username' %}">
{% trans 'Sub' %}
</a>
{% if order_by == 'username' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
@ -38,13 +38,13 @@
{% if order_by == 'fio' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
</th>
<th class="col-xs-2">
<a href="{% url 'abonapp:people_list' group.pk %}?{% url_replace request order_by='street' dir=dir|default:'down' %}">
<a href="{% url 'abonapp:people_list' group.pk %}?{% url_order_by request order_by='street' %}">
{% trans 'Street' %}
</a>
{% if order_by == 'street' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
</th>
<th class="col-xs-1">
<a href="{% url 'abonapp:people_list' group.pk %}?{% url_replace request order_by='house' dir=dir|default:'down' %}">
<a href="{% url 'abonapp:people_list' group.pk %}?{% url_order_by request order_by='house' %}">
{% trans 'Apartment' %}
</a>
{% if order_by == 'house' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
@ -52,7 +52,7 @@
<th class="col-xs-1">{% trans 'Telephone' %}</th>
<th class="col-xs-2">{% trans 'Service' %}</th>
<th class="hidden-xs col-sm-1">
<a href="{% url 'abonapp:people_list' group.pk %}?{% url_replace request order_by='ballance' dir=dir|default:'down' %}">
<a href="{% url 'abonapp:people_list' group.pk %}?{% url_order_by request order_by='ballance' %}">
{% trans 'Balance' %}
</a>
{% if order_by == 'ballance' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}

0
abonapp/templatetags/__init__.py

12
abonapp/views.py

@ -1,6 +1,6 @@
from typing import Dict, Optional
from django.contrib.gis.shortcuts import render_to_text
from django.core.exceptions import PermissionDenied
from django.core.exceptions import PermissionDenied, ValidationError
from django.db import IntegrityError, ProgrammingError, transaction
from django.db.models import Count, Q
from django.shortcuts import render, redirect, get_object_or_404, resolve_url
@ -590,7 +590,8 @@ def clear_dev(request, gid, uname):
abon = models.Abon.objects.get(username=uname)
abon.device = None
abon.dev_port = None
abon.save(update_fields=('device', 'dev_port'))
abon.is_dynamic_ip = False
abon.save(update_fields=('device', 'dev_port', 'is_dynamic_ip'))
messages.success(request, _('Device has successfully unattached'))
except models.Abon.DoesNotExist:
messages.error(request, _('Abon does not exist'))
@ -1026,6 +1027,13 @@ class EditSibscriberMarkers(UpdateView):
obj = models.Abon.objects.get(username=self.kwargs.get('uname'))
return obj
def dispatch(self, request, *args, **kwargs):
try:
return super(EditSibscriberMarkers, self).dispatch(request, *args, **kwargs)
except ValidationError as e:
messages.error(request, e)
return self.render_to_response(self.get_context_data())
def get_context_data(self, **kwargs):
context = super(EditSibscriberMarkers, self).get_context_data(**kwargs)
context['gid'] = self.kwargs.get('gid')

24
clientsideapp/templates/clientsideapp/ext.html

@ -51,18 +51,18 @@
<a href="{{ client_side_services }}">{% trans 'Services' %}</a>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">{% trans 'Language' %} <b class="caret"></b></a>
<ul class="dropdown-menu">
{% url 'set_language' as set_language_url %}
{% for lang in LANGUAGES %}
<li><a href="#" id="langfrm_{{ lang.0 }}" onclick="document.setLang{{ lang.0 }}.submit();">{{ lang.1 }}</a></li>
<form name="setLang{{ lang.0}}" action="{{ set_language_url }}" method="POST" class="hidden">{% csrf_token %}
<input type="hidden" name="language" value="{{ lang.0 }}">
</form>
{% endfor %}
</ul>
</li>
{# <li class="dropdown">#}
{# <a href="#" class="dropdown-toggle" data-toggle="dropdown">{% trans 'Language' %} <b class="caret"></b></a>#}
{# <ul class="dropdown-menu">#}
{# {% url 'set_language' as set_language_url %}#}
{# {% for lang in LANGUAGES %}#}
{# <li><a href="#" id="langfrm_{{ lang.0 }}" onclick="document.setLang{{ lang.0 }}.submit();">{{ lang.1 }}</a></li>#}
{# <form name="setLang{{ lang.0}}" action="{{ set_language_url }}" method="POST" class="hidden">{% csrf_token %}#}
{# <input type="hidden" name="language" value="{{ lang.0 }}">#}
{# </form>#}
{# {% endfor %}#}
{# </ul>#}
{# </li>#}
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">{% trans 'Other' %} <b class="caret"></b></a>

1
devapp/dev_types.py

@ -311,6 +311,7 @@ class EltexPort(BasePort):
class EltexSwitch(DLinkDevice):
description = _('Eltex switch')
is_use_device_port = False
has_attachable_to_subscriber = True
def get_ports(self) -> ListOrError:
res = []

14
devapp/forms.py

@ -9,6 +9,20 @@ from djing import MAC_ADDR_REGEX, IP_ADDR_REGEX
class DeviceForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
"""
Move comment from value to placeholder in HTML form
"""
initial = kwargs.get('initial')
if initial:
comment = initial.get('comment')
del initial['comment']
else:
comment = None
super(DeviceForm, self).__init__(*args, **kwargs)
self.fields['comment'].widget.attrs['placeholder'] = comment
mac_addr = forms.CharField(widget=forms.TextInput(attrs={
'pattern': MAC_ADDR_REGEX,
'required': True

10
devapp/models.py

@ -74,11 +74,11 @@ class Device(models.Model):
return self.status
def get_manager_klass(self):
klasses = tuple(kl for kl in self.DEVICE_TYPES if kl[0] == self.devtype)
if len(klasses) > 0:
res = klasses[0][1]
if issubclass(res, DevBase):
return res
klasses = next(kl for kl in self.DEVICE_TYPES if kl[0] == self.devtype)
if klasses:
code, dev_class = klasses
if issubclass(dev_class, DevBase):
return dev_class
raise TypeError('one of types is not subclass of DevBase. '
'Or implementation of that device type is not found')

6
devapp/templates/devapp/devices.html

@ -21,20 +21,20 @@
<tr>
<th>#</th>
<th class="col-md-2">
<a href="{% url 'devapp:devs' group.pk %}?{% url_replace request order_by='ip_address' dir=dir|default:'down' %}">
<a href="{% url 'devapp:devs' group.pk %}?{% url_order_by request order_by='ip_address' %}">
{% trans 'Ip address' %}
</a>
{% if order_by == 'ip_address' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
</th>
<th class="col-md-5">
<a href="{% url 'devapp:devs' group.pk %}?{% url_replace request order_by='comment' dir=dir|default:'down' %}">
<a href="{% url 'devapp:devs' group.pk %}?{% url_order_by request order_by='comment' %}">
{% trans 'Comment' %}
</a>
{% if order_by == 'comment' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
</th>
<th class="col-md-3">{% trans 'Mac address' %}</th>
<th class="col-md-1">
<a href="{% url 'devapp:devs' group.pk %}?{% url_replace request order_by='devtype' dir=dir|default:'down' %}">
<a href="{% url 'devapp:devs' group.pk %}?{% url_order_by request order_by='devtype' %}">
{% trans 'Device type' %}
</a>
{% if order_by == 'devtype' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}

7
devapp/templates/devapp/devices_null_group.html

@ -1,5 +1,6 @@
{% extends request.is_ajax|yesno:'bajax.html,base.html' %}
{% load i18n %}
{% load dpagination %}
{% block breadcrumb %}
<ol class="breadcrumb">
@ -19,19 +20,19 @@
<thead>
<tr>
<th>
<a href="{% url 'devapp:devices_null_group' %}?order_by=ip_address&dir={{ dir|default:'down' }}">
<a href="{% url 'devapp:devices_null_group' %}?{% url_order_by request order_by='ip_address' %}">
{% trans 'Ip address' %}
</a>
{% if order_by == 'ip_address' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
</th>
<th>
<a href="{% url 'devapp:devices_null_group' %}?order_by=comment&dir={{ dir|default:'down' }}">
<a href="{% url 'devapp:devices_null_group' %}?{% url_order_by request order_by='comment' %}">
{% trans 'Comment' %}
</a>
{% if order_by == 'comment' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
</th>
<th width="250">
<a href="{% url 'devapp:devices_null_group' %}?order_by=devtype&dir={{ dir|default:'down' }}">
<a href="{% url 'devapp:devices_null_group' %}?{% url_order_by request order_by='devtype' %}">
{% trans 'Device type' %}
</a>
{% if order_by == 'devtype' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}

2
devapp/templates/devapp/manage_ports/list.html

@ -27,7 +27,7 @@
{% else %}
<td>{{ port.num_abons }}</td>
{% endif %}
<td class="btn-group btn-group-sm">
<td class="btn-group btn-group-sm btn-group-justified">
<a href="{% url 'devapp:show_subscriber_on_port' gid did port.id %}" class="btn btn-default btn-modal" title="{% trans 'Show subscriber on port' %}" data-toggle="tooltip">
<span class="glyphicon glyphicon-eye-open"></span>
</a>

11
devapp/views.py

@ -30,13 +30,8 @@ from .models import Device, Port, DeviceDBException, DeviceMonitoringException
from .forms import DeviceForm, PortForm, DeviceExtraDataForm
class BaseDeviceListView(global_base_views.BaseListWithFiltering):
http_method_names = ('get',)
paginate_by = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10)
@method_decorator((login_required, only_admins), name='dispatch')
class DevicesListView(global_base_views.OrderingMixin, BaseDeviceListView):
class DevicesListView(global_base_views.OrderedFilteredList):
context_object_name = 'devices'
template_name = 'devapp/devices.html'
@ -63,7 +58,7 @@ class DevicesListView(global_base_views.OrderingMixin, BaseDeviceListView):
@method_decorator((login_required, only_admins), name='dispatch')
class DevicesWithoutGroupsListView(global_base_views.OrderingMixin, BaseDeviceListView):
class DevicesWithoutGroupsListView(global_base_views.OrderedFilteredList):
context_object_name = 'devices'
template_name = 'devapp/devices_null_group.html'
queryset = Device.objects.filter(group=None).only('comment', 'devtype', 'pk', 'ip_address')
@ -505,7 +500,7 @@ def toggle_port(request, device_id: int, portid: int, status=0):
@method_decorator((login_required, only_admins), name='dispatch')
class GroupsListView(BaseDeviceListView):
class GroupsListView(global_base_views.OrderedFilteredList):
context_object_name = 'groups'
template_name = 'devapp/group_list.html'
model = Group

6
djing/fields.py

@ -91,11 +91,11 @@ class MACAddressField(models.Field):
return self.get_prep_value(value)
except AddrFormatError:
return None
elif lookup_type in ('in'):
elif lookup_type == 'in':
try:
macs = []
for mac in value:
macs += [self.get_prep_value(mac)]
macs.extend(self.get_prep_value(mac))
return macs
except AddrFormatError:
return None
@ -106,7 +106,7 @@ class MACAddressField(models.Field):
try:
from south.modelsinspector import add_introspection_rules
add_introspection_rules([], ["^macaddress\.fields\.MACAddressField"])
add_introspection_rules((), ("^macaddress\.fields\.MACAddressField",))
except ImportError:
pass

10
djing/global_base_views.py

@ -80,14 +80,6 @@ class OrderingMixin(object):
def get_context_data(self, **kwargs):
context = super(OrderingMixin, self).get_context_data(**kwargs)
context['order_by'] = self.request.GET.get('order_by')
direction = self.request.GET.get('dir')
if direction == 'down':
direction = 'up'
elif direction == 'up':
direction = 'down'
else:
direction = ''
context['dir'] = direction
return context
def get_ordering(self):
@ -149,5 +141,5 @@ class BaseListWithFiltering(RedirectWhenErrorMixin, ListView):
})
class BaseOrderedFilteringList(OrderingMixin, BaseListWithFiltering):
class OrderedFilteredList(OrderingMixin, BaseListWithFiltering):
paginate_by = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10)

2
djing/local_settings.py.template

@ -4,7 +4,7 @@ Custom settings for each system
DEBUG = True
ALLOWED_HOSTS = ['*']
ALLOWED_HOSTS = '*',
DEFAULT_FROM_EMAIL = 'admin@yoursite.com'

1
djing/settings.py

@ -93,6 +93,7 @@ TEMPLATES = [
],
'libraries': {
'globaltags': 'djing.templatetags.globaltags',
'dpagination': 'djing.templatetags.dpagination'
}
},
},

12
abonapp/templatetags/dpagination.py → djing/templatetags/dpagination.py

@ -11,8 +11,18 @@ def url_page_replace(request, field, value):
@register.simple_tag
def url_replace(request, *args, **kwargs):
def url_order_by(request, **kwargs):
dict_ = request.GET.copy()
for k, v in kwargs.items():
dict_[k] = v
direction = dict_.get('dir')
if direction is None:
direction = dict_.get('default_direction', 'up')
if direction == 'down':
direction = 'up'
elif direction == 'up':
direction = 'down'
else:
direction = ''
dict_['dir'] = direction
return dict_.urlencode()

2
docs/dev.md

@ -97,7 +97,7 @@ class EltexSwitch(DLinkDevice):
Свойство **@is_use_device_port** используется в DHCP чтоб понять что мы используем для привязки к абоненту всё устройство или
только порт устройства. Например, если у устройства только 1 порт абонента (PON ONU), и мы привязываем этого абонента ко всему устройству
а не к порту, то нужно вернуть False, На обычных свичах где мы авторизуем абонента на порту возвращаем True.
а не к порту, то нужно указать False, На обычных свичах где мы авторизуем абонента на порту возвращаем True.
Реализация SNMPBaseWorker по сути не нужна, класс абстрактных методов не имеет.
Потому когда наследуем наследуемся от *DevBase* то в базовые классы добавим и SNMPBaseWorker, как это сделано в *DLinkDevice*:

3
group_app/templates/group_app/group_list.html

@ -1,5 +1,6 @@
{% extends 'base.html' %}
{% load i18n %}
{% load dpagination %}
{% block breadcrumb %}
<ol class="breadcrumb">
@ -22,7 +23,7 @@
<th width="50">#</th>
<th width="50">{% trans 'TeCo' %}</th>
<th>
<a href="{% url 'group_app:group_list' %}?order_by=title&dir={{ dir|default:'down' }}">
<a href="{% url 'group_app:group_list' %}?{% url_order_by request order_by='title' %}">
{% trans 'Title' %}
</a>
{% if order_by == 'title' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}

6
group_app/views.py

@ -1,6 +1,6 @@
from django.db.models import Count
from django.http import HttpResponseRedirect
from django.views.generic import ListView, UpdateView, CreateView, DeleteView
from django.views.generic import UpdateView, CreateView, DeleteView
from django.contrib.auth.decorators import login_required
from django.utils.translation import gettext_lazy as _
from django.utils.decorators import method_decorator
@ -8,12 +8,14 @@ from django.urls import reverse_lazy
from django.contrib import messages
from django.conf import settings
from guardian.decorators import permission_required_or_403 as permission_required
from djing.global_base_views import OrderedFilteredList
from . import models
from . import forms
@method_decorator(login_required, name='dispatch')
class GroupListView(ListView):
class GroupListView(OrderedFilteredList):
http_method_names = ('get',)
paginate_by = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10)
template_name = 'group_app/group_list.html'

8
searchapp/views.py

@ -23,16 +23,18 @@ def home(request):
devices = Device.objects.filter(ip_address=s)
else:
abons = Abon.objects.filter(
Q(fio__icontains=s) | Q(username__icontains=s) | Q(telephone__icontains=s)
Q(fio__icontains=s) | Q(username__icontains=s) | Q(telephone__icontains=s) |
Q(additional_telephones__telephone__icontains=s)
)
if re.match(MAC_ADDR_REGEX, s):
devices = Device.objects.filter(mac_addr=s)
else:
devices = Device.objects.filter(comment__icontains=s)
else:
abons = []
devices = []
abons = ()
devices = ()
for abn in abons:
abn.fio = replace_without_case(escape(abn.fio), s, "<b>%s</b>" % s)

9
tariff_app/templates/tariff_app/tarifs.html

@ -1,5 +1,6 @@
{% extends request.is_ajax|yesno:'nullcont.htm,tariff_app/ext.html' %}
{% load i18n %}
{% load dpagination %}
{% block content %}
<div class="table-responsive">
@ -7,25 +8,25 @@
<thead>
<tr>
<th>
<a href="{% url 'tarifs:home' %}?order_by=title&dir={{ dir|default:'down' }}">
<a href="{% url 'tarifs:home' %}?{% url_order_by request order_by='title' %}">
{% trans 'tariff' %}
</a>
{% if order_by == 'title' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
</th>
<th>
<a href="{% url 'tarifs:home' %}?order_by=speedIn&dir={{ dir|default:'down' }}">
<a href="{% url 'tarifs:home' %}?{% url_order_by request order_by='speedIn' %}">
{% trans 'Speed In' %}
</a>
{% if order_by == 'speedIn' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
</th>
<th>
<a href="{% url 'tarifs:home' %}?order_by=speedOut&dir={{ dir|default:'down' }}">
<a href="{% url 'tarifs:home' %}?{% url_order_by request order_by='speedOut' %}">
{% trans 'Speed Out' %}
</a>
{% if order_by == 'speedOut' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
</th>
<th>
<a href="{% url 'tarifs:home' %}?order_by=amount&dir={{ dir|default:'down' }}">
<a href="{% url 'tarifs:home' %}?{% url_order_by request order_by='amount' %}">
{% trans 'Price' %}
</a>
{% if order_by == 'amount' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}

15
tariff_app/views.py

@ -1,28 +1,21 @@
from django.contrib.auth.decorators import login_required
from django.contrib.gis.shortcuts import render_to_text
from django.urls import reverse_lazy
from django.utils.decorators import method_decorator
from django.utils.translation import ugettext as _
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib import messages
from django.core.exceptions import PermissionDenied
from django.views.generic import ListView, DeleteView
from django.conf import settings
from django.views.generic import DeleteView
from guardian.decorators import permission_required_or_403 as permission_required
from djing.global_base_views import OrderingMixin
from djing.global_base_views import OrderedFilteredList
from .models import Tariff, PeriodicPay
from djing import lib
from . import forms
class BaseServiceListView(ListView):
http_method_names = ('get',)
paginate_by = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10)
@method_decorator((login_required, lib.decorators.only_admins), name='dispatch')
class TariffsListView(BaseServiceListView, OrderingMixin):
class TariffsListView(OrderedFilteredList):
"""
Show Services(Tariffs) list
"""
@ -80,7 +73,7 @@ class TariffDeleteView(DeleteView):
@method_decorator(login_required, name='dispatch')
@method_decorator(permission_required('tariff_app.delete_tariff'), name='dispatch')
class PeriodicPaysListView(BaseServiceListView):
class PeriodicPaysListView(OrderedFilteredList):
context_object_name = 'pays'
model = PeriodicPay
template_name = 'tariff_app/periodic_pays/list.html'

Loading…
Cancel
Save