From 35a10c53368367b480aa96e27a427e67eeaa1894 Mon Sep 17 00:00:00 2001 From: Dmitry Novikov Date: Fri, 19 Jan 2018 11:53:17 +0300 Subject: [PATCH 1/5] fix bugs --- abonapp/views.py | 18 +++++++++++------- accounts_app/models.py | 2 +- devapp/views.py | 6 +++--- static/css/custom.css | 5 ++--- taskapp/templates/taskapp/tasklist.html | 2 +- 5 files changed, 18 insertions(+), 15 deletions(-) diff --git a/abonapp/views.py b/abonapp/views.py index 0e2c356..48a7455 100644 --- a/abonapp/views.py +++ b/abonapp/views.py @@ -753,18 +753,22 @@ def save_user_dev_port(request, gid, uid): if abon.device is not None: try: other_abon = models.Abon.objects.get(device=abon.device, dev_port=port) - user_url = resolve_url('abonapp:abon_home', other_abon.group.id, other_abon.id) - messages.error(request, _("%(user_name)s already pinned to this port on this device") % { - 'user_url': user_url, - 'user_name': other_abon.get_full_name() - }) - return redirect('abonapp:abon_home', gid, uid) + if other_abon != abon: + user_url = resolve_url('abonapp:abon_home', other_abon.group.id, other_abon.id) + messages.error(request, _("%(user_name)s already pinned to this port on this device") % { + 'user_url': user_url, + 'user_name': other_abon.get_full_name() + }) + return redirect('abonapp:abon_home', gid, uid) except models.Abon.DoesNotExist: pass abon.dev_port = port if abon.is_dynamic_ip != is_dynamic_ip: - abon.is_dynamic_ip = is_dynamic_ip + if is_dynamic_ip == 'on': + abon.is_dynamic_ip = True + else: + abon.is_dynamic_ip = False abon.save(update_fields=['dev_port', 'is_dynamic_ip']) else: abon.save(update_fields=['dev_port']) diff --git a/accounts_app/models.py b/accounts_app/models.py index ca53866..985f320 100644 --- a/accounts_app/models.py +++ b/accounts_app/models.py @@ -3,7 +3,7 @@ import os from django.db import models from django.contrib.auth.models import BaseUserManager, AbstractBaseUser, PermissionsMixin from django.core.validators import RegexValidator -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext_lazy as _ from django.conf import settings from photo_app.models import Photo diff --git a/devapp/views.py b/devapp/views.py index 201fbc2..17760c5 100644 --- a/devapp/views.py +++ b/devapp/views.py @@ -71,7 +71,7 @@ def devices_null_group(request): def devdel(request, device_id): try: dev = Device.objects.get(pk=device_id) - back_url = resolve_url('devapp:devs', grp=dev.user_group.pk if dev.user_group else 0) + back_url = resolve_url('devapp:devs', group_id=dev.user_group.pk if dev.user_group else 0) dev.delete() return res_success(request, back_url) except Device.DoesNotExist: @@ -162,7 +162,7 @@ def manage_ports(request, device_id): except Device.DoesNotExist: messages.error(request, _('Device does not exist')) - return redirect('devapp:view', dev.user_group.pk if dev.user_group else 0, did=device_id) + return redirect('devapp:group_list') except DeviceDBException as e: messages.error(request, e) return render(request, 'devapp/manage_ports/list.html', { @@ -273,7 +273,7 @@ def edit_single_port(request, group_id, device_id, port_id): messages.success(request, _('Port successfully saved')) else: messages.error(request, _('Form is invalid, check fields and try again')) - return redirect('devapp:manage_ports', group_id, port_id) + return redirect('devapp:manage_ports', group_id, device_id) frm = PortForm(instance=port) return render_to_text('devapp/manage_ports/modal_add_edit_port.html', { diff --git a/static/css/custom.css b/static/css/custom.css index 0fe073e..ade7ac7 100644 --- a/static/css/custom.css +++ b/static/css/custom.css @@ -242,9 +242,8 @@ button[data-toggle=offcanvas]{ * Цвет заливки графика */ .ct-series-a .ct-area { - fill: black; - opacity: 0.3; - fill-opacity: 0.3; + fill: #367cb8; + fill-opacity: 0.4; } diff --git a/taskapp/templates/taskapp/tasklist.html b/taskapp/templates/taskapp/tasklist.html index c206fb9..3723158 100644 --- a/taskapp/templates/taskapp/tasklist.html +++ b/taskapp/templates/taskapp/tasklist.html @@ -44,7 +44,7 @@ {% endif %} {{ task.get_mode_display }} - {{ task.descr }} + {{ task.descr|default:'' }} {% if task.author %} {{ task.author.username }} From 3ce2b2b25a713bd2e1d085815505f1538fa98cba Mon Sep 17 00:00:00 2001 From: Dmitry Novikov Date: Fri, 19 Jan 2018 11:53:17 +0300 Subject: [PATCH 2/5] fix bugs --- abonapp/views.py | 18 +++++++++++------- accounts_app/models.py | 2 +- agent/netflow/netflow_handler.sh | 22 ---------------------- devapp/views.py | 6 +++--- static/css/custom.css | 5 ++--- taskapp/templates/taskapp/tasklist.html | 2 +- 6 files changed, 18 insertions(+), 37 deletions(-) delete mode 100755 agent/netflow/netflow_handler.sh diff --git a/abonapp/views.py b/abonapp/views.py index 0e2c356..48a7455 100644 --- a/abonapp/views.py +++ b/abonapp/views.py @@ -753,18 +753,22 @@ def save_user_dev_port(request, gid, uid): if abon.device is not None: try: other_abon = models.Abon.objects.get(device=abon.device, dev_port=port) - user_url = resolve_url('abonapp:abon_home', other_abon.group.id, other_abon.id) - messages.error(request, _("%(user_name)s already pinned to this port on this device") % { - 'user_url': user_url, - 'user_name': other_abon.get_full_name() - }) - return redirect('abonapp:abon_home', gid, uid) + if other_abon != abon: + user_url = resolve_url('abonapp:abon_home', other_abon.group.id, other_abon.id) + messages.error(request, _("%(user_name)s already pinned to this port on this device") % { + 'user_url': user_url, + 'user_name': other_abon.get_full_name() + }) + return redirect('abonapp:abon_home', gid, uid) except models.Abon.DoesNotExist: pass abon.dev_port = port if abon.is_dynamic_ip != is_dynamic_ip: - abon.is_dynamic_ip = is_dynamic_ip + if is_dynamic_ip == 'on': + abon.is_dynamic_ip = True + else: + abon.is_dynamic_ip = False abon.save(update_fields=['dev_port', 'is_dynamic_ip']) else: abon.save(update_fields=['dev_port']) diff --git a/accounts_app/models.py b/accounts_app/models.py index ca53866..985f320 100644 --- a/accounts_app/models.py +++ b/accounts_app/models.py @@ -3,7 +3,7 @@ import os from django.db import models from django.contrib.auth.models import BaseUserManager, AbstractBaseUser, PermissionsMixin from django.core.validators import RegexValidator -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext_lazy as _ from django.conf import settings from photo_app.models import Photo diff --git a/agent/netflow/netflow_handler.sh b/agent/netflow/netflow_handler.sh deleted file mode 100755 index c5c873e..0000000 --- a/agent/netflow/netflow_handler.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash - -FNAME="$1" - -if [[ -z "$FNAME" ]]; then - echo "Нужно имя файла дампа netflow" - exit 1 -fi - -CUR_DIR=`dirname $0` - -DUMP_FILE="/tmp/djing_flow/$FNAME" -PATH=/usr/local/sbin:/usr/local/bin:/usr/bin -TMP_DUMP=/tmp/djing_flow/djing_flow_dump.tmp - -cd $CUR_DIR -mkdir -p /tmp/djing_flow -mv $DUMP_FILE $TMP_DUMP - -./djing_flow < $TMP_DUMP | /usr/bin/mysql -uUSER -h -p --password= - -rm $TMP_DUMP diff --git a/devapp/views.py b/devapp/views.py index 201fbc2..17760c5 100644 --- a/devapp/views.py +++ b/devapp/views.py @@ -71,7 +71,7 @@ def devices_null_group(request): def devdel(request, device_id): try: dev = Device.objects.get(pk=device_id) - back_url = resolve_url('devapp:devs', grp=dev.user_group.pk if dev.user_group else 0) + back_url = resolve_url('devapp:devs', group_id=dev.user_group.pk if dev.user_group else 0) dev.delete() return res_success(request, back_url) except Device.DoesNotExist: @@ -162,7 +162,7 @@ def manage_ports(request, device_id): except Device.DoesNotExist: messages.error(request, _('Device does not exist')) - return redirect('devapp:view', dev.user_group.pk if dev.user_group else 0, did=device_id) + return redirect('devapp:group_list') except DeviceDBException as e: messages.error(request, e) return render(request, 'devapp/manage_ports/list.html', { @@ -273,7 +273,7 @@ def edit_single_port(request, group_id, device_id, port_id): messages.success(request, _('Port successfully saved')) else: messages.error(request, _('Form is invalid, check fields and try again')) - return redirect('devapp:manage_ports', group_id, port_id) + return redirect('devapp:manage_ports', group_id, device_id) frm = PortForm(instance=port) return render_to_text('devapp/manage_ports/modal_add_edit_port.html', { diff --git a/static/css/custom.css b/static/css/custom.css index 0fe073e..ade7ac7 100644 --- a/static/css/custom.css +++ b/static/css/custom.css @@ -242,9 +242,8 @@ button[data-toggle=offcanvas]{ * Цвет заливки графика */ .ct-series-a .ct-area { - fill: black; - opacity: 0.3; - fill-opacity: 0.3; + fill: #367cb8; + fill-opacity: 0.4; } diff --git a/taskapp/templates/taskapp/tasklist.html b/taskapp/templates/taskapp/tasklist.html index c206fb9..3723158 100644 --- a/taskapp/templates/taskapp/tasklist.html +++ b/taskapp/templates/taskapp/tasklist.html @@ -44,7 +44,7 @@ {% endif %} {{ task.get_mode_display }} - {{ task.descr }} + {{ task.descr|default:'' }} {% if task.author %} {{ task.author.username }} From 21b1da970eb667607c12c9c67a87a6cd7ebcba32 Mon Sep 17 00:00:00 2001 From: nerosketch Date: Sun, 21 Jan 2018 21:53:55 +0300 Subject: [PATCH 3/5] Did functionality to export subscribers to csv --- abonapp/forms.py | 46 +++++++++++++++------ abonapp/locale/ru/LC_MESSAGES/django.po | 23 ++++++++++- abonapp/models.py | 41 +++++++----------- abonapp/templates/abonapp/modal_export.html | 14 +++++++ abonapp/templates/abonapp/peoples.html | 27 ++++++------ abonapp/urls_abon.py | 1 + abonapp/views.py | 33 +++++++++++++++ accounts_app/models.py | 1 + 8 files changed, 133 insertions(+), 53 deletions(-) create mode 100644 abonapp/templates/abonapp/modal_export.html diff --git a/abonapp/forms.py b/abonapp/forms.py index 36fa6b5..1e25604 100644 --- a/abonapp/forms.py +++ b/abonapp/forms.py @@ -8,7 +8,6 @@ from string import digits, ascii_lowercase from . import models from django.conf import settings - TELEPHONE_REGEXP = getattr(settings, 'TELEPHONE_REGEXP', r'^\+[7,8,9,3]\d{10,11}$') @@ -16,7 +15,7 @@ def generate_random_username(length=6, chars=digits, split=2, delimiter=''): username = ''.join([choice(chars) for i in range(length)]) if split: - username = delimiter.join([username[start:start+split] for start in range(0, len(username), split)]) + username = delimiter.join([username[start:start + split] for start in range(0, len(username), split)]) try: models.Abon.objects.get(username=username) @@ -26,7 +25,7 @@ def generate_random_username(length=6, chars=digits, split=2, delimiter=''): def generate_random_password(): - return generate_random_username(length=8, chars=digits+ascii_lowercase) + return generate_random_username(length=8, chars=digits + ascii_lowercase) class AbonForm(forms.ModelForm): @@ -41,14 +40,16 @@ class AbonForm(forms.ModelForm): if abon_group_queryset is not None: self.fields['street'].queryset = abon_group_queryset - username = forms.CharField(max_length=127, required=False, initial=generate_random_username, widget=forms.TextInput(attrs={ - 'placeholder': _('login'), - 'class': "form-control", - 'required': '' - })) + username = forms.CharField(max_length=127, required=False, initial=generate_random_username, + widget=forms.TextInput(attrs={ + 'placeholder': _('login'), + 'class': "form-control", + 'required': '' + })) password = forms.CharField(max_length=64, initial=generate_random_password, - widget=forms.TextInput(attrs={'class': 'form-control', 'type': 'password', 'autocomplete': 'new-password'})) + widget=forms.TextInput( + attrs={'class': 'form-control', 'type': 'password', 'autocomplete': 'new-password'})) class Meta: model = models.Abon @@ -116,7 +117,6 @@ class PassportForm(forms.ModelForm): class ExtraFieldForm(forms.ModelForm): - class Meta: model = models.ExtraFieldsModel fields = '__all__' @@ -132,7 +132,7 @@ class AbonStreetForm(forms.ModelForm): model = models.AbonStreet fields = '__all__' widgets = { - 'name': forms.TextInput(attrs={'class': 'form-control', 'required':'', 'autofocus':''}), + 'name': forms.TextInput(attrs={'class': 'form-control', 'required': '', 'autofocus': ''}), 'group': forms.Select(attrs={'class': 'form-control'}) } @@ -148,5 +148,27 @@ class AdditionalTelephoneForm(forms.ModelForm): 'required': '', 'class': 'form-control' }), - 'owner_name': forms.TextInput(attrs={'class': 'form-control', 'required':''}) + 'owner_name': forms.TextInput(attrs={'class': 'form-control', 'required': ''}) } + + +class ExportUsersForm(forms.Form): + FIELDS_CHOICES = ( + ('username', _('profile username')), + ('fio', _('fio')), + ('ip_address', _('Ip Address')), + ('description', _('Comment')), + ('street', _('Street')), + ('house', _('House')), + ('birth_day', _('birth day')), + ('is_active', _('Is active')), + ('telephone', _('Telephone')), + ('current_tariff', _('Service title')), + ('ballance', _('Ballance')), + ('device', _('Device')), + ('dev_port', _('Device port')), + ('is_dynamic_ip', _('Is dynamic ip')) + ) + fields = forms.MultipleChoiceField(choices=FIELDS_CHOICES, + widget=forms.CheckboxSelectMultiple(attrs={"checked": ""}), + label=_('Fields')) diff --git a/abonapp/locale/ru/LC_MESSAGES/django.po b/abonapp/locale/ru/LC_MESSAGES/django.po index 27e0b00..56b9a2b 100644 --- a/abonapp/locale/ru/LC_MESSAGES/django.po +++ b/abonapp/locale/ru/LC_MESSAGES/django.po @@ -421,7 +421,7 @@ msgstr "Добавить муфту" #: templates/abonapp/editAbon.html:171 msgid "Device port" -msgstr "Порт устройства" +msgstr "Порт устройства" #: templates/abonapp/editAbon.html:190 msgid "Is dynamic network settings" @@ -995,3 +995,24 @@ msgstr "Показать график по дате" #, python-format msgid "%(user_name)s already pinned to this port on this device" msgstr "%(user_name)s уже привязан к этому порту на этом устройстве" + +msgid "Export" +msgstr "Экспорт" + +msgid "Export users" +msgstr "Экспорт абонентов" + +msgid "Fields" +msgstr "Поля" + +msgid "Select the fields" +msgstr "Выберите поля" + +msgid "Service title" +msgstr "Название тарифа" + +msgid "Is dynamic ip" +msgstr "Динамический ip" + +msgid "Unexpected format %(export_format)s" +msgstr "Нежиданный формат %(export_format)s" diff --git a/abonapp/models.py b/abonapp/models.py index e7d0e73..3095541 100644 --- a/abonapp/models.py +++ b/abonapp/models.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from datetime import datetime from django.core.exceptions import ValidationError from django.core.validators import RegexValidator @@ -55,23 +54,21 @@ class AbonLog(models.Model): class AbonTariff(models.Model): tariff = models.ForeignKey(Tariff, models.CASCADE, related_name='linkto_tariff') - # время начала действия услуги time_start = models.DateTimeField(null=True, blank=True, default=None) - # время завершения услуги deadline = models.DateTimeField(null=True, blank=True, default=None) def calc_amount_service(self): amount = self.tariff.amount return round(amount, 2) - # Используется-ли услуга сейчас, если время старта есть то он активирован + # is used service now, if time start is present than it activated def is_started(self): return False if self.time_start is None else True def __str__(self): - return "%d: %s" % ( - self.pk or 0, + return "%s: %s" % ( + self.deadline, self.tariff.title ) @@ -139,7 +136,6 @@ class ExtraFieldsModel(models.Model): db_table = 'abon_extra_fields' - class AbonManager(MyUserManager): def get_queryset(self): @@ -159,7 +155,6 @@ class Abon(UserProfile): dev_port = models.ForeignKey('devapp.Port', null=True, blank=True, on_delete=models.SET_NULL) is_dynamic_ip = models.BooleanField(default=False) - # возвращает связь с текущим тарифом для абонента def active_tariff(self): return self.current_tariff @@ -177,12 +172,10 @@ class Abon(UserProfile): verbose_name = _('Abon') verbose_name_plural = _('Abons') - # Платим за что-то def make_pay(self, curuser, how_match_to_pay=0.0): self.ballance -= how_match_to_pay self.save(update_fields=['ballance']) - # Пополняем счёт def add_ballance(self, current_user, amount, comment): AbonLog.objects.create( abon=self, @@ -192,7 +185,6 @@ class Abon(UserProfile): ) self.ballance += amount - # покупаем тариф def pick_tariff(self, tariff, author, comment=None, deadline=None): if not isinstance(tariff, Tariff): raise TypeError @@ -204,13 +196,13 @@ class Abon(UserProfile): if self.current_tariff is not None: if self.current_tariff.tariff == tariff: - # Эта услуга уже подключена + # if service already connected raise LogicError(_('That service already activated')) else: - # Не надо молча заменять услугу если какая-то уже есть + # if service is present then speak about it raise LogicError(_('Service already activated')) - # если не хватает денег + # if not enough money if self.ballance < amount: raise LogicError(_('not enough money')) @@ -218,30 +210,30 @@ class Abon(UserProfile): new_abtar.save() self.current_tariff = new_abtar - # снимаем деньги за услугу + # charge for the service self.ballance -= amount self.save() - # Запись об этом в лог + # make log about it AbonLog.objects.create( abon=self, amount=-tariff.amount, author=author, comment=comment or _('Buy service default log') ) - # Производим расчёт услуги абонента, т.е. завершаем если пришло время + # Destroy the service if the time has come def bill_service(self, author): abon_tariff = self.active_tariff() if abon_tariff is None: return nw = timezone.now() - # если услуга просрочена + # if service is overdue if nw > abon_tariff.deadline: print("Service %s for user %s is overdued, end service" % (abon_tariff.tariff, self)) abon_tariff.delete() - # есть-ли доступ у абонента к услуге, смотрим в tariff_app.custom_tariffs..manage_access() + # is subscriber have access to service, view in tariff_app.custom_tariffs..manage_access() def is_access(self): abon_tariff = self.active_tariff() if abon_tariff is None: @@ -250,7 +242,7 @@ class Abon(UserProfile): ct = trf.get_calc_type()(abon_tariff) return ct.manage_access(self) - # создаём абонента из структуры агента + # make subscriber from agent structure def build_agent_struct(self): if self.ip_address: user_ip = ip2int(self.ip_address) @@ -265,7 +257,7 @@ class Abon(UserProfile): return AbonStruct(self.pk, user_ip, agent_trf, bool(self.is_active)) def save(self, *args, **kwargs): - # проверяем не-ли у кого такого-же ip + # check if ip address already busy if self.ip_address is not None and Abon.objects.filter(ip_address=self.ip_address).exclude(pk=self.pk).count() > 0: self.is_bad_ip = True raise LogicError(_('Ip address already exist')) @@ -319,7 +311,8 @@ class InvoiceForPayment(models.Model): class AllTimePayLogManager(models.Manager): - def by_days(self): + @staticmethod + def by_days(): cur = connection.cursor() cur.execute(r'SELECT SUM(summ) as alsum, DATE_FORMAT(date_add, "%Y-%m-%d") AS pay_date FROM all_time_pay_log ' r'GROUP BY DATE_FORMAT(date_add, "%Y-%m-%d")') @@ -408,10 +401,8 @@ def abon_post_save(sender, **kwargs): try: tm = Transmitter() if created: - # создаём абонента tm.add_user(agent_abon, ip_timeout=timeout) else: - # обновляем абонента на NAS tm.update_user(agent_abon, ip_timeout=timeout) except (NasFailedResult, NasNetworkError, ConnectionResetError) as e: @@ -426,9 +417,7 @@ def abon_del_signal(sender, **kwargs): ab = abon.build_agent_struct() if ab is None: return True - # подключаемся к NAS'у tm = Transmitter() - # нашли абонента, и удаляем его на NAS tm.remove_user(ab) except (NasFailedResult, NasNetworkError): return True diff --git a/abonapp/templates/abonapp/modal_export.html b/abonapp/templates/abonapp/modal_export.html new file mode 100644 index 0000000..1444209 --- /dev/null +++ b/abonapp/templates/abonapp/modal_export.html @@ -0,0 +1,14 @@ +{% load i18n %} +{% load bootstrap3 %} +
{% csrf_token %} + + +
diff --git a/abonapp/templates/abonapp/peoples.html b/abonapp/templates/abonapp/peoples.html index 7ccc764..7b49cbf 100644 --- a/abonapp/templates/abonapp/peoples.html +++ b/abonapp/templates/abonapp/peoples.html @@ -3,14 +3,13 @@ {% load dpagination %} {% block main %} + - - - {% include 'message_block.html' %} +{% include 'message_block.html' %}

{% trans 'The people in the selected group' %}

@@ -21,32 +20,32 @@ # - + {% trans 'Sub' %} {% if order_by == 'username' %}{% endif %} {% trans 'Last traffic' %} - + {% trans 'Ip address' %} {% if order_by == 'ip_address' %}{% endif %} - + {% trans 'fio' %} {% if order_by == 'fio' %}{% endif %} - + {% trans 'Street' %} {% if order_by == 'street' %}{% endif %} - + {% trans 'Apartment' %} {% if order_by == 'house' %}{% endif %} @@ -54,7 +53,7 @@ {% trans 'Telephone' %} {% trans 'Service' %} - + {% trans 'Ballance' %} {% if order_by == 'ballance' %}{% endif %} @@ -165,6 +164,6 @@
- {% include 'toolbar_page.html' with pag=peoples %} +{% include 'toolbar_page.html' with pag=peoples %} {% endblock %} diff --git a/abonapp/urls_abon.py b/abonapp/urls_abon.py index 1bbf288..440de85 100644 --- a/abonapp/urls_abon.py +++ b/abonapp/urls_abon.py @@ -7,6 +7,7 @@ urlpatterns = [ url(r'^addabon$', views.addabon, name='add_abon'), url(r'^services$', views.chgroup_tariff, name='ch_group_tariff'), url(r'^phonebook$', views.phonebook, name='phonebook'), + url(r'^export$', views.abon_export, name='abon_export'), url(r'^street/add$', views.street_add, name='street_add'), url(r'^street/edit', views.street_edit, name='street_edit'), url(r'^street/(?P\d+)/delete$', views.street_del, name='street_del'), diff --git a/abonapp/views.py b/abonapp/views.py index 48a7455..f21e01a 100644 --- a/abonapp/views.py +++ b/abonapp/views.py @@ -907,6 +907,39 @@ def phonebook(request, gid): }, request=request) +@login_required +@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid')) +def abon_export(request, gid): + res_format = request.GET.get('f') + + if request.method == 'POST': + frm = forms.ExportUsersForm(request.POST) + if frm.is_valid(): + cleaned_data = frm.clean() + fields = cleaned_data.get('fields') + subscribers = models.Abon.objects.filter(group__id=gid).only(*fields).values_list(*fields) + if res_format == 'csv': + import csv + response = HttpResponse(content_type='text/csv') + response['Content-Disposition'] = 'attachment; filename="users.csv"' + writer = csv.writer(response, quoting=csv.QUOTE_NONNUMERIC) + for row in subscribers: + writer.writerow(row) + return response + else: + messages.info(request, _('Unexpected format %(export_format)s') % {'export_format': res_format}) + return redirect('abonapp:group_list') + else: + messages.error(request, _('fix form errors')) + return redirect('abonapp:group_list') + else: + frm = forms.ExportUsersForm() + return render_to_text('abonapp/modal_export.html', { + 'gid': gid, + 'form': frm + }, request=request) + + @login_required @permission_required('abonapp.change_abon') @permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid')) diff --git a/accounts_app/models.py b/accounts_app/models.py index 985f320..360a914 100644 --- a/accounts_app/models.py +++ b/accounts_app/models.py @@ -108,3 +108,4 @@ class UserProfile(AbstractBaseUser, PermissionsMixin): ) verbose_name = _('Staff account profile') verbose_name_plural = _('Staff account profiles') + ordering = ['fio'] From 387ec969cc5d7a038bf4379b3bcc07f52b174338 Mon Sep 17 00:00:00 2001 From: Dmitry Novikov Date: Sun, 21 Jan 2018 21:54:48 +0300 Subject: [PATCH 4/5] fix --- abonapp/templates/abonapp/peoples.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/abonapp/templates/abonapp/peoples.html b/abonapp/templates/abonapp/peoples.html index 7ccc764..851c1f9 100644 --- a/abonapp/templates/abonapp/peoples.html +++ b/abonapp/templates/abonapp/peoples.html @@ -21,32 +21,32 @@ # - + {% trans 'Sub' %} {% if order_by == 'username' %}{% endif %} {% trans 'Last traffic' %} - + {% trans 'Ip address' %} {% if order_by == 'ip_address' %}{% endif %} - + {% trans 'fio' %} {% if order_by == 'fio' %}{% endif %} - + {% trans 'Street' %} {% if order_by == 'street' %}{% endif %} - + {% trans 'Apartment' %} {% if order_by == 'house' %}{% endif %} @@ -54,7 +54,7 @@ {% trans 'Telephone' %} {% trans 'Service' %} - + {% trans 'Ballance' %} {% if order_by == 'ballance' %}{% endif %} From 16ba530adc780ca8f01f6d7fd369a9b1ff489807 Mon Sep 17 00:00:00 2001 From: nerosketch Date: Sun, 21 Jan 2018 22:40:30 +0300 Subject: [PATCH 5/5] fix --- abonapp/forms.py | 8 ++++---- abonapp/templates/abonapp/peoples.html | 3 +++ abonapp/views.py | 2 ++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/abonapp/forms.py b/abonapp/forms.py index 1e25604..7618da6 100644 --- a/abonapp/forms.py +++ b/abonapp/forms.py @@ -158,15 +158,15 @@ class ExportUsersForm(forms.Form): ('fio', _('fio')), ('ip_address', _('Ip Address')), ('description', _('Comment')), - ('street', _('Street')), + ('street__name', _('Street')), ('house', _('House')), ('birth_day', _('birth day')), ('is_active', _('Is active')), ('telephone', _('Telephone')), - ('current_tariff', _('Service title')), + ('current_tariff__tariff__title', _('Service title')), ('ballance', _('Ballance')), - ('device', _('Device')), - ('dev_port', _('Device port')), + ('device__comment', _('Device')), + ('dev_port__descr', _('Device port')), ('is_dynamic_ip', _('Is dynamic ip')) ) fields = forms.MultipleChoiceField(choices=FIELDS_CHOICES, diff --git a/abonapp/templates/abonapp/peoples.html b/abonapp/templates/abonapp/peoples.html index 7b49cbf..f69d853 100644 --- a/abonapp/templates/abonapp/peoples.html +++ b/abonapp/templates/abonapp/peoples.html @@ -136,6 +136,9 @@ {% trans 'Phonebook' %} + + {% trans 'Export users' %} + diff --git a/abonapp/views.py b/abonapp/views.py index f21e01a..99980a5 100644 --- a/abonapp/views.py +++ b/abonapp/views.py @@ -923,6 +923,8 @@ def abon_export(request, gid): response = HttpResponse(content_type='text/csv') response['Content-Disposition'] = 'attachment; filename="users.csv"' writer = csv.writer(response, quoting=csv.QUOTE_NONNUMERIC) + display_values = [f[1] for f in frm.fields['fields'].choices if f[0] in fields] + writer.writerow(display_values) for row in subscribers: writer.writerow(row) return response