Browse Source

На ветке global_group_update

Изменения, которые будут включены в коммит:
	изменено:      abonapp/admin.py
	изменено:      abonapp/forms.py
	изменено:      abonapp/locale/ru/LC_MESSAGES/django.po
	переименовано: abonapp/migrations/0001_squashed_0022_auto_20170816_1109.py -> abonapp/migrations/0001_initial.py
	удалено:       abonapp/migrations/0002_auto_20170905_1248.py
	удалено:       abonapp/migrations/0003_auto_20170927_1838.py
	удалено:       abonapp/migrations/0004_auto_20180122_1732.py
	удалено:       abonapp/migrations/0005_auto_20180123_1353.py
	удалено:       abonapp/migrations/0006_abon_markers.py
	изменено:      abonapp/models.py
	изменено:      abonapp/templates/abonapp/addAbon.html
	удалено:       abonapp/templates/abonapp/addGroup.html
	изменено:      abonapp/templates/abonapp/addInvoice.html
	изменено:      abonapp/templates/abonapp/buy_tariff.html
	изменено:      abonapp/templates/abonapp/charts.html
	изменено:      abonapp/templates/abonapp/editAbon.html
	изменено:      abonapp/templates/abonapp/ext.htm
	изменено:      abonapp/templates/abonapp/group_list.html
	изменено:      abonapp/templates/abonapp/group_tariffs.html
	изменено:      abonapp/templates/abonapp/invoiceForPayment.html
	изменено:      abonapp/templates/abonapp/modal_abonamount.html
	изменено:      abonapp/templates/abonapp/passport_view.html
	изменено:      abonapp/templates/abonapp/payHistory.html
	изменено:      abonapp/templates/abonapp/peoples.html
	изменено:      abonapp/templates/abonapp/service.html
	изменено:      abonapp/urls.py
	изменено:      abonapp/views.py
	изменено:      accounts_app/migrations/0001_initial.py
	удалено:       accounts_app/migrations/0002_userprofile_email.py
	удалено:       accounts_app/migrations/0003_auto_20161206_2135.py
	удалено:       accounts_app/migrations/0004_auto_20170128_1316.py
	удалено:       accounts_app/migrations/0005_auto_20170222_2224.py
	удалено:       accounts_app/migrations/0006_auto_20170416_1029.py
	удалено:       accounts_app/migrations/0007_auto_20170816_1109.py
	удалено:       accounts_app/migrations/0008_auto_20170927_1838.py
	изменено:      accounts_app/models.py
	изменено:      accounts_app/templates/accounts/create_acc.html
	изменено:      accounts_app/templates/accounts/profile_chgroup.html
	изменено:      accounts_app/templates/accounts/set_abon_groups_permission.html
	изменено:      accounts_app/views.py
	изменено:      agent/commands/dhcp.py
	изменено:      chatbot/migrations/0001_initial.py
	удалено:       chatbot/migrations/0002_auto_20171214_1517.py
	изменено:      clientsideapp/views.py
	изменено:      devapp/forms.py
	изменено:      devapp/locale/ru/LC_MESSAGES/django.po
	новый файл:    devapp/migrations/0001_initial.py
	удалено:       devapp/migrations/0001_squashed_0007_auto_20170816_1109.py
	удалено:       devapp/migrations/0002_device_user_group.py
	удалено:       devapp/migrations/0003_auto_20170927_1838.py
	удалено:       devapp/migrations/0004_auto_20171103_0006.py
	удалено:       devapp/migrations/0005_device_snmp_item_num.py
	удалено:       devapp/migrations/0006_auto_20180129_1625.py
	изменено:      devapp/models.py
	изменено:      devapp/templates/devapp/add_dev.html
	изменено:      devapp/templates/devapp/custom_dev_page/olt.html
	изменено:      devapp/templates/devapp/custom_dev_page/onu.html
	изменено:      devapp/templates/devapp/custom_dev_page/ports.html
	изменено:      devapp/templates/devapp/dev.html
	изменено:      devapp/templates/devapp/devices.html
	изменено:      devapp/templates/devapp/devices_null_group.html
	изменено:      devapp/templates/devapp/ext.htm
	изменено:      devapp/templates/devapp/fix_dev_group.html
	изменено:      devapp/templates/devapp/group_list.html
	изменено:      devapp/templates/devapp/manage_ports/add_ports.html
	изменено:      devapp/templates/devapp/manage_ports/fix_abon_device.html
	изменено:      devapp/templates/devapp/manage_ports/list.html
	изменено:      devapp/views.py
	изменено:      dialing_app/migrations/0001_initial.py
	удалено:       dialing_app/migrations/0002_auto_20171229_1353.py
	удалено:       dialing_app/migrations/0003_smsout.py
	изменено:      dialing_app/views.py
	изменено:      djing/settings.py
	изменено:      djing/urls.py
	новый файл:    group_app/__init__.py
	новый файл:    group_app/admin.py
	новый файл:    group_app/apps.py
	новый файл:    group_app/forms.py
	новый файл:    group_app/locale/ru/LC_MESSAGES/django.po
	новый файл:    group_app/migrations/0001_initial.py
	новый файл:    group_app/migrations/__init__.py
	новый файл:    group_app/models.py
	новый файл:    group_app/templates/group_app/add_group.html
	новый файл:    group_app/templates/group_app/edit_group.html
	новый файл:    group_app/templates/group_app/ext.html
	новый файл:    group_app/templates/group_app/group_list.html
	новый файл:    group_app/tests.py
	новый файл:    group_app/urls.py
	новый файл:    group_app/views.py
	изменено:      locale/ru/LC_MESSAGES/django.po
	изменено:      mapapp/migrations/0001_initial.py
	удалено:       mapapp/migrations/0002_auto_20171103_0006.py
	изменено:      mapapp/templates/maps/dot.html
	изменено:      mapapp/templates/maps/map_tooltip.html
	изменено:      mapapp/templates/maps/ya_index.html
	изменено:      mapapp/views.py
	изменено:      msg_app/migrations/0001_initial.py
	изменено:      photo_app/migrations/0001_initial.py
	переименовано: statistics/migrations/0002_statcache.py -> statistics/migrations/0001_initial.py
	изменено:      tariff_app/migrations/0001_initial.py
	удалено:       tariff_app/migrations/0002_tariff_descr.py
	удалено:       tariff_app/migrations/0003_tariff_is_admin.py
	удалено:       tariff_app/migrations/0004_auto_20170416_0350.py
	удалено:       tariff_app/migrations/0005_auto_20170502_2229.py
	удалено:       tariff_app/migrations/0006_auto_20180122_1732.py
	удалено:       tariff_app/migrations/0007_auto_20180215_1423.py
	изменено:      tariff_app/models.py
	изменено:      tariff_app/templates/tariff_app/tarifs.html
	изменено:      taskapp/forms.py
	изменено:      taskapp/migrations/0001_initial.py
	удалено:       taskapp/migrations/0001_squashed_0015_auto_20170816_1109.py
	удалено:       taskapp/migrations/0002_auto_20161006_0027.py
	удалено:       taskapp/migrations/0002_auto_20180219_1255.py
	удалено:       taskapp/migrations/0003_auto_20161130_1815.py
	удалено:       taskapp/migrations/0004_auto_20161202_1230.py
	удалено:       taskapp/migrations/0005_auto_20161206_0013.py
	удалено:       taskapp/migrations/0006_auto_20161206_2135.py
	удалено:       taskapp/migrations/0007_auto_20161206_2303.py
	удалено:       taskapp/migrations/0008_auto_20161213_1932.py
	удалено:       taskapp/migrations/0009_auto_20161216_2214.py
	удалено:       taskapp/migrations/0010_auto.py
	удалено:       taskapp/migrations/0011_auto_20170116_0126.py
	удалено:       taskapp/migrations/0012_auto_20170407_0124.py
	удалено:       taskapp/migrations/0013_auto_20170413_1944.py
	удалено:       taskapp/migrations/0014_auto_20170416_1029.py
	удалено:       taskapp/migrations/0015_auto_20170816_1109.py
	изменено:      templates/base.html
devel
Dmitry 8 years ago
parent
commit
8396561bb8
  1. 1
      abonapp/admin.py
  2. 19
      abonapp/forms.py
  3. 17
      abonapp/locale/ru/LC_MESSAGES/django.po
  4. 308
      abonapp/migrations/0001_initial.py
  5. 52
      abonapp/migrations/0002_auto_20170905_1248.py
  6. 43
      abonapp/migrations/0003_auto_20170927_1838.py
  7. 130
      abonapp/migrations/0004_auto_20180122_1732.py
  8. 20
      abonapp/migrations/0005_auto_20180123_1353.py
  9. 23
      abonapp/migrations/0006_abon_markers.py
  10. 27
      abonapp/models.py
  11. 4
      abonapp/templates/abonapp/addAbon.html
  12. 39
      abonapp/templates/abonapp/addGroup.html
  13. 8
      abonapp/templates/abonapp/addInvoice.html
  14. 10
      abonapp/templates/abonapp/buy_tariff.html
  15. 2
      abonapp/templates/abonapp/charts.html
  16. 24
      abonapp/templates/abonapp/editAbon.html
  17. 16
      abonapp/templates/abonapp/ext.htm
  18. 12
      abonapp/templates/abonapp/group_list.html
  19. 5
      abonapp/templates/abonapp/group_tariffs.html
  20. 6
      abonapp/templates/abonapp/invoiceForPayment.html
  21. 3
      abonapp/templates/abonapp/modal_abonamount.html
  22. 2
      abonapp/templates/abonapp/passport_view.html
  23. 4
      abonapp/templates/abonapp/payHistory.html
  24. 45
      abonapp/templates/abonapp/peoples.html
  25. 14
      abonapp/templates/abonapp/service.html
  26. 2
      abonapp/urls.py
  27. 182
      abonapp/views.py
  28. 63
      accounts_app/migrations/0001_initial.py
  29. 20
      accounts_app/migrations/0002_userprofile_email.py
  30. 25
      accounts_app/migrations/0003_auto_20161206_2135.py
  31. 18
      accounts_app/migrations/0004_auto_20170128_1316.py
  32. 21
      accounts_app/migrations/0005_auto_20170222_2224.py
  33. 21
      accounts_app/migrations/0006_auto_20170416_1029.py
  34. 21
      accounts_app/migrations/0007_auto_20170816_1109.py
  35. 19
      accounts_app/migrations/0008_auto_20170927_1838.py
  36. 28
      accounts_app/models.py
  37. 1
      accounts_app/templates/accounts/create_acc.html
  38. 3
      accounts_app/templates/accounts/profile_chgroup.html
  39. 10
      accounts_app/templates/accounts/set_abon_groups_permission.html
  40. 26
      accounts_app/views.py
  41. 14
      agent/commands/dhcp.py
  42. 32
      chatbot/migrations/0001_initial.py
  43. 59
      chatbot/migrations/0002_auto_20171214_1517.py
  44. 4
      clientsideapp/views.py
  45. 5
      devapp/forms.py
  46. 4
      devapp/locale/ru/LC_MESSAGES/django.po
  47. 62
      devapp/migrations/0001_initial.py
  48. 90
      devapp/migrations/0001_squashed_0007_auto_20170816_1109.py
  49. 22
      devapp/migrations/0002_device_user_group.py
  50. 23
      devapp/migrations/0003_auto_20170927_1838.py
  51. 72
      devapp/migrations/0004_auto_20171103_0006.py
  52. 20
      devapp/migrations/0005_device_snmp_item_num.py
  53. 34
      devapp/migrations/0006_auto_20180129_1625.py
  54. 4
      devapp/models.py
  55. 2
      devapp/templates/devapp/add_dev.html
  56. 2
      devapp/templates/devapp/custom_dev_page/olt.html
  57. 2
      devapp/templates/devapp/custom_dev_page/onu.html
  58. 4
      devapp/templates/devapp/custom_dev_page/ports.html
  59. 2
      devapp/templates/devapp/dev.html
  60. 8
      devapp/templates/devapp/devices.html
  61. 6
      devapp/templates/devapp/devices_null_group.html
  62. 10
      devapp/templates/devapp/ext.htm
  63. 6
      devapp/templates/devapp/fix_dev_group.html
  64. 19
      devapp/templates/devapp/group_list.html
  65. 8
      devapp/templates/devapp/manage_ports/add_ports.html
  66. 4
      devapp/templates/devapp/manage_ports/fix_abon_device.html
  67. 8
      devapp/templates/devapp/manage_ports/list.html
  68. 81
      devapp/views.py
  69. 37
      dialing_app/migrations/0001_initial.py
  70. 35
      dialing_app/migrations/0002_auto_20171229_1353.py
  71. 31
      dialing_app/migrations/0003_smsout.py
  72. 10
      dialing_app/views.py
  73. 2
      djing/settings.py
  74. 1
      djing/urls.py
  75. 0
      group_app/__init__.py
  76. 4
      group_app/admin.py
  77. 5
      group_app/apps.py
  78. 8
      group_app/forms.py
  79. 69
      group_app/locale/ru/LC_MESSAGES/django.po
  80. 30
      group_app/migrations/0001_initial.py
  81. 0
      group_app/migrations/__init__.py
  82. 23
      group_app/models.py
  83. 20
      group_app/templates/group_app/add_group.html
  84. 20
      group_app/templates/group_app/edit_group.html
  85. 23
      group_app/templates/group_app/ext.html
  86. 59
      group_app/templates/group_app/group_list.html
  87. 3
      group_app/tests.py
  88. 10
      group_app/urls.py
  89. 52
      group_app/views.py
  90. 66
      locale/ru/LC_MESSAGES/django.po
  91. 16
      mapapp/migrations/0001_initial.py
  92. 45
      mapapp/migrations/0002_auto_20171103_0006.py
  93. 10
      mapapp/templates/maps/dot.html
  94. 2
      mapapp/templates/maps/map_tooltip.html
  95. 2
      mapapp/templates/maps/ya_index.html
  96. 17
      mapapp/views.py
  97. 2
      msg_app/migrations/0001_initial.py
  98. 4
      photo_app/migrations/0001_initial.py
  99. 18
      statistics/migrations/0001_initial.py
  100. 34
      statistics/migrations/0002_statcache.py

1
abonapp/admin.py

@ -3,7 +3,6 @@ from django.contrib import admin
from . import models
admin.site.register(models.AbonGroup)
admin.site.register(models.Abon)
admin.site.register(models.InvoiceForPayment)
admin.site.register(models.AbonLog)

19
abonapp/forms.py

@ -12,7 +12,7 @@ from django.conf import settings
TELEPHONE_REGEXP = getattr(settings, 'TELEPHONE_REGEXP', r'^\+[7,8,9,3]\d{10,11}$')
def generate_random_username(length=6, chars=digits, split=2, delimiter=''):
def generate_random_chars(length=6, chars=digits, split=2, delimiter=''):
username = ''.join([choice(chars) for i in range(length)])
if split:
@ -25,8 +25,13 @@ def generate_random_username(length=6, chars=digits, split=2, delimiter=''):
return username
def generate_random_username():
username = generate_random_chars(length=6, chars=digits)
return str(int(username))
def generate_random_password():
return generate_random_username(length=8, chars=digits + ascii_lowercase)
return generate_random_chars(length=8, chars=digits + ascii_lowercase)
class AbonForm(forms.ModelForm):
@ -92,16 +97,6 @@ class AbonForm(forms.ModelForm):
return acc
class AbonGroupForm(forms.ModelForm):
class Meta:
model = models.AbonGroup
fields = '__all__'
widgets = {
'title': forms.TextInput(attrs={'class': 'form-control'}),
'profiles': forms.TextInput(attrs={'class': 'form-control'})
}
class PassportForm(forms.ModelForm):
class Meta:
model = models.PassportInfo

17
abonapp/locale/ru/LC_MESSAGES/django.po

@ -96,10 +96,6 @@ msgstr "Динамический ip"
msgid "Fields"
msgstr "Поля"
#: models.py:31
msgid "Can view subscriber group"
msgstr "Может просматривать группу абонентов"
#: models.py:33
msgid "Abon group"
msgstr "Группа абонентов"
@ -894,19 +890,11 @@ msgstr "Просмотр абонента"
msgid "yes,no"
msgstr "Да,Нет"
#: views.py:94
msgid "create group success msg"
msgstr "Группа успешно создана"
#: views.py:97 views.py:161 views.py:308 views.py:423 views.py:500 views.py:642
#: views.py:812 views.py:884 views.py:953 views.py:1059
msgid "fix form errors"
msgstr "Некоторые поля заполнены не правильно, проверте ещё раз"
#: views.py:128
msgid "delete group success msg"
msgstr "Группа успешно удалена"
#: views.py:158
msgid "create abon success msg"
msgstr "Абонент успешно создан"
@ -1128,7 +1116,7 @@ msgid "User flags has changed successfully"
msgstr "Флаги абонента изменены успешно"
msgid "Services"
msgstr "Услуги"
msgstr "Тарифы"
msgid "Payments"
msgstr "Финансы"
@ -1144,3 +1132,6 @@ msgstr "Инфо."
msgid "Dialing"
msgstr "Звонки"
msgid "Subscribers"
msgstr "Абоненты"

308
abonapp/migrations/0001_squashed_0022_auto_20170816_1109.py → abonapp/migrations/0001_initial.py

@ -1,7 +1,8 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-09-04 16:15
# Generated by Django 1.11 on 2018-02-26 00:20
from __future__ import unicode_literals
import bitfield.models
from django.conf import settings
import django.core.validators
from django.db import migrations, models
@ -15,8 +16,8 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
('devapp', '0001_squashed_0007_auto_20170816_1109'),
('tariff_app', '0002_tariff_descr'),
('devapp', '0001_initial'),
('group_app', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('accounts_app', '0001_initial'),
('tariff_app', '0001_initial'),
@ -26,128 +27,82 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='Abon',
fields=[
('userprofile_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to=settings.AUTH_USER_MODEL)),
('ballance', models.FloatField(default=0.0, validators=[django.core.validators.DecimalValidator])),
('address', models.CharField(max_length=256)),
('baseaccount_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='accounts_app.BaseAccount')),
('ballance', models.FloatField(default=0.0)),
('ip_address', mydefs.MyGenericIPAddressField(blank=True, max_length=8, null=True, protocol='ipv4')),
('description', models.TextField(blank=True, null=True, verbose_name='Comment')),
('house', models.CharField(blank=True, max_length=12, null=True, verbose_name='House')),
('is_dynamic_ip', models.BooleanField(default=False)),
('markers', bitfield.models.BitField((('icon_donkey', 'Donkey'), ('icon_fire', 'Fire'), ('icon_ok', 'Ok'), ('icon_king', 'King'), ('icon_tv', 'TV'), ('icon_smile', 'Smile'), ('icon_dollar', 'Dollar'), ('icon_service', 'Service'), ('icon_mrk', 'Marker')), default=0)),
],
options={
'verbose_name': 'Abon',
'verbose_name_plural': 'Abons',
'db_table': 'abonent',
'ordering': ['fio'],
'permissions': (('can_buy_tariff', 'Buy service perm'), ('can_view_passport', 'Can view passport'), ('can_add_ballance', 'fill account'), ('can_ping', 'Can ping')),
},
bases=('accounts_app.userprofile',),
bases=('accounts_app.baseaccount',),
),
migrations.CreateModel(
name='AbonGroup',
name='AbonLog',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=127, unique=True)),
('amount', models.FloatField(default=0.0)),
('comment', models.CharField(max_length=128)),
('date', models.DateTimeField(auto_now_add=True)),
],
options={
'db_table': 'abonent_groups',
'db_table': 'abonent_log',
'ordering': ['-date'],
'permissions': (('can_view_abonlog', 'Can view subscriber logs'),),
},
),
migrations.CreateModel(
name='AbonLog',
name='AbonStreet',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('amount', models.FloatField(default=0.0)),
('comment', models.CharField(max_length=128)),
('date', models.DateTimeField(auto_now_add=True)),
('abon', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='abonapp.Abon')),
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to=settings.AUTH_USER_MODEL)),
('name', models.CharField(max_length=64)),
('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='group_app.Group')),
],
options={
'db_table': 'abonent_log',
'verbose_name': 'Street',
'verbose_name_plural': 'Streets',
'db_table': 'abon_street',
'ordering': ['name'],
},
),
migrations.CreateModel(
name='AbonTariff',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('tariff_priority', models.PositiveSmallIntegerField(default=0)),
('time_start', models.DateTimeField(blank=True, default=None, null=True)),
('abon', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='abonapp.Abon')),
('deadline', models.DateTimeField(blank=True, default=None, null=True)),
('tariff', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='linkto_tariff', to='tariff_app.Tariff')),
],
options={
'ordering': ('tariff_priority',),
'verbose_name': 'Abon service',
'verbose_name_plural': 'Abon services',
'db_table': 'abonent_tariff',
'ordering': ['time_start'],
'permissions': (('can_complete_service', 'finish service perm'),),
},
),
migrations.CreateModel(
name='InvoiceForPayment',
name='AdditionalTelephone',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('status', models.BooleanField(default=False)),
('amount', models.FloatField(default=0.0)),
('comment', models.CharField(max_length=128)),
('date_create', models.DateTimeField(auto_now_add=True)),
('date_pay', models.DateTimeField(blank=True, null=True)),
('abon', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='abonapp.Abon')),
('author', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
('telephone', models.CharField(max_length=16, validators=[django.core.validators.RegexValidator('^\\+[7,8,9,3]\\d{10,11}$')], verbose_name='Telephone')),
('owner_name', models.CharField(max_length=127)),
],
options={
'ordering': ('date_create',),
'db_table': 'abonent_inv_pay',
'verbose_name': 'Additional telephone',
'verbose_name_plural': 'Additional telephones',
'db_table': 'additional_telephones',
'ordering': ('owner_name',),
'permissions': (('can_view_additionaltelephones', 'Can view additional telephones'),),
},
),
migrations.AddField(
model_name='abon',
name='current_tariffs',
field=models.ManyToManyField(through='abonapp.AbonTariff', to='tariff_app.Tariff'),
),
migrations.AddField(
model_name='abon',
name='group',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='abonapp.AbonGroup'),
),
migrations.AlterUniqueTogether(
name='abontariff',
unique_together=set([('abon', 'tariff', 'tariff_priority')]),
),
migrations.AddField(
model_name='abongroup',
name='profiles',
field=models.ManyToManyField(blank=True, related_name='abon_groups', to=settings.AUTH_USER_MODEL),
),
migrations.AlterModelOptions(
name='abon',
options={'permissions': (('can_buy_tariff', 'Покупка тарифа абоненту'),)},
),
migrations.AlterModelOptions(
name='abongroup',
options={'permissions': (('can_add_ballance', 'Пополнение счёта'),)},
),
migrations.AlterModelOptions(
name='abontariff',
options={'ordering': ('tariff_priority',), 'permissions': (('can_complete_service', 'Досрочное завершение услуги абонента'), ('can_activate_service', 'Активация услуги абонента'))},
),
migrations.CreateModel(
name='AbonStreet',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=64)),
('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='abonapp.AbonGroup')),
],
),
migrations.RemoveField(
model_name='abon',
name='address',
),
migrations.AddField(
model_name='abon',
name='description',
field=models.TextField(blank=True, null=True),
),
migrations.AddField(
model_name='abon',
name='house',
field=models.CharField(blank=True, max_length=12, null=True),
),
migrations.AddField(
model_name='abon',
name='street',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='abonapp.AbonStreet'),
),
migrations.CreateModel(
name='AllPayLog',
fields=[
@ -158,7 +113,7 @@ class Migration(migrations.Migration):
],
options={
'db_table': 'all_pay_log',
'ordering': ('date_action',),
'ordering': ['-date_action'],
},
),
migrations.CreateModel(
@ -167,70 +122,44 @@ class Migration(migrations.Migration):
('pay_id', models.CharField(max_length=36, primary_key=True, serialize=False, unique=True)),
('date_add', models.DateTimeField(auto_now_add=True)),
('summ', models.FloatField(default=0.0)),
('trade_point', models.CharField(blank=True, default=None, max_length=20, null=True, verbose_name='Trade point')),
('receipt_num', models.BigIntegerField(default=0, verbose_name='Receipt number')),
],
options={
'db_table': 'all_time_pay_log',
'ordering': ('date_add',),
'ordering': ['-date_add'],
},
),
migrations.CreateModel(
name='AbonRawPassword',
name='ExtraFieldsModel',
fields=[
('account', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='abonapp.Abon')),
('passw_text', models.CharField(max_length=64)),
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(default='no title', max_length=16)),
('field_type', models.CharField(choices=[('int', 'Digital field'), ('str', 'Text field'), ('dbl', 'Floating field'), ('ipa', 'Ip Address')], default='str', max_length=3)),
('data', models.CharField(blank=True, max_length=64, null=True)),
],
options={
'db_table': 'abon_raw_password',
'db_table': 'abon_extra_fields',
},
),
migrations.AlterModelTable(
name='abonstreet',
table='abon_street',
),
migrations.AddField(
model_name='abontariff',
name='deadline',
field=models.DateTimeField(blank=True, default=None, null=True),
),
migrations.CreateModel(
name='ExtraFieldsModel',
name='InvoiceForPayment',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('field_type', models.CharField(choices=[('int', 'Цифровое поле'), ('str', 'Текстовое поле'), ('dbl', 'Дробное с плавающей точкой'), ('ipa', 'IP Адрес')], default='str', max_length=3)),
('data', models.CharField(blank=True, max_length=64, null=True)),
('title', models.CharField(default='no title', max_length=16)),
('status', models.BooleanField(default=False)),
('amount', models.FloatField(default=0.0)),
('comment', models.CharField(max_length=128)),
('date_create', models.DateTimeField(auto_now_add=True)),
('date_pay', models.DateTimeField(blank=True, null=True)),
],
options={
'db_table': 'abon_extra_fields',
'verbose_name': 'Debt',
'verbose_name_plural': 'Debts',
'db_table': 'abonent_inv_pay',
'ordering': ('date_create',),
'permissions': (('can_view_invoiceforpayment', 'Can view invoice for payment'),),
},
),
migrations.AlterModelOptions(
name='abon',
options={'permissions': (('can_buy_tariff', 'Покупка тарифа абоненту'), ('can_view_passport', 'Can view passport'))},
),
migrations.AlterModelOptions(
name='abontariff',
options={'ordering': ('tariff_priority',), 'permissions': (('can_complete_service', 'Снятие со счёта средств'), ('can_activate_service', 'Активация услуги абонента'))},
),
migrations.AlterField(
model_name='abon',
name='ballance',
field=models.FloatField(default=0.0),
),
migrations.AlterModelOptions(
name='abon',
options={'permissions': (('can_buy_tariff', 'Покупка тарифа абоненту'), ('can_view_passport', 'Может просматривать паспортные данные'))},
),
migrations.AddField(
model_name='abon',
name='extra_fields',
field=models.ManyToManyField(blank=True, to='abonapp.ExtraFieldsModel'),
),
migrations.AddField(
model_name='abongroup',
name='tariffs',
field=models.ManyToManyField(blank=True, related_name='tariff_groups', to='tariff_app.Tariff'),
),
migrations.CreateModel(
name='PassportInfo',
fields=[
@ -239,38 +168,83 @@ class Migration(migrations.Migration):
('number', models.CharField(max_length=6, validators=[django.core.validators.RegexValidator(re.compile('^-?\\d+\\Z', 32), code='invalid', message='Enter a valid integer.')])),
('distributor', models.CharField(max_length=64)),
('date_of_acceptance', models.DateField()),
('abon', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='abonapp.Abon')),
],
options={
'verbose_name': 'Passport Info',
'verbose_name_plural': 'Passport Info',
'db_table': 'passport_info',
},
),
migrations.CreateModel(
name='AbonDevice',
name='PeriodicPayForId',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('abon', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='abonapp.Abon')),
('device', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='devapp.Device')),
('last_pay', models.DateTimeField(blank=True, null=True, verbose_name='Last pay time')),
('next_pay', models.DateTimeField(verbose_name='Next time to pay')),
],
options={
'db_table': 'abon_device',
'db_table': 'periodic_pay_for_id',
},
),
migrations.AlterUniqueTogether(
name='abondevice',
unique_together=set([('abon', 'device')]),
migrations.CreateModel(
name='AbonRawPassword',
fields=[
('account', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='abonapp.Abon')),
('passw_text', models.CharField(max_length=64)),
],
options={
'db_table': 'abon_raw_password',
},
),
migrations.AddField(
model_name='periodicpayforid',
name='account',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='abonapp.Abon', verbose_name='Account'),
),
migrations.AlterField(
model_name='abondevice',
migrations.AddField(
model_name='periodicpayforid',
name='periodic_pay',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='tariff_app.PeriodicPay', verbose_name='Periodic pay'),
),
migrations.AddField(
model_name='passportinfo',
name='abon',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='abonapp.Abon'),
),
migrations.AddField(
model_name='invoiceforpayment',
name='abon',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='abonapp.Abon'),
),
migrations.AlterField(
model_name='abondevice',
name='device',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='devapp.Device'),
migrations.AddField(
model_name='invoiceforpayment',
name='author',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='alltimepaylog',
name='abon',
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_DEFAULT, to='abonapp.Abon'),
),
migrations.AddField(
model_name='additionaltelephone',
name='abon',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='additional_telephones', to='abonapp.Abon'),
),
migrations.AddField(
model_name='abonlog',
name='abon',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='abonapp.Abon'),
),
migrations.AddField(
model_name='abonlog',
name='author',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='abon',
name='ip_address',
field=mydefs.MyGenericIPAddressField(blank=True, max_length=8, null=True, protocol='ipv4'),
name='current_tariff',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='abonapp.AbonTariff'),
),
migrations.AddField(
model_name='abon',
@ -284,35 +258,17 @@ class Migration(migrations.Migration):
),
migrations.AddField(
model_name='abon',
name='is_dynamic_ip',
field=models.BooleanField(default=False),
),
migrations.DeleteModel(
name='AbonDevice',
),
migrations.AlterModelOptions(
name='abontariff',
options={'permissions': (('can_complete_service', 'Снятие со счёта средств'),)},
name='extra_fields',
field=models.ManyToManyField(blank=True, to='abonapp.ExtraFieldsModel'),
),
migrations.RemoveField(
migrations.AddField(
model_name='abon',
name='current_tariffs',
name='group',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='group_app.Group', verbose_name='User group'),
),
migrations.AddField(
model_name='abon',
name='current_tariff',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='abonapp.AbonTariff'),
),
migrations.AlterUniqueTogether(
name='abontariff',
unique_together=set([]),
),
migrations.RemoveField(
model_name='abontariff',
name='abon',
),
migrations.RemoveField(
model_name='abontariff',
name='tariff_priority',
name='street',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='abonapp.AbonStreet', verbose_name='Street'),
),
]

52
abonapp/migrations/0002_auto_20170905_1248.py

@ -1,52 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-09-05 12:48
from __future__ import unicode_literals
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0001_squashed_0022_auto_20170816_1109'),
]
operations = [
migrations.CreateModel(
name='AdditionalTelephone',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('telephone', models.CharField(max_length=16, validators=[django.core.validators.RegexValidator('^\\+[7,8,9,3]\\d{10,11}$')], verbose_name='Телефон')),
('owner_name', models.CharField(max_length=127)),
],
options={
'verbose_name': 'Дополнительный телефон',
'verbose_name_plural': 'Дополнительные телефоны',
'db_table': 'additional_telephones',
'ordering': ('owner_name',),
},
),
migrations.AlterModelOptions(
name='abon',
options={'permissions': (('can_buy_tariff', 'Покупка тарифа абоненту'), ('can_view_passport', 'Может просматривать паспортные данные')), 'verbose_name': 'Абонент', 'verbose_name_plural': 'Абоненты'},
),
migrations.AlterModelOptions(
name='abongroup',
options={'permissions': (('can_add_ballance', 'Пополнение счёта'),), 'verbose_name': 'Группа абонентов', 'verbose_name_plural': 'Группы абонентов'},
),
migrations.AlterModelOptions(
name='abonstreet',
options={'verbose_name': 'Улица', 'verbose_name_plural': 'Улицы'},
),
migrations.AlterModelOptions(
name='abontariff',
options={'permissions': (('can_complete_service', 'Снятие со счёта средств'),), 'verbose_name': 'Услуга абонента', 'verbose_name_plural': 'Услуги абонентов'},
),
migrations.AddField(
model_name='additionaltelephone',
name='abon',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='additional_telephones', to='abonapp.Abon'),
),
]

43
abonapp/migrations/0003_auto_20170927_1838.py

@ -1,43 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-09-27 18:38
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0002_auto_20170905_1248'),
]
operations = [
migrations.AlterModelOptions(
name='abon',
options={'permissions': (('can_buy_tariff', 'Покупка тарифа абоненту'), ('can_view_passport', 'Может просматривать паспортные данные'), ('can_add_ballance', 'Пополнение счёта'), ('can_ping', 'Может пинговать')), 'verbose_name': 'Абонент', 'verbose_name_plural': 'Абоненты'},
),
migrations.AlterModelOptions(
name='abongroup',
options={'permissions': (('can_view_abongroup', 'Может просматривать группу абонентов'),), 'verbose_name': 'Группа абонентов', 'verbose_name_plural': 'Группы абонентов'},
),
migrations.AlterModelOptions(
name='abonlog',
options={'permissions': (('can_view_abonlog', 'Может видеть логи абонента'),)},
),
migrations.AlterModelOptions(
name='additionaltelephone',
options={'ordering': ('owner_name',), 'permissions': (('can_view_additionaltelephones', 'Может видеть дополнительные телефоны'),), 'verbose_name': 'Дополнительный телефон', 'verbose_name_plural': 'Дополнительные телефоны'},
),
migrations.AlterModelOptions(
name='invoiceforpayment',
options={'ordering': ('date_create',), 'permissions': (('can_view_invoiceforpayment', 'Может видеть назначенные платежи'),), 'verbose_name': 'Квитанция (долг)', 'verbose_name_plural': 'Квитанции (долги)'},
),
migrations.AlterModelOptions(
name='passportinfo',
options={'verbose_name': 'Паспортные данные', 'verbose_name_plural': 'Паспортные данные'},
),
migrations.AlterModelTable(
name='passportinfo',
table='passport_info',
),
]

130
abonapp/migrations/0004_auto_20180122_1732.py

@ -1,130 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2018-01-22 17:32
from __future__ import unicode_literals
from django.conf import settings
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('tariff_app', '0006_auto_20180122_1732'),
('abonapp', '0003_auto_20170927_1838'),
]
operations = [
migrations.CreateModel(
name='PeriodicPayForId',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('last_pay', models.DateTimeField(blank=True, null=True, verbose_name='Last pay time')),
('next_pay', models.DateTimeField(verbose_name='Next time to pay')),
],
options={
'db_table': 'periodic_pay_for_id',
},
),
migrations.AlterModelOptions(
name='abon',
options={'ordering': ['fio'], 'permissions': (('can_buy_tariff', 'Buy service perm'), ('can_view_passport', 'Can view passport'), ('can_add_ballance', 'fill account'), ('can_ping', 'Can ping')), 'verbose_name': 'Abon', 'verbose_name_plural': 'Abons'},
),
migrations.AlterModelOptions(
name='abongroup',
options={'ordering': ['title'], 'permissions': (('can_view_abongroup', 'Can view subscriber group'),), 'verbose_name': 'Abon group', 'verbose_name_plural': 'Abon groups'},
),
migrations.AlterModelOptions(
name='abonlog',
options={'ordering': ['-date'], 'permissions': (('can_view_abonlog', 'Can view subscriber logs'),)},
),
migrations.AlterModelOptions(
name='abonstreet',
options={'ordering': ['name'], 'verbose_name': 'Street', 'verbose_name_plural': 'Streets'},
),
migrations.AlterModelOptions(
name='abontariff',
options={'ordering': ['time_start'], 'permissions': (('can_complete_service', 'finish service perm'),), 'verbose_name': 'Abon service', 'verbose_name_plural': 'Abon services'},
),
migrations.AlterModelOptions(
name='additionaltelephone',
options={'ordering': ('owner_name',), 'permissions': (('can_view_additionaltelephones', 'Can view additional telephones'),), 'verbose_name': 'Additional telephone', 'verbose_name_plural': 'Additional telephones'},
),
migrations.AlterModelOptions(
name='allpaylog',
options={'ordering': ['-date_action']},
),
migrations.AlterModelOptions(
name='alltimepaylog',
options={'ordering': ['-date_add']},
),
migrations.AlterModelOptions(
name='invoiceforpayment',
options={'ordering': ('date_create',), 'permissions': (('can_view_invoiceforpayment', 'Can view invoice for payment'),), 'verbose_name': 'Debt', 'verbose_name_plural': 'Debts'},
),
migrations.AlterModelOptions(
name='passportinfo',
options={'verbose_name': 'Passport Info', 'verbose_name_plural': 'Passport Info'},
),
migrations.AddField(
model_name='alltimepaylog',
name='abon',
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_DEFAULT, to='abonapp.Abon'),
),
migrations.AddField(
model_name='alltimepaylog',
name='receipt_num',
field=models.IntegerField(default=0, verbose_name='Receipt number'),
),
migrations.AddField(
model_name='alltimepaylog',
name='trade_point',
field=models.CharField(blank=True, default=None, max_length=20, null=True, verbose_name='Trade point'),
),
migrations.AlterField(
model_name='abon',
name='description',
field=models.TextField(blank=True, null=True, verbose_name='Comment'),
),
migrations.AlterField(
model_name='abon',
name='group',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='abonapp.AbonGroup', verbose_name='User group'),
),
migrations.AlterField(
model_name='abon',
name='house',
field=models.CharField(blank=True, max_length=12, null=True, verbose_name='House'),
),
migrations.AlterField(
model_name='abon',
name='street',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='abonapp.AbonStreet', verbose_name='Street'),
),
migrations.AlterField(
model_name='abonlog',
name='author',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='additionaltelephone',
name='telephone',
field=models.CharField(max_length=16, validators=[django.core.validators.RegexValidator('^\\+[7,8,9,3]\\d{10,11}$')], verbose_name='Telephone'),
),
migrations.AlterField(
model_name='extrafieldsmodel',
name='field_type',
field=models.CharField(choices=[('int', 'Digital field'), ('str', 'Text field'), ('dbl', 'Floating field'), ('ipa', 'Ip Address')], default='str', max_length=3),
),
migrations.AddField(
model_name='periodicpayforid',
name='account',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='abonapp.Abon', verbose_name='Account'),
),
migrations.AddField(
model_name='periodicpayforid',
name='periodic_pay',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='tariff_app.PeriodicPay', verbose_name='Periodic pay'),
),
]

20
abonapp/migrations/0005_auto_20180123_1353.py

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2018-01-23 13:53
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0004_auto_20180122_1732'),
]
operations = [
migrations.AlterField(
model_name='alltimepaylog',
name='receipt_num',
field=models.BigIntegerField(default=0, verbose_name='Receipt number'),
),
]

23
abonapp/migrations/0006_abon_markers.py

@ -1,23 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2018-02-13 14:06
from __future__ import unicode_literals
import bitfield.models
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0005_auto_20180123_1353'),
]
operations = [
migrations.AddField(
model_name='abon',
name='markers',
field=bitfield.models.BitField((('icon_donkey', 'Donkey'), ('icon_fire', 'Fire'), ('icon_ok', 'Ok'),
('icon_king', 'King'), ('icon_tv', 'TV'), ('icon_smile', 'Smile'),
('icon_dollar', 'Dollar'), ('icon_service', 'Service'),
('icon_mrk', 'Marker')), default=None),
),
]

27
abonapp/models.py

@ -10,8 +10,9 @@ from django.dispatch import receiver
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from accounts_app.models import UserProfile, MyUserManager
from accounts_app.models import UserProfile, MyUserManager, BaseAccount
from agent import Transmitter, AbonStruct, TariffStruct, NasFailedResult, NasNetworkError
from group_app.models import Group
from mydefs import MyGenericIPAddressField, ip2int, LogicError, ip_addr_regex
from tariff_app.models import Tariff, PeriodicPay
from bitfield import BitField
@ -20,24 +21,6 @@ from bitfield import BitField
TELEPHONE_REGEXP = getattr(settings, 'TELEPHONE_REGEXP', r'^\+[7,8,9,3]\d{10,11}$')
class AbonGroup(models.Model):
title = models.CharField(max_length=127, unique=True)
profiles = models.ManyToManyField(UserProfile, blank=True, related_name='abon_groups')
tariffs = models.ManyToManyField(Tariff, blank=True, related_name='tariff_groups')
class Meta:
db_table = 'abonent_groups'
permissions = (
('can_view_abongroup', _('Can view subscriber group')),
)
verbose_name = _('Abon group')
verbose_name_plural = _('Abon groups')
ordering = ['title']
def __str__(self):
return self.title
class AbonLog(models.Model):
abon = models.ForeignKey('Abon', models.CASCADE)
amount = models.FloatField(default=0.0)
@ -89,7 +72,7 @@ class AbonTariff(models.Model):
class AbonStreet(models.Model):
name = models.CharField(max_length=64)
group = models.ForeignKey(AbonGroup, models.CASCADE)
group = models.ForeignKey(Group, models.CASCADE)
def __str__(self):
return self.name
@ -149,9 +132,9 @@ class AbonManager(MyUserManager):
return super(MyUserManager, self).get_queryset().filter(is_admin=False)
class Abon(UserProfile):
class Abon(BaseAccount):
current_tariff = models.ForeignKey(AbonTariff, null=True, blank=True, on_delete=models.SET_NULL)
group = models.ForeignKey(AbonGroup, models.SET_NULL, blank=True, null=True, verbose_name=_('User group'))
group = models.ForeignKey(Group, models.SET_NULL, blank=True, null=True, verbose_name=_('User group'))
ballance = models.FloatField(default=0.0)
ip_address = MyGenericIPAddressField(blank=True, null=True)
description = models.TextField(_('Comment'), null=True, blank=True)

4
abonapp/templates/abonapp/addAbon.html

@ -5,7 +5,7 @@
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'abonapp:group_list' %}">{% trans 'User groups' %}</a></li>
<li><a href="{% url 'abonapp:people_list' abon_group.id %}">{{ abon_group.title }}</a></li>
<li><a href="{% url 'abonapp:people_list' group.id %}">{{ group.title }}</a></li>
<li class="active">{% trans 'Add abon' %}</li>
</ol>
@ -16,7 +16,7 @@
<h3 class="panel-title">{% trans 'Add abon' %}</h3>
</div>
<div class="panel-body">
<form role="form" action="{% url 'abonapp:add_abon' abon_group.id %}" method="post">{% csrf_token %}
<form role="form" action="{% url 'abonapp:add_abon' group.id %}" method="post">{% csrf_token %}
<div class="form-group">
<label for="login">{% trans 'login' %}</label>

39
abonapp/templates/abonapp/addGroup.html

@ -1,39 +0,0 @@
{% extends 'base.html' %}
{% load i18n %}
{% block main %}
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'abonapp:group_list' %}">{% trans 'User groups' %}</a></li>
<li class="active">{% trans 'Add group' %}</li>
</ol>
{% include 'message_block.html' %}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans 'Add group' %}</h3>
</div>
<div class="panel-body">
<form role="form" action="{% url 'abonapp:add_group' %}" method="post">{% csrf_token %}
<div class="form-group">
<label for="gtitle">{% trans 'Group title' %}</label>
<div class="input-group">
<span class="input-group-addon"><span class="glyphicon glyphicon-bookmark"></span></span>
<input id="gtitle" type="text" name="title" required class="form-control">{{ form.title.errors }}
</div>
</div>
<div class="btn-group">
<button type="submit" class="btn btn-sm btn-primary">
<span class="glyphicon glyphicon-save"></span> {% trans 'Save' %}
</button>
<button type="reset" class="btn btn-sm btn-default">
<span class="glyphicon glyphicon-remove-circle"></span> {% trans 'Reset' %}
</button>
</div>
</form>
</div>
</div>
{% endblock %}

8
abonapp/templates/abonapp/addInvoice.html

@ -5,8 +5,8 @@
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'abonapp:group_list' %}">{% trans 'User groups' %}</a></li>
<li><a href="{% url 'abonapp:people_list' abon_group.id %}">{{ abon_group.title }}</a></li>
<li><a href="{% url 'abonapp:abon_home' abon_group.id abon.id %}">{{ abon.fio }}</a></li>
<li><a href="{% url 'abonapp:people_list' group.id %}">{{ group.title }}</a></li>
<li><a href="{% url 'abonapp:abon_home' group.id abon.id %}">{{ abon.fio }}</a></li>
<li class="active">{% trans 'Add debt' %}</li>
</ol>
@ -15,11 +15,11 @@
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans 'Add receipt for' %}
<u><a href="{% url 'abonapp:abon_home' abon_group.id abon.id %}">{{ abon.fio }}</a></u>
<u><a href="{% url 'abonapp:abon_home' group.id abon.id %}">{{ abon.fio }}</a></u>
</h3>
</div>
<div class="panel-body">
<form role="form" action="{% url 'abonapp:add_invoice' abon_group.id abon.id %}"
<form role="form" action="{% url 'abonapp:add_invoice' group.id abon.id %}"
method="post">{% csrf_token %}
<div class="form-group">
<label for="pamount">{% trans 'Sum of pay' %}</label>

10
abonapp/templates/abonapp/buy_tariff.html

@ -5,8 +5,8 @@
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'abonapp:group_list' %}">{% trans 'User groups' %}</a></li>
<li><a href="{% url 'abonapp:people_list' abon_group.pk %}">{{ abon_group.title }}</a></li>
<li><a href="{% url 'abonapp:abon_home' abon_group.pk abon.pk %}">{{ abon.fio }}</a></li>
<li><a href="{% url 'abonapp:people_list' group.pk %}">{{ group.title }}</a></li>
<li><a href="{% url 'abonapp:abon_home' group.pk abon.pk %}">{{ abon.fio }}</a></li>
<li class="active">{% trans 'Pick a service' %}</li>
</ol>
@ -15,11 +15,11 @@
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans 'Pick a service for' %}
<a href="{% url 'abonapp:abon_home' abon_group.pk abon.pk %}"><u>{% trans 'Sub' %}</u></a>
<a href="{% url 'abonapp:abon_home' group.pk abon.pk %}"><u>{% trans 'Sub' %}</u></a>
</h3>
</div>
<div class="panel-body">
<form role="form" action="{% url 'abonapp:pick_tariff' abon_group.pk abon.pk %}"
<form role="form" action="{% url 'abonapp:pick_tariff' group.pk abon.pk %}"
method="post">{% csrf_token %}
<div class="form-group">
{% if tariffs %}
@ -59,7 +59,7 @@
<div class="alert alert-danger" role="alert">
<span class="glyphicon glyphicon-exclamation-sign"></span>
{% trans 'This group has no services' %},
<a href="{% url 'abonapp:ch_group_tariff' abon_group.pk %}">
<a href="{% url 'abonapp:ch_group_tariff' group.pk %}">
{% trans 'Attach serices to groups' %}
</a>
</div>

2
abonapp/templates/abonapp/charts.html

@ -11,7 +11,7 @@
<div class="panel-body">
{% if charts_data %}
<div id="chrt"></div>
<form action="{% url 'abonapp:charts' abon_group.pk abon.pk %}" method="get" class="input-group">
<form action="{% url 'abonapp:charts' group.pk abon.pk %}" method="get" class="input-group">
<span class="input-group-btn">
<button class="btn btn-default" type="submit">
<span class="glyphicon glyphicon-calendar"></span> {% trans 'Show graph by date' %}

24
abonapp/templates/abonapp/editAbon.html

@ -10,7 +10,7 @@
<h3 class="panel-title">{% trans 'Change subscriber' %}</h3>
</div>
<div class="panel-body">
<form autocomplete="off" class="form-horizontal" action="{% url 'abonapp:abon_home' abon_group.pk abon.pk %}" method="post">{% csrf_token %}
<form autocomplete="off" class="form-horizontal" action="{% url 'abonapp:abon_home' group.pk abon.pk %}" method="post">{% csrf_token %}
{% bootstrap_field form.username label_class='col-sm-4' field_class='col-sm-8' form_group_class='form-group-sm' %}
{% bootstrap_field form.fio label_class='col-sm-4' field_class='col-sm-8' form_group_class='form-group-sm' %}
@ -24,10 +24,10 @@
<a href="sip:{{ form.telephone.value }}" class="btn btn-default" data-toggle="tooltip" title="{% trans 'Call to' %}">
<span class="glyphicon glyphicon-earphone"></span>
</a>
<a href="{% url 'abonapp:telephones' abon_group.pk abon.pk %}" class="btn btn-default btn-modal" data-toggle="tooltip" title="{% trans 'Additional telephones' %}">
<a href="{% url 'abonapp:telephones' group.pk abon.pk %}" class="btn btn-default btn-modal" data-toggle="tooltip" title="{% trans 'Additional telephones' %}">
<span class="glyphicon glyphicon-list"></span>
</a>
<a href="{% url 'abonapp:telephone_new' abon_group.pk abon.pk %}" class="btn btn-default btn-modal" data-toggle="tooltip" title="{% trans 'Add telephone' %}">
<a href="{% url 'abonapp:telephone_new' group.pk abon.pk %}" class="btn btn-default btn-modal" data-toggle="tooltip" title="{% trans 'Add telephone' %}">
<span class="glyphicon glyphicon-plus"></span>
</a>
</span>
@ -41,7 +41,7 @@
<div class="input-group input-group-sm">
<input type="text" value="{{ ip|default:'' }}" class="form-control" name="ip" placeholder="{% trans 'Not assigned' %}" id="ipfield" pattern="^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"{% if abon.is_dynamic_ip %} disabled{% endif %}/>
<span class="input-group-btn">
<a href="{% url 'abonapp:reset_ip' abon_group.pk abon.pk %}" class="btn btn-default btn-cmd" data-toggle="tooltip" title="{% trans 'Reset ip' %}" onclick="$('#ipfield').val('');">
<a href="{% url 'abonapp:reset_ip' group.pk abon.pk %}" class="btn btn-default btn-cmd" data-toggle="tooltip" title="{% trans 'Reset ip' %}" onclick="$('#ipfield').val('');">
<span class="glyphicon glyphicon-refresh"></span>
</a>
</span>
@ -116,20 +116,20 @@
</div>
<div class="panel-body">
<form class="form-horizontal" action="{% url 'abonapp:save_user_dev_port' abon_group.pk abon.pk %}" method="post">{% csrf_token %}
<form class="form-horizontal" action="{% url 'abonapp:save_user_dev_port' group.pk abon.pk %}" method="post">{% csrf_token %}
<div class="form-group-sm">
<label for="id_method" class="col-sm-4 control-label">{% trans 'Device' %}</label>
<div class="col-sm-8 btn-group btn-group-sm">
{% if device %}
<a href="{% url 'devapp:view' abon_group.pk device.pk %}" target="_blank" class="btn btn-sm btn-default" title="{% trans 'Mac Address' %}: {{ device.mac_addr|default:_('Not assigned') }}">
<a href="{% url 'devapp:view' group.pk device.pk %}" target="_blank" class="btn btn-sm btn-default" title="{% trans 'Mac Address' %}: {{ device.mac_addr|default:_('Not assigned') }}">
<span class="glyphicon glyphicon-hdd"></span> <span class="hidden-md">{{ device.comment|truncatechars:11 }} {{ device.ip_address }}</span>
</a>
<a href="{% url 'abonapp:clear_dev' abon_group.pk abon.pk %}" class="btn btn-sm btn-danger">
<a href="{% url 'abonapp:clear_dev' group.pk abon.pk %}" class="btn btn-sm btn-danger">
<span class="glyphicon glyphicon-remove-circle"></span> <span class="hidden-xs hidden-lg">{% trans 'Remove clutch' %}</span>
</a>
{% else %}
<a href="{% url 'abonapp:dev' abon_group.pk abon.pk %}" class="btn btn-success btn-sm btn-modal">
<a href="{% url 'abonapp:dev' group.pk abon.pk %}" class="btn btn-success btn-sm btn-modal">
<span class="glyphicon glyphicon-plus"></span> {% trans 'Add clutch' %}
</a>
{% endif %}
@ -177,7 +177,7 @@
<h3 class="panel-title">{% trans 'Extra fields' %}</h3>
</div>
<div class="panel-body">
<form class="form-horizontal" action="{% url 'abonapp:extra_field_edit' abon_group.pk abon.pk %}" method="post">{% csrf_token %}
<form class="form-horizontal" action="{% url 'abonapp:extra_field_edit' group.pk abon.pk %}" method="post">{% csrf_token %}
{% for ef in abon.extra_fields.all %}
<div class="form-group-sm">
@ -188,7 +188,7 @@
<input type="text" value="{{ ef.data|default:_('Not assigned') }}" class="form-control" pattern="{{ ef.get_regexp }}" name="ex">
<input type="hidden" value="{{ ef.pk }}" name="ed">
<span class="input-group-btn">
<a href="{% url 'abonapp:extra_field_delete' abon_group.pk abon.pk ef.pk %}" class="btn btn-danger" title="{% trans 'Delete' %}">
<a href="{% url 'abonapp:extra_field_delete' group.pk abon.pk ef.pk %}" class="btn btn-danger" title="{% trans 'Delete' %}">
<span class="glyphicon glyphicon-remove"></span>
</a>
</span>
@ -202,7 +202,7 @@
<div class="form-group-sm">
<div class="col-sm-offset-4 col-sm-8 btn-group btn-group-sm">
<a href="{% url 'abonapp:extra_field' abon_group.pk abon.pk %}" class="btn btn-success btn-modal" title="{% trans 'Add extra field' %}">
<a href="{% url 'abonapp:extra_field' group.pk abon.pk %}" class="btn btn-success btn-modal" title="{% trans 'Add extra field' %}">
<span class="glyphicon glyphicon-plus"></span> {% trans 'Add' %}
</a>
@ -227,7 +227,7 @@
</div>
<div class="panel-footer">
<div class="btn-group">
<a href="{% url 'abonapp:markers_edit' abon_group.pk abon.pk %}" class="btn btn-default btn-modal">
<a href="{% url 'abonapp:markers_edit' group.pk abon.pk %}" class="btn btn-default btn-modal">
<span class="glyphicon glyphicon-edit"></span> {% trans 'Edit' %}
</a>
</div>

16
abonapp/templates/abonapp/ext.htm

@ -5,7 +5,7 @@
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'abonapp:group_list' %}">{% trans 'User groups' %}</a></li>
<li><a href="{% url 'abonapp:people_list' abon_group.pk %}">{{ abon_group.title }}</a></li>
<li><a href="{% url 'abonapp:people_list' group.pk %}">{{ group.title }}</a></li>
<li class="active">{{ abon.fio }}</li>
</ol>
@ -21,39 +21,39 @@
<ul class="nav nav-tabs nav-justified">
{% url 'abonapp:abon_home' abon_group.pk abon.pk as abon_home %}
{% url 'abonapp:abon_home' group.pk abon.pk as abon_home %}
<li{% if abon_home == request.path %} class="active"{% endif %}>
<a href="{{ abon_home }}">{% trans 'Sub information' %}</a>
</li>
{% url 'abonapp:abon_services' abon_group.pk abon.pk as abserv %}
{% url 'abonapp:abon_services' group.pk abon.pk as abserv %}
<li{% if abserv == request.path %} class="active"{% endif %}>
<a href="{{ abserv }}">{% trans 'Services' %}</a>
</li>
{% if perms.abonapp.can_view_passport %}
{% url 'abonapp:passport_view' abon_group.pk abon.pk as passport_view_url %}
{% url 'abonapp:passport_view' group.pk abon.pk as passport_view_url %}
<li{% if passport_view_url == request.path %} class="active"{% endif %}>
<a href="{{ passport_view_url }}">{% trans 'Passport information' %}</a>
</li>
{% endif %}
{% url 'abonapp:abon_phistory' abon_group.pk abon.pk as abphist %}
{% url 'abonapp:abon_phistory' group.pk abon.pk as abphist %}
<li{% if abphist == request.path %} class="active"{% endif %}>
<a href="{{ abphist }}">{% trans 'Payments' %}</a>
</li>
{% url 'abonapp:task_log' abon_group.pk abon.pk as abtasklog %}
{% url 'abonapp:task_log' group.pk abon.pk as abtasklog %}
<li{% if abtasklog == request.path %} class="active"{% endif %}>
<a href="{{ abtasklog }}">{% trans 'History of tasks' %}</a>
</li>
{% url 'abonapp:charts' abon_group.pk abon.pk as abtasklog %}
{% url 'abonapp:charts' group.pk abon.pk as abtasklog %}
<li{% if abtasklog == request.path %} class="active"{% endif %}>
<a href="{{ abtasklog }}">{% trans 'Charts' %}</a>
</li>
{% url 'abonapp:dials' abon_group.pk abon.pk as abdials %}
{% url 'abonapp:dials' group.pk abon.pk as abdials %}
<li{% if abdials == request.path %} class="active"{% endif %}>
<a href="{{ abdials }}">{% trans 'Dialing' %}</a>
</li>

12
abonapp/templates/abonapp/group_list.html

@ -35,13 +35,6 @@
<td><a href="{% url 'abonapp:people_list' gr.pk %}">{{ gr.title }}</a></td>
<td class="hidden-xs">{{ gr.usercount }}</td>
<td class="btn-group">
{% if perms.abonapp.delete_abongroup %}
{% if gr.usercount == 0 %}
<a href="{% url 'abonapp:del_group' %}?id={{ gr.pk }}" class="btn btn-sm btn-danger">
<span class="glyphicon glyphicon-remove-circle"></span>
</a>
{% endif %}
{% endif %}
<a href="{% url 'abonapp:ch_group_tariff' gr.pk %}" class="btn btn-sm btn-default"
title="{% trans 'User groups' %}">
<span class="glyphicon glyphicon-cog"></span>
@ -57,11 +50,6 @@
<tfoot>
<tr>
<td colspan="4" class="btn-group btn-group-sm">
{% if perms.abonapp.add_abongroup %}
<a href="{% url 'abonapp:add_group' %}" class="btn btn-success">
<span class="glyphicon glyphicon-plus"></span> <span class="hidden-xs">{% trans 'Add group' %}</span>
</a>
{% endif %}
{% if perms.abonapp.can_view_abonlog %}
<a href="{% url 'abonapp:log' %}" class="btn btn-default">
<span class="glyphicon glyphicon-record"></span> <span class="hidden-xs">{% trans 'Subscribers actions' %}</span>

5
abonapp/templates/abonapp/group_tariffs.html

@ -5,17 +5,18 @@
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'abonapp:group_list' %}">{% trans 'User groups' %}</a></li>
<li><a href="{% url 'abonapp:people_list' abon_group.id %}">{{ abon_group.title }}</a></li>
<li><a href="{% url 'abonapp:people_list' group.id %}">{{ group.title }}</a></li>
<li class="active">{% trans 'Belonging services for groups' %}</li>
</ol>
{% include 'message_block.html' %}
<legend>{% trans 'Belonging services for groups' %}</legend>
<form action="{% url 'abonapp:ch_group_tariff' abon_group.pk %}" method="post" role="form">{% csrf_token %}
<form action="{% url 'abonapp:ch_group_tariff' group.pk %}" method="post" role="form">{% csrf_token %}
{% for tariff in tariffs %}
<div class="checkbox">
<label>
{# FIXME после создания метода привязки тарифов к группам применить его тут #}
{% if tariff in abon_group.tariffs.all %}
<input name="tr" type="checkbox" value="{{ tariff.pk }}" checked/>
{% else %}

6
abonapp/templates/abonapp/invoiceForPayment.html

@ -5,8 +5,8 @@
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'abonapp:group_list' %}">{% trans 'User groups' %}</a></li>
<li><a href="{% url 'abonapp:people_list' abon_group.pk %}">{{ abon_group.title }}</a></li>
<li><a href="{% url 'abonapp:abon_phistory' abon_group.pk abon.pk %}">{{ abon.fio }}</a></li>
<li><a href="{% url 'abonapp:people_list' group.pk %}">{{ group.title }}</a></li>
<li><a href="{% url 'abonapp:abon_phistory' group.pk abon.pk %}">{{ abon.fio }}</a></li>
<li class="active">{% trans 'Debts' %}</li>
</ol>
@ -57,7 +57,7 @@
<tfoot>
<tr>
<th colspan="7">
<a href="{% url 'abonapp:add_invoice' abon_group.id abon.id %}" class="btn btn-success btn-sm">
<a href="{% url 'abonapp:add_invoice' group.id abon.id %}" class="btn btn-success btn-sm">
<span class="glyphicon glyphicon-plus"></span> {% trans 'Add debt' %}
</a>
</th>

3
abonapp/templates/abonapp/modal_abonamount.html

@ -1,6 +1,5 @@
{% load i18n %}
<form role="form" action="{% url 'abonapp:abon_amount' abon_group.id abon.id %}" method="post"> {% csrf_token %}
<form role="form" action="{% url 'abonapp:abon_amount' group_id abon.id %}" method="post"> {% csrf_token %}
<div class="modal-header primary">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title"><span class="glyphicon glyphicon-shopping-cart"></span>{% trans 'Additional sum' %}</h4>

2
abonapp/templates/abonapp/passport_view.html

@ -9,7 +9,7 @@
<h3 class="panel-title">{% trans 'Passport information' %}</h3>
</div>
<div class="panel-body">
<form role="form" class="form-horizontal" action="{% url 'abonapp:passport_view' abon_group.pk abon.pk %}" method="post">{% csrf_token %}
<form role="form" class="form-horizontal" action="{% url 'abonapp:passport_view' group.pk abon.pk %}" method="post">{% csrf_token %}
<div class="form-group-sm">
<label for="id_series" class="col-sm-3 control-label">{% trans 'Pasport serial' %}</label>

4
abonapp/templates/abonapp/payHistory.html

@ -36,7 +36,7 @@
<tr>
<td colspan="4" class="btn-group btn-group-sm">
{% if perms.abonapp.can_add_ballance %}
<a href="{% url 'abonapp:abon_amount' abon_group.pk abon.pk %}" class="btn btn-default btn-modal">
<a href="{% url 'abonapp:abon_amount' group.pk abon.pk %}" class="btn btn-default btn-modal">
<span class="glyphicon glyphicon-credit-card"></span> {% trans 'Fill account' %}
</a>
{% else %}
@ -44,7 +44,7 @@
<span class="glyphicon glyphicon-credit-card"></span> {% trans 'Fill account' %}
</a>
{% endif %}
<a href="{% url 'abonapp:abon_debts' abon_group.pk abon.pk %}" class="btn btn-default">
<a href="{% url 'abonapp:abon_debts' group.pk abon.pk %}" class="btn btn-default">
<span class="glyphicon glyphicon-gbp"></span> {% trans 'Debts' %}
</a>
</td>

45
abonapp/templates/abonapp/peoples.html

@ -3,13 +3,13 @@
{% load dpagination %}
{% block main %}
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'abonapp:group_list' %}">{% trans 'User groups' %}</a></li>
<li class="active">{{ abon_group.title }}</li>
</ol>
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'abonapp:group_list' %}">{% trans 'User groups' %}</a></li>
<li class="active">{{ group.title }}</li>
</ol>
{% include 'message_block.html' %}
{% include 'message_block.html' %}
<h3>{% trans 'The people in the selected group' %}</h3>
<div class="row">
@ -20,32 +20,32 @@
<tr>
<th>#</th>
<th class="col-xs-1">
<a href="{% url 'abonapp:people_list' abon_group.pk %}?{% url_replace request order_by='username' dir=dir|default:'down' %}">
<a href="{% url 'abonapp:people_list' group.pk %}?{% url_replace request order_by='username' dir=dir|default:'down' %}">
{% trans 'Sub' %}
</a>
{% if order_by == 'username' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
</th>
<th class="hidden-xs">{% trans 'Last traffic' %}</th>
<th class="col-xs-1 hidden-md">
<a href="{% url 'abonapp:people_list' abon_group.pk %}?{% url_replace request order_by='ip_address' dir=dir|default:'down' %}">
<a href="{% url 'abonapp:people_list' group.pk %}?{% url_replace request order_by='ip_address' dir=dir|default:'down' %}">
{% trans 'Ip address' %}
</a>
{% if order_by == 'ip_address' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
</th>
<th class="col-xs-2">
<a href="{% url 'abonapp:people_list' abon_group.pk %}?{% url_replace request order_by='fio' dir=dir|default:'down' %}">
<a href="{% url 'abonapp:people_list' group.pk %}?{% url_replace request order_by='fio' dir=dir|default:'down' %}">
{% trans 'fio' %}
</a>
{% if order_by == 'fio' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
</th>
<th class="col-xs-2">
<a href="{% url 'abonapp:people_list' abon_group.pk %}?{% url_replace request order_by='street' dir=dir|default:'down' %}">
<a href="{% url 'abonapp:people_list' group.pk %}?{% url_replace request order_by='street' dir=dir|default:'down' %}">
{% 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' abon_group.pk %}?{% url_replace request order_by='house' dir=dir|default:'down' %}">
<a href="{% url 'abonapp:people_list' group.pk %}?{% url_replace request order_by='house' dir=dir|default:'down' %}">
{% trans 'Apartment' %}
</a>
{% if order_by == 'house' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
@ -53,7 +53,7 @@
<th class="col-xs-2">{% trans 'Telephone' %}</th>
<th class="col-xs-2">{% trans 'Service' %}</th>
<th class="hidden-xs col-sm-1">
<a href="{% url 'abonapp:people_list' abon_group.pk %}?{% url_replace request order_by='ballance' dir=dir|default:'down' %}">
<a href="{% url 'abonapp:people_list' group.pk %}?{% url_replace request order_by='ballance' dir=dir|default:'down' %}">
{% trans 'Ballance' %}
</a>
{% if order_by == 'ballance' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
@ -67,14 +67,15 @@
{% for human in peoples %}
{% if human.is_active %}
<tr>
{% else %}
{% else %}
<tr class="danger">
{% endif %}
<td>{% if human.stat_cache and human.stat_cache.is_online %}
<span class="glyphicon glyphicon-ok text-success"></span>
{% else %}
<span class="glyphicon glyphicon-remove-sign text-muted"></span>
{% endif %}</td>
{% endif %}
</td>
<td>
<a href="{% url 'abonapp:abon_home' human.group.pk human.pk %}">{{ human.username }}</a>
</td>
@ -120,7 +121,7 @@
<td colspan="12">
{% trans 'Subscribers not found' %}.
{% if perms.abonapp.add_abon %}
<a href="{% url 'abonapp:add_abon' abon_group.pk %}">{% trans 'Add abon' %}</a>
<a href="{% url 'abonapp:add_abon' group.pk %}">{% trans 'Add abon' %}</a>
{% endif %}
</td>
</tr>
@ -131,17 +132,17 @@
<tr>
<td colspan="12" class="btn-group btn-group-sm">
{% if perms.abonapp.add_abon %}
<a href="{% url 'abonapp:add_abon' abon_group.pk %}" class="btn btn-default" title="{% trans 'Add' %}" data-toggle="tooltip">
<a href="{% url 'abonapp:add_abon' group.pk %}" class="btn btn-default" title="{% trans 'Add' %}" data-toggle="tooltip">
<span class="glyphicon glyphicon-plus"></span> {% trans 'Add abon' %}
</a>
{% endif %}
<a href="{% url 'abonapp:ch_group_tariff' abon_group.pk %}" class="btn btn-default" title="{% trans 'User groups' %}" data-toggle="tooltip">
<a href="{% url 'abonapp:ch_group_tariff' group.pk %}" class="btn btn-default" title="{% trans 'User groups' %}" data-toggle="tooltip">
<span class="glyphicon glyphicon-subscript"></span> {% trans 'Tariffs in groups' %}
</a>
<a href="{% url 'abonapp:phonebook' abon_group.pk %}" class="btn btn-default btn-modal">
<a href="{% url 'abonapp:phonebook' group.pk %}" class="btn btn-default btn-modal">
<span class="glyphicon glyphicon-earphone"></span> {% trans 'Phonebook' %}
</a>
<a href="{% url 'abonapp:abon_export' abon_group.pk %}" class="btn btn-default btn-modal">
<a href="{% url 'abonapp:abon_export' group.pk %}" class="btn btn-default btn-modal">
<span class="glyphicon glyphicon-export"></span> {% trans 'Export users' %}
</a>
</td>
@ -155,15 +156,15 @@
<div class="panel-heading">{% trans 'Streets' %}</div>
<div class="list-group">
{% for street in streets %}
<a href="{% url 'abonapp:people_list' abon_group.pk %}?{% url_page_replace request 'street' street.pk %}" class="list-group-item{% if street_id == street.pk %} active{% endif %}">{{ street.name }}</a>
<a href="{% url 'abonapp:people_list' group.pk %}?{% url_page_replace request 'street' street.pk %}" class="list-group-item{% if street_id == street.pk %} active{% endif %}">{{ street.name }}</a>
{% empty %}
<a href="#" class="list-group-item">{% trans 'No streets found for that group' %}</a>
{% endfor %}
<div class="btn-group btn-group-sm btn-group-justified">
<a href="{% url 'abonapp:street_add' abon_group.pk %}" class="btn btn-success btn-modal" data-toggle="tooltip" title="{% trans 'Add street' %}">
<a href="{% url 'abonapp:street_add' group.pk %}" class="btn btn-success btn-modal" data-toggle="tooltip" title="{% trans 'Add street' %}">
<span class="glyphicon glyphicon-plus"></span> {% trans 'Add' %}
</a>
<a href="{% url 'abonapp:street_edit' abon_group.pk %}" class="btn btn-primary btn-modal" data-toggle="tooltip" title="{% trans 'Edit streets' %}">
<a href="{% url 'abonapp:street_edit' group.pk %}" class="btn btn-primary btn-modal" data-toggle="tooltip" title="{% trans 'Edit streets' %}">
<span class="glyphicon glyphicon-edit"></span> {% trans 'Edit' %}
</a>
</div>

14
abonapp/templates/abonapp/service.html

@ -49,13 +49,13 @@
{% else %}
{% trans 'Subscriber has no service' %}.
<a href="{% url 'abonapp:pick_tariff' abon_group.pk abon.pk %}">
<a href="{% url 'abonapp:pick_tariff' group.pk abon.pk %}">
{% trans 'Buy service' %}
</a>
{% endif %}
{% if abon_tariff %}
<a href="{% url 'abonapp:unsubscribe_service' abon_group.pk abon.pk abon_tariff.pk %}" class="btn btn-sm btn-danger">
<a href="{% url 'abonapp:unsubscribe_service' group.pk abon.pk abon_tariff.pk %}" class="btn btn-sm btn-danger">
<span class="glyphicon glyphicon-remove-circle"></span> {% trans 'Finish service' %}
</a>
{% endif %}
@ -82,7 +82,7 @@
{% with can_ch_trf=perms.tariff_app.change_tariff %}
{% for service in services %}
<tr>
<td><a href="{% url 'abonapp:pick_tariff' abon_group.pk abon.pk %}?selected_tariff={{ service.pk }}"
<td><a href="{% url 'abonapp:pick_tariff' group.pk abon.pk %}?selected_tariff={{ service.pk }}"
class="btn btn-sm btn-default" title="{{ service.get_calc_type_display }}" data-toggle="tooltip"{% if abon_tariff %} disabled{% endif %}>
<span class="glyphicon glyphicon-shopping-cart"></span>
</a></td>
@ -100,7 +100,7 @@
{% empty %}
<tr><td colspan="5">
{% trans 'This group has no services' %}
<a href="{% url 'abonapp:ch_group_tariff' abon_group.pk %}" class="btn btn-sm btn-default" title="{% trans 'User groups' %}">
<a href="{% url 'abonapp:ch_group_tariff' group.pk %}" class="btn btn-sm btn-default" title="{% trans 'User groups' %}">
<span class="glyphicon glyphicon-cog"></span> {% trans 'Tariffs in groups' %}
</a>
</td></tr>
@ -108,7 +108,7 @@
{% endwith %}
</tbody>
</table>
<a href="{% url 'abonapp:ch_group_tariff' abon_group.pk %}" class="btn btn-sm btn-primary" title="{% trans 'User groups' %}">
<a href="{% url 'abonapp:ch_group_tariff' group.pk %}" class="btn btn-sm btn-primary" title="{% trans 'User groups' %}">
<span class="glyphicon glyphicon-cog"></span> {% trans 'Attach services to group' %}
</a>
</div>
@ -131,11 +131,11 @@
<dt>{% trans 'Next time to pay' %}</dt>
<dd>{{ periodic_pay.next_pay|date:'d E Y' }}</dd>
</dl>
<a href="{% url 'abonapp:del_periodic_pay' abon_group.pk abon.pk periodic_pay.pk %}" class="btn btn-sm btn-danger">
<a href="{% url 'abonapp:del_periodic_pay' group.pk abon.pk periodic_pay.pk %}" class="btn btn-sm btn-danger">
<span class="glyphicon glyphicon-remove-circle"></span> {% trans 'Remove periodic pay' %}
</a>
{% else %}
<a href="{% url 'abonapp:add_periodic_pay' abon_group.pk abon.pk %}" class="btn btn-primary btn-sm btn-modal">
<a href="{% url 'abonapp:add_periodic_pay' group.pk abon.pk %}" class="btn btn-primary btn-sm btn-modal">
<span class="glyphicon glyphicon-plus"></span> {% trans 'Add periodic pay' %}
</a>
{% endif %}

2
abonapp/urls.py

@ -8,8 +8,6 @@ app_name = 'abonapp'
urlpatterns = [
url(r'^$', views.GroupListView.as_view(), name='group_list'),
url(r'^addgroup$', views.addgroup, name='add_group'),
url(r'^delgroup', views.delgroup, name='del_group'),
url(r'^fin_report$', views.fin_report, name='fin_report'),

182
abonapp/views.py

@ -24,6 +24,7 @@ from datetime import datetime, date, timedelta
from taskapp.models import Task
from dialing_app.models import AsteriskCDR
from statistics.models import getModel
from group_app.models import Group
from guardian.shortcuts import get_objects_for_user, assign_perm
from guardian.decorators import permission_required_or_403 as permission_required
from djing.global_base_views import OrderingMixin
@ -67,84 +68,38 @@ class PeoplesListView(BaseAbonListView):
gid = mydefs.safe_int(self.kwargs.get('gid'))
if gid == 0:
return HttpResponseBadRequest('group id is broken')
abon_group = get_object_or_404(models.AbonGroup, pk=gid)
if not self.request.user.has_perm('abonapp.can_view_abongroup', abon_group):
group = get_object_or_404(Group, pk=gid)
if not self.request.user.has_perm('group_app.can_view_group', group):
raise PermissionDenied
context = super(PeoplesListView, self).get_context_data(**kwargs)
context['streets'] = models.AbonStreet.objects.filter(group=gid)
context['street_id'] = mydefs.safe_int(self.request.GET.get('street'))
context['abon_group'] = abon_group
context['group'] = group
return context
@login_required
@permission_required('abonapp.add_abongroup')
def addgroup(request):
frm = forms.AbonGroupForm()
try:
if request.method == 'POST':
frm = forms.AbonGroupForm(request.POST)
if frm.is_valid():
grp = frm.save()
assign_perm('abonapp.can_view_abongroup', request.user, grp)
assign_perm('abonapp.delete_abongroup', request.user, grp)
assign_perm('abonapp.change_abongroup', request.user, grp)
messages.success(request, _('create group success msg'))
return redirect('abonapp:group_list')
else:
messages.error(request, _('fix form errors'))
except (NasFailedResult, NasNetworkError) as e:
messages.error(request, e)
except mydefs.MultipleException as errs:
for err in errs.err_list:
messages.add_message(request, messages.constants.ERROR, err)
return render(request, 'abonapp/addGroup.html', {
'form': frm
})
class GroupListView(BaseAbonListView):
context_object_name = 'groups'
template_name = 'abonapp/group_list.html'
queryset = models.AbonGroup.objects.annotate(usercount=Count('abon')).order_by('title')
queryset = Group.objects.annotate(usercount=Count('abon'))
def get_queryset(self):
queryset = super(GroupListView, self).get_queryset()
queryset = get_objects_for_user(self.request.user, 'abonapp.can_view_abongroup', klass=queryset,
queryset = get_objects_for_user(self.request.user, 'group_app.can_view_group', klass=queryset,
accept_global_perms=False)
return queryset
@login_required
def delgroup(request):
try:
agd = mydefs.safe_int(request.GET.get('id'))
abon_group = models.AbonGroup.objects.get(pk=agd)
if not request.user.has_perm('abonapp.delete_abongroup', abon_group):
raise PermissionDenied
abon_group.delete()
messages.success(request, _('delete group success msg'))
return mydefs.res_success(request, 'abonapp:group_list')
except (NasFailedResult, NasNetworkError) as e:
messages.error(request, e)
except mydefs.MultipleException as errs:
for err in errs.err_list:
messages.add_message(request, messages.constants.ERROR, err)
except models.AbonGroup.DoesNotExist:
return mydefs.res_error(request, 'Group with id=%d does not exist' % agd)
return mydefs.res_error(request, 'abonapp:group_list')
@login_required
@permission_required('abonapp.add_abon')
def addabon(request, gid):
frm = None
group = None
try:
group = get_object_or_404(models.AbonGroup, pk=gid)
if not request.user.has_perm('abonapp.can_view_abongroup', group):
group = get_object_or_404(Group, pk=gid)
if not request.user.has_perm('group_app.can_view_group', group):
raise PermissionDenied
if request.method == 'POST':
frm = forms.AbonForm(request.POST, initial={'group': group})
@ -164,7 +119,7 @@ def addabon(request, gid):
messages.error(request, e)
except mydefs.MultipleException as errs:
for err in errs.err_list:
messages.add_message(request, messages.constants.ERROR, err)
messages.error(request, err)
if not frm:
frm = forms.AbonForm(initial={
@ -175,7 +130,7 @@ def addabon(request, gid):
return render(request, 'abonapp/addAbon.html', {
'form': frm,
'abon_group': group
'group': group
})
@ -186,7 +141,7 @@ def del_abon(request):
try:
abon = get_object_or_404(models.Abon, pk=uid)
if not request.user.has_perm('abonapp.delete_abon') or not request.user.has_perm(
'abonapp.can_view_abongroup', abon.group):
'group_app.can_view_group', abon.group):
raise PermissionDenied
gid = abon.group.id
abon.delete()
@ -199,7 +154,7 @@ def del_abon(request):
messages.error(request, _("NAS says: '%s'") % e)
except mydefs.MultipleException as errs:
for err in errs.err_list:
messages.add_message(request, messages.constants.ERROR, err)
messages.error(request, err)
return redirect('abonapp:group_list')
@ -223,14 +178,14 @@ def abonamount(request, gid, uid):
messages.error(request, e)
except mydefs.MultipleException as errs:
for err in errs.err_list:
messages.add_message(request, messages.constants.ERROR, err)
messages.error(request, err)
return render_to_text('abonapp/modal_abonamount.html', {
'abon': abon,
'abon_group': get_object_or_404(models.AbonGroup, pk=gid)
'group_id': gid
}, request=request)
@method_decorator(permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid')), name='dispatch')
@method_decorator(permission_required('group_app.can_view_group', (Group, 'pk', 'gid')), name='dispatch')
class DebtsListView(BaseAbonListView):
context_object_name = 'invoices'
template_name = 'abonapp/invoiceForPayment.html'
@ -242,12 +197,12 @@ class DebtsListView(BaseAbonListView):
def get_context_data(self, **kwargs):
context = super(DebtsListView, self).get_context_data(**kwargs)
context['abon_group'] = self.abon.group
context['group'] = self.abon.group
context['abon'] = self.abon
return context
@method_decorator(permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid')), name='dispatch')
@method_decorator(permission_required('group_app.can_view_group', (Group, 'pk', 'gid')), name='dispatch')
class PayHistoryListView(BaseAbonListView):
context_object_name = 'pay_history'
template_name = 'abonapp/payHistory.html'
@ -260,7 +215,7 @@ class PayHistoryListView(BaseAbonListView):
def get_context_data(self, **kwargs):
context = super(PayHistoryListView, self).get_context_data(**kwargs)
context['abon_group'] = self.abon.group
context['group'] = self.abon.group
context['abon'] = self.abon
return context
@ -268,8 +223,8 @@ class PayHistoryListView(BaseAbonListView):
@login_required
@mydefs.only_admins
def abon_services(request, gid, uid):
grp = get_object_or_404(models.AbonGroup, pk=gid)
if not request.user.has_perm('abonapp.can_view_abongroup', grp):
grp = get_object_or_404(Group, pk=gid)
if not request.user.has_perm('group_app.can_view_group', grp):
raise PermissionDenied
abon = get_object_or_404(models.Abon, pk=uid)
@ -285,8 +240,8 @@ def abon_services(request, gid, uid):
return render(request, 'abonapp/service.html', {
'abon': abon,
'abon_tariff': abon.current_tariff,
'abon_group': abon.group,
'services': grp.tariffs.all(),
'group': abon.group,
'services': Tariff.objects.get_tariffs_by_group(abon.group.pk),
'periodic_pay': periodic_pay
})
@ -295,8 +250,8 @@ def abon_services(request, gid, uid):
@mydefs.only_admins
def abonhome(request, gid, uid):
abon = get_object_or_404(models.Abon, pk=uid)
abon_group = get_object_or_404(models.AbonGroup, pk=gid)
if not request.user.has_perm('abonapp.can_view_abongroup', abon_group):
group = get_object_or_404(Group, pk=gid)
if not request.user.has_perm('group_app.can_view_group', group):
raise PermissionDenied
frm = None
passw = None
@ -329,13 +284,13 @@ def abonhome(request, gid, uid):
messages.warning(request, _('User has not have password, and cannot login'))
except mydefs.MultipleException as errs:
for err in errs.err_list:
messages.add_message(request, messages.constants.ERROR, err)
messages.error(request, err)
if request.user.has_perm('abonapp.change_abon'):
return render(request, 'abonapp/editAbon.html', {
'form': frm or forms.AbonForm(instance=abon, initial={'password': passw}),
'abon': abon,
'abon_group': abon_group,
'group': group,
'ip': abon.ip_address,
'is_bad_ip': getattr(abon, 'is_bad_ip', False),
'device': abon.device,
@ -344,7 +299,7 @@ def abonhome(request, gid, uid):
else:
return render(request, 'abonapp/viewAbon.html', {
'abon': abon,
'abon_group': abon_group,
'group': group,
'ip': abon.ip_address,
'passw': passw
})
@ -362,7 +317,7 @@ def terminal_pay(request):
def add_invoice(request, gid, uid):
uid = mydefs.safe_int(uid)
abon = get_object_or_404(models.Abon, pk=uid)
grp = get_object_or_404(models.AbonGroup, pk=gid)
grp = get_object_or_404(Group, pk=gid)
try:
if request.method == 'POST':
@ -386,21 +341,22 @@ def add_invoice(request, gid, uid):
messages.error(request, e)
except mydefs.MultipleException as errs:
for err in errs.err_list:
messages.add_message(request, messages.constants.ERROR, err)
messages.error(request, err)
return render(request, 'abonapp/addInvoice.html', {
'abon': abon,
'invcount': models.InvoiceForPayment.objects.filter(abon=abon).count(),
'abon_group': grp
'group': grp
})
@login_required
@mydefs.only_admins
@permission_required('abonapp.can_buy_tariff')
@transaction.atomic
def pick_tariff(request, gid, uid):
grp = get_object_or_404(models.AbonGroup, pk=gid)
grp = get_object_or_404(Group, pk=gid)
abon = get_object_or_404(models.Abon, pk=uid)
tariffs = grp.tariffs.all()
tariffs = Tariff.objects.get_tariffs_by_group(grp.pk)
try:
if request.method == 'POST':
trf = Tariff.objects.get(pk=request.POST.get('tariff'))
@ -425,14 +381,14 @@ def pick_tariff(request, gid, uid):
messages.error(request, _('Tariff your picked does not exist'))
except mydefs.MultipleException as errs:
for err in errs.err_list:
messages.add_message(request, messages.constants.ERROR, err)
messages.error(request, err)
except ValueError as e:
messages.error(request, "%s: %s" % (_('fix form errors'), e))
return render(request, 'abonapp/buy_tariff.html', {
'tariffs': tariffs,
'abon': abon,
'abon_group': grp,
'group': grp,
'selected_tariff': mydefs.safe_int(request.GET.get('selected_tariff'))
})
@ -450,7 +406,7 @@ def unsubscribe_service(request, gid, uid, abon_tariff_id):
messages.warning(request, e)
except mydefs.MultipleException as errs:
for err in errs.err_list:
messages.add_message(request, messages.constants.ERROR, err)
messages.error(request, err)
return redirect('abonapp:abon_services', gid=gid, uid=uid)
@ -475,7 +431,7 @@ class DebtorsListView(ListView):
@method_decorator(login_required, name='dispatch')
@method_decorator(permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid')), name='dispatch')
@method_decorator(permission_required('group_app.can_view_group', (Group, 'pk', 'gid')), name='dispatch')
class TaskLogListView(ListView):
paginate_by = PAGINATION_ITEMS_PER_PAGE
http_method_names = ['get']
@ -489,7 +445,7 @@ class TaskLogListView(ListView):
def get_context_data(self, **kwargs):
context = super(TaskLogListView, self).get_context_data(**kwargs)
context['abon_group'] = self.abon.group
context['group'] = self.abon.group
context['abon'] = self.abon
return context
@ -497,8 +453,8 @@ class TaskLogListView(ListView):
@login_required
@permission_required('abonapp.can_view_passport')
def passport_view(request, gid, uid):
abon = get_object_or_404(models.Abon, pk=uid)
try:
abon = models.Abon.objects.get(pk=uid)
if request.method == 'POST':
try:
passport_instance = models.PassportInfo.objects.get(abon=abon)
@ -523,7 +479,7 @@ def passport_view(request, gid, uid):
messages.warning(request, _('Passport info for the user does not exist'))
frm = forms.PassportForm()
return render(request, 'abonapp/passport_view.html', {
'abon_group': get_object_or_404(models.AbonGroup, pk=gid),
'group': get_object_or_404(Group, pk=gid),
'abon': abon,
'frm': frm
})
@ -532,17 +488,19 @@ def passport_view(request, gid, uid):
@login_required
@mydefs.only_admins
def chgroup_tariff(request, gid):
grp = get_object_or_404(models.AbonGroup, pk=gid)
grp = get_object_or_404(Group, pk=gid)
if not request.user.has_perm('abonapp.change_abongroup', grp):
raise PermissionDenied
if request.method == 'POST':
tr = request.POST.getlist('tr')
# FIXME после создания метода привязки тарифов к группам убрать это представление
grp.tariffs.clear()
grp.tariffs.add(*[int(d) for d in tr])
grp.save()
tariffs = Tariff.objects.all()
return render(request, 'abonapp/group_tariffs.html', {
'abon_group': grp,
'group': grp,
'tariffs': tariffs
})
@ -567,7 +525,7 @@ def dev(request, gid, uid):
messages.error(request, _('Abon does not exist'))
return redirect('abonapp:people_list', gid=gid)
return render(request, 'abonapp/modal_dev.html', {
'devices': Device.objects.filter(user_group=gid),
'devices': Device.objects.filter(group=gid),
'dev': abon_dev,
'gid': gid, 'uid': uid
})
@ -575,7 +533,7 @@ def dev(request, gid, uid):
@login_required
@permission_required('abonapp.change_abon')
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
@permission_required('group_app.can_view_group', (Group, 'pk', 'gid'))
def clear_dev(request, gid, uid):
try:
abon = models.Abon.objects.get(pk=uid)
@ -589,7 +547,7 @@ def clear_dev(request, gid, uid):
@login_required
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
@permission_required('group_app.can_view_group', (Group, 'pk', 'gid'))
def charts(request, gid, uid):
high = 100
@ -603,9 +561,8 @@ def charts(request, gid, uid):
StatElem = getModel(wandate)
abon = models.Abon.objects.get(pk=uid)
if abon.group is None:
abon.group = models.AbonGroup.objects.get(pk=gid)
abon.group = Group.objects.get(pk=gid)
abon.save(update_fields=['group'])
abongroup = abon.group
if abon.ip_address is None:
charts_data = None
@ -626,7 +583,7 @@ def charts(request, gid, uid):
except models.Abon.DoesNotExist:
messages.error(request, _('Abon does not exist'))
return redirect('abonapp:people_list', gid)
except models.AbonGroup.DoesNotExist:
except Group.DoesNotExist:
messages.error(request, _("Group what you want doesn't exist"))
return redirect('abonapp:group_list')
except ProgrammingError as e:
@ -634,7 +591,7 @@ def charts(request, gid, uid):
return redirect('abonapp:abon_home', gid=gid, uid=uid)
return render(request, 'abonapp/charts.html', {
'abon_group': abongroup,
'group': abon.group,
'abon': abon,
'charts_data': ',\n'.join(charts_data) if charts_data is not None else None,
'high': high,
@ -664,7 +621,7 @@ def make_extra_field(request, gid, uid):
frm = forms.ExtraFieldForm()
except mydefs.MultipleException as errs:
for err in errs.err_list:
messages.add_message(request, messages.constants.ERROR, err)
messages.error(request, err)
frm = forms.ExtraFieldForm()
return render_to_text('abonapp/modal_extra_field.html', {
'abon': abon,
@ -749,7 +706,7 @@ class DialsListView(BaseAbonListView):
def get_queryset(self):
abon = get_object_or_404(models.Abon, pk=self.kwargs.get('uid'))
if not self.request.user.has_perm('abonapp.can_view_abongroup', abon.group):
if not self.request.user.has_perm('group_app.can_view_group', abon.group):
raise PermissionDenied
self.abon = abon
if abon.telephone is not None and abon.telephone != '':
@ -763,7 +720,7 @@ class DialsListView(BaseAbonListView):
def get_context_data(self, **kwargs):
context = super(DialsListView, self).get_context_data(**kwargs)
context['abon_group'] = get_object_or_404(models.AbonGroup, pk=self.kwargs.get('gid'))
context['group'] = get_object_or_404(Group, pk=self.kwargs.get('gid'))
context['abon'] = self.abon
return context
@ -772,6 +729,15 @@ class DialsListView(BaseAbonListView):
return redirect('abonapp:dials', self.abon.group.pk, self.abon.pk)
return super(DialsListView, self).render_to_response(context, **response_kwargs)
def get(self, request, *args, **kwargs):
try:
return super(DialsListView, self).get(request, *args, **kwargs)
except ProgrammingError as e:
messages.error(request, e)
return redirect('abonapp:abon_home',
self.kwargs.get('gid'),
self.kwargs.get('uid'))
@login_required
@permission_required('abonapp.change_abon')
@ -801,7 +767,7 @@ def save_user_dev_port(request, gid, uid):
pass
except models.Abon.MultipleObjectsReturned:
messages.error(request, _('Multiple users on the same device port'))
return redirect('devapp:manage_ports', abon.device.user_group.pk, abon.device.pk)
return redirect('devapp:manage_ports', abon.device.group.pk, abon.device.pk)
abon.dev_port = port
if abon.is_dynamic_ip != is_dynamic_ip:
@ -822,7 +788,7 @@ def save_user_dev_port(request, gid, uid):
@login_required
@permission_required('abonapp.add_abonstreet')
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
@permission_required('group_app.can_view_group', (Group, 'pk', 'gid'))
def street_add(request, gid):
if request.method == 'POST':
frm = forms.AbonStreetForm(request.POST)
@ -842,7 +808,7 @@ def street_add(request, gid):
@login_required
@permission_required('abonapp.change_abonstreet')
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
@permission_required('group_app.can_view_group', (Group, 'pk', 'gid'))
def street_edit(request, gid):
try:
if request.method == 'POST':
@ -867,7 +833,7 @@ def street_edit(request, gid):
@login_required
@permission_required('abonapp.delete_abonstreet')
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
@permission_required('group_app.can_view_group', (Group, 'pk', 'gid'))
def street_del(request, gid, sid):
try:
models.AbonStreet.objects.get(pk=sid, group=gid).delete()
@ -879,7 +845,7 @@ def street_del(request, gid, sid):
@login_required
@permission_required('abonapp.can_view_additionaltelephones')
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
@permission_required('group_app.can_view_group', (Group, 'pk', 'gid'))
def tels(request, gid, uid):
abon = get_object_or_404(models.Abon, pk=uid)
telephones = abon.additional_telephones.all()
@ -927,7 +893,7 @@ def tel_del(request, gid, uid):
@login_required
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
@permission_required('group_app.can_view_group', (Group, 'pk', 'gid'))
def phonebook(request, gid):
res_format = request.GET.get('f')
t1 = models.Abon.objects.filter(group__id=int(gid)).only('telephone', 'fio').values_list('telephone', 'fio')
@ -948,7 +914,7 @@ def phonebook(request, gid):
@login_required
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
@permission_required('group_app.can_view_group', (Group, 'pk', 'gid'))
def abon_export(request, gid):
res_format = request.GET.get('f')
@ -984,7 +950,7 @@ def abon_export(request, gid):
@login_required
@permission_required('abonapp.change_abon')
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
@permission_required('group_app.can_view_group', (Group, 'pk', 'gid'))
def reset_ip(request, gid, uid):
abon = get_object_or_404(models.Abon, pk=uid)
signals.post_save.disconnect(models.abon_post_save, sender=models.Abon)
@ -1016,7 +982,7 @@ def fin_report(request):
@login_required
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
@permission_required('group_app.can_view_group', (Group, 'pk', 'gid'))
def add_edit_periodic_pay(request, gid, uid, periodic_pay_id=0):
if periodic_pay_id == 0:
if not request.user.has_perm('abonapp.add_periodicpayforid'):
@ -1047,7 +1013,7 @@ def add_edit_periodic_pay(request, gid, uid, periodic_pay_id=0):
@login_required
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
@permission_required('group_app.can_view_group', (Group, 'pk', 'gid'))
@permission_required('abonapp.delete_periodicpayforid')
def del_periodic_pay(request, gid, uid, periodic_pay_id):
periodic_pay_instance = get_object_or_404(models.PeriodicPayForId, pk=periodic_pay_id)
@ -1078,12 +1044,12 @@ class EditSibscriberMarkers(UpdateView):
return context
def form_invalid(self, form):
messages.add_message(self.request, messages.ERROR, _('fix form errors'))
messages.error(self.request, _('fix form errors'))
return super(EditSibscriberMarkers, self).form_invalid(form)
def form_valid(self, form):
v = super(EditSibscriberMarkers, self).form_valid(form)
messages.add_message(self.request, messages.SUCCESS, _('User flags has changed successfully'))
messages.success(self.request, _('User flags has changed successfully'))
return v

63
accounts_app/migrations/0001_initial.py

@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2016-06-28 23:51
# Generated by Django 1.11 on 2018-02-26 00:20
from __future__ import unicode_literals
import django.core.validators
from django.db import migrations, models
@ -7,44 +8,58 @@ import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0007_alter_validators_add_error_messages'),
('auth', '0008_alter_user_username_max_length'),
('group_app', '0001_initial'),
('photo_app', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='UserProfile',
name='BaseAccount',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False,
help_text='Designates that this user has all permissions without explicitly assigning them.',
verbose_name='superuser status')),
('username', models.CharField(max_length=127, unique=True)),
('fio', models.CharField(max_length=256)),
('birth_day', models.DateField(auto_now_add=True)),
('is_active', models.BooleanField(default=True)),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('username', models.CharField(max_length=127, unique=True, verbose_name='profile username')),
('fio', models.CharField(max_length=256, verbose_name='fio')),
('birth_day', models.DateField(auto_now_add=True, verbose_name='birth day')),
('is_active', models.BooleanField(default=True, verbose_name='Is active')),
('is_admin', models.BooleanField(default=False)),
('telephone', models.CharField(max_length=16, unique=True, validators=[
django.core.validators.RegexValidator(r'^\\+[7,8,9,3]\\d{10,11}$')],
verbose_name='Telephone number')),
('skype', models.CharField(blank=True, max_length=20)),
('avatar', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE,
to='photo_app.Photo')),
('groups', models.ManyToManyField(blank=True,
help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.',
related_name='user_set', related_query_name='user', to='auth.Group',
verbose_name='groups')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.',
related_name='user_set', related_query_name='user',
to='auth.Permission', verbose_name='user permissions')),
('telephone', models.CharField(max_length=16, validators=[django.core.validators.RegexValidator('^\\+[7,8,9,3]\\d{10,11}$')], verbose_name='Telephone')),
],
options={
'abstract': False,
'db_table': 'base_accounts',
},
),
migrations.CreateModel(
name='UserProfile',
fields=[
('baseaccount_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='accounts_app.BaseAccount')),
('email', models.EmailField(default='admin@example.ru', max_length=254)),
('avatar', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='photo_app.Photo')),
('responsibility_groups', models.ManyToManyField(blank=True, to='group_app.Group', verbose_name='Responsibility groups')),
],
options={
'verbose_name': 'Staff account profile',
'verbose_name_plural': 'Staff account profiles',
'ordering': ['fio'],
'permissions': (('can_view_userprofile', 'Can view staff profile'),),
},
bases=('accounts_app.baseaccount',),
),
migrations.AddField(
model_name='baseaccount',
name='groups',
field=models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups'),
),
migrations.AddField(
model_name='baseaccount',
name='user_permissions',
field=models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions'),
),
]

20
accounts_app/migrations/0002_userprofile_email.py

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2016-11-30 15:15
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts_app', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='userprofile',
name='email',
field=models.EmailField(default='ex@host.loc', max_length=254),
preserve_default=False,
),
]

25
accounts_app/migrations/0003_auto_20161206_2135.py

@ -1,25 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2016-12-06 18:35
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts_app', '0002_userprofile_email'),
]
operations = [
migrations.RemoveField(
model_name='userprofile',
name='skype',
),
migrations.AlterField(
model_name='userprofile',
name='telephone',
field=models.CharField(max_length=16,
validators=[django.core.validators.RegexValidator('^\\+[7,8,9,3]\\d{10,11}$')],
verbose_name='Telephone number'),
),
]

18
accounts_app/migrations/0004_auto_20170128_1316.py

@ -1,18 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-01-28 10:16
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts_app', '0003_auto_20161206_2135'),
]
operations = [
migrations.AlterField(
model_name='userprofile',
name='email',
field=models.EmailField(default='admin@example.ru', max_length=254),
),
]

21
accounts_app/migrations/0005_auto_20170222_2224.py

@ -1,21 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-02-22 19:24
from __future__ import unicode_literals
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts_app', '0004_auto_20170128_1316'),
]
operations = [
migrations.AlterField(
model_name='userprofile',
name='telephone',
field=models.CharField(max_length=16, validators=[django.core.validators.RegexValidator('^\\+[7,8,9,3]\\d{10,11}$')], verbose_name='Номер телефона'),
),
]

21
accounts_app/migrations/0006_auto_20170416_1029.py

@ -1,21 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-04-16 07:29
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('accounts_app', '0005_auto_20170222_2224'),
]
operations = [
migrations.AlterField(
model_name='userprofile',
name='avatar',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='photo_app.Photo'),
),
]

21
accounts_app/migrations/0007_auto_20170816_1109.py

@ -1,21 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-08-16 11:09
from __future__ import unicode_literals
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts_app', '0006_auto_20170416_1029'),
]
operations = [
migrations.AlterField(
model_name='userprofile',
name='telephone',
field=models.CharField(max_length=16, validators=[django.core.validators.RegexValidator('^\\+[7,8,9,3]\\d{10,11}$')], verbose_name='Телефон'),
),
]

19
accounts_app/migrations/0008_auto_20170927_1838.py

@ -1,19 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-09-27 18:38
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('accounts_app', '0007_auto_20170816_1109'),
]
operations = [
migrations.AlterModelOptions(
name='userprofile',
options={'permissions': (('can_view_userprofile', 'Может просматривать учётку сотрудника'),), 'verbose_name': 'Учётная запись работника', 'verbose_name_plural': 'Учётные записи работников'},
),
]

28
accounts_app/models.py

@ -6,6 +6,7 @@ from django.core.validators import RegexValidator
from django.utils.translation import gettext_lazy as _
from django.conf import settings
from photo_app.models import Photo
from group_app.models import Group
DEFAULT_PICTURE = getattr(settings, 'DEFAULT_PICTURE', '/static/img/user_ava.gif')
@ -45,7 +46,7 @@ class MyUserManager(BaseUserManager):
return user
class UserProfile(AbstractBaseUser, PermissionsMixin):
class BaseAccount(AbstractBaseUser, PermissionsMixin):
username = models.CharField(_('profile username'), max_length=127, unique=True)
fio = models.CharField(_('fio'), max_length=256)
birth_day = models.DateField(_('birth day'), auto_now_add=True)
@ -57,8 +58,6 @@ class UserProfile(AbstractBaseUser, PermissionsMixin):
#unique=True,
validators=[RegexValidator(TELEPHONE_REGEXP)]
)
avatar = models.ForeignKey(Photo, null=True, blank=True, on_delete=models.SET_NULL)
email = models.EmailField(default='admin@example.ru')
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['telephone']
@ -78,6 +77,26 @@ class UserProfile(AbstractBaseUser, PermissionsMixin):
# Simplest possible answer: All admins are staff
return self.is_admin
def __str__(self):
return self.get_full_name()
class Meta:
db_table = 'base_accounts'
class UserProfileManager(MyUserManager):
def get_profiles_by_group(self, group_id):
return self.filter(responsibility_groups__id__in=[group_id], is_admin=True, is_active=True)
class UserProfile(BaseAccount):
avatar = models.ForeignKey(Photo, null=True, blank=True, on_delete=models.SET_NULL)
email = models.EmailField(default='admin@example.ru')
responsibility_groups = models.ManyToManyField(Group, blank=True, verbose_name=_('Responsibility groups'))
objects = UserProfileManager()
def get_big_ava(self):
if self.avatar:
path = self.avatar.big()
@ -99,9 +118,6 @@ class UserProfile(AbstractBaseUser, PermissionsMixin):
else:
return DEFAULT_PICTURE
def __str__(self):
return self.get_full_name()
class Meta:
permissions = (
('can_view_userprofile', _('Can view staff profile')),

1
accounts_app/templates/accounts/create_acc.html

@ -1,4 +1,5 @@
{% extends request.is_ajax|yesno:'bajax.html,base.html' %}
{% load i18n %}
{% block main %}
<ol class="breadcrumb">

3
accounts_app/templates/accounts/profile_chgroup.html

@ -4,9 +4,10 @@
<legend>{% trans 'The responsibility of the staff of the group of subscribers' %}</legend>
<form action="{% url 'acc_app:profile_setup_group' userprofile.id %}" method="post" role="form">{% csrf_token %}
{% for ag in abongroups %}
{% for ag in groups %}
<div class="checkbox">
<label>
{# FIXME После реализации метода возвращающего связи групп с профилями применить его тут #}
{% if userprofile in ag.profiles.all %}
<input name="ag" type="checkbox" value="{{ ag.pk }}" checked/>
{% else %}

10
accounts_app/templates/accounts/set_abon_groups_permission.html

@ -4,15 +4,15 @@
<legend>{% trans 'The list of user groups to which the account has access' %}</legend>
<form action="{% url 'acc_app:set_abon_groups_permission' userprofile.pk %}" method="post" role="form">{% csrf_token %}
{% for ag in abongroups %}
{% for grp in groups %}
<div class="checkbox">
<label>
{% if ag.pk in picked_groups_ids %}
<input name="ag" type="checkbox" value="{{ ag.pk }}" checked/>
{% if grp.pk in picked_groups_ids %}
<input name="grp" type="checkbox" value="{{ grp.pk }}" checked/>
{% else %}
<input name="ag" type="checkbox" value="{{ ag.pk }}"/>
<input name="grp" type="checkbox" value="{{ grp.pk }}"/>
{% endif %}
{{ ag.title }}
{{ grp.title }}
</label>
</div>
{% endfor %}

26
accounts_app/views.py

@ -10,7 +10,7 @@ from django.utils.translation import ugettext as _
from django.views.generic import ListView
from django.conf import settings
from abonapp.models import AbonGroup
from group_app.models import Group
from photo_app.models import Photo
from .models import UserProfile
@ -104,11 +104,11 @@ def chgroup(request, uid):
usr.abon_groups.clear()
usr.abon_groups.add(*[int(d) for d in ag])
usr.save()
abongroups = AbonGroup.objects.only('pk', 'title')
groups = Group.objects.only('pk', 'title')
return render(request, 'accounts/profile_chgroup.html', {
'uid': uid,
'userprofile': usr,
'abongroups': abongroups
'groups': groups
})
@ -234,7 +234,7 @@ def perms(request, uid):
raise PermissionDenied
userprofile = get_object_or_404(UserProfile, id=uid)
klasses = (
'abonapp.AbonGroup', 'abonapp.Abon', 'accounts_app.UserProfile',
'abonapp.Abon', 'accounts_app.UserProfile',
'abonapp.AbonTariff', 'abonapp.AbonStreet', 'devapp.Device',
'abonapp.PassportInfo', 'abonapp.AdditionalTelephone'
)
@ -303,22 +303,22 @@ def set_abon_groups_permission(request, uid):
raise PermissionDenied
userprofile = get_object_or_404(UserProfile, pk=uid)
picked_groups = get_objects_for_user(userprofile, 'abonapp.can_view_abongroup', accept_global_perms=False)
picked_groups = get_objects_for_user(userprofile, 'group_app.can_view_group', accept_global_perms=False)
picked_groups = picked_groups.values_list('pk', flat=True)
if request.method == 'POST':
checked_groups = [int(ag) for ag in request.POST.getlist('ag', default=0)]
for abon_group in AbonGroup.objects.all():
if abon_group.pk in checked_groups and abon_group.pk not in picked_groups:
assign_perm('abonapp.can_view_abongroup', userprofile, obj=abon_group)
elif abon_group.pk not in checked_groups and abon_group.pk in picked_groups:
remove_perm('abonapp.can_view_abongroup', userprofile, obj=abon_group)
checked_groups = [int(ag) for ag in request.POST.getlist('grp', default=0)]
for grp in Group.objects.all():
if grp.pk in checked_groups and grp.pk not in picked_groups:
assign_perm('groupapp.can_view_group', userprofile, obj=grp)
elif grp.pk not in checked_groups and grp.pk in picked_groups:
remove_perm('groupapp.can_view_group', userprofile, obj=grp)
return redirect('acc_app:set_abon_groups_permission', uid)
abongroups = AbonGroup.objects.only('pk', 'title')
groups = Group.objects.only('pk', 'title')
return render(request, 'accounts/set_abon_groups_permission.html', {
'uid': uid,
'userprofile': userprofile,
'abongroups': abongroups,
'groups': groups,
'picked_groups_ids': picked_groups
})

14
agent/commands/dhcp.py

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
from django.core.exceptions import MultipleObjectsReturned
from django.utils.translation import ugettext as _
from abonapp.models import Abon
from devapp.models import Device, Port
@ -16,7 +15,7 @@ def dhcp_commit(client_ip, client_mac, switch_mac, switch_port):
else:
abon = Abon.objects.get(device=dev)
if not abon.is_dynamic_ip:
print('D:', _('User settings is not dynamic'))
print('D:', 'User settings is not dynamic')
return
if not abon.is_access():
print('D:', 'User %s is not access to service' % abon.username)
@ -24,13 +23,16 @@ def dhcp_commit(client_ip, client_mac, switch_mac, switch_port):
abon.ip_address = client_ip
abon.is_dhcp = True
abon.save(update_fields=['ip_address'])
#print('S:', _("Ip address:'%s' update for '%s' successfull, on port: %s") % (client_ip, abon.get_short_name(), port))
# print('S:', _("Ip address:'%s' update for '%s' successfull, on port: %s") % (client_ip, abon.get_short_name(), port))
except Abon.DoesNotExist:
print('N:', _("User with device '%s' does not exist") % dev)
print('N:', "User with device '%s' does not exist" % dev)
except Device.DoesNotExist:
print('N:', _('Device with mac %s not found') % switch_mac)
print('N:', 'Device with mac %s not found' % switch_mac)
except Port.DoesNotExist:
print('N:', _('Port %d on device with mac %s does not exist') % (int(switch_port), switch_mac))
print('N:', 'Port %(switch_port)d on device with mac %(switch_mac)s does not exist' % {
'switch_port': int(switch_port),
'switch_mac': switch_mac
})
except MultipleObjectsReturned as e:
print('E:', 'MultipleObjectsReturned:', type(e), e, port, dev)

32
chatbot/migrations/0001_initial.py

@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-01-15 20:55
# Generated by Django 1.11 on 2018-02-26 00:20
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
@ -23,13 +24,38 @@ class Migration(migrations.Migration):
('date_sent', models.DateTimeField(auto_now_add=True)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'Message history',
'verbose_name_plural': 'Message histories',
'db_table': 'chat_message_history',
},
),
migrations.CreateModel(
name='MessageQueue',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('message', models.CharField(max_length=255, verbose_name='Message')),
('status', models.CharField(choices=[('n', 'New'), ('r', 'Read')], default='n', max_length=1, verbose_name='Status of message')),
('tag', models.CharField(default='none', max_length=6, verbose_name='App tag')),
('target_employee', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Target employee')),
],
options={
'verbose_name': 'Message queue',
'verbose_name_plural': 'Message queue',
'db_table': 'chat_message_queue',
},
),
migrations.CreateModel(
name='TelegramBot',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('chat_id', models.PositiveIntegerField(default=0)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
('chat_id', models.PositiveIntegerField(default=0, verbose_name='Telegram chat id')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Employee')),
],
options={
'verbose_name': 'Telegram bot',
'verbose_name_plural': 'Telegram bots',
'db_table': 'chat_telegram_bot',
},
),
]

59
chatbot/migrations/0002_auto_20171214_1517.py

@ -1,59 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-12-14 15:17
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('chatbot', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='MessageQueue',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('message', models.CharField(max_length=255, verbose_name='Message')),
('status', models.CharField(choices=[('n', 'New'), ('r', 'Read')], default='n', max_length=1, verbose_name='Status of message')),
('tag', models.CharField(default='none', max_length=6, verbose_name='App tag')),
('target_employee', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Target employee')),
],
options={
'verbose_name': 'Message queue',
'verbose_name_plural': 'Message queue',
'db_table': 'chat_message_queue',
},
),
migrations.AlterModelOptions(
name='messagehistory',
options={'verbose_name': 'Message history', 'verbose_name_plural': 'Message histories'},
),
migrations.AlterModelOptions(
name='telegrambot',
options={'verbose_name': 'Telegram bot', 'verbose_name_plural': 'Telegram bots'},
),
migrations.AlterField(
model_name='telegrambot',
name='chat_id',
field=models.PositiveIntegerField(default=0, verbose_name='Telegram chat id'),
),
migrations.AlterField(
model_name='telegrambot',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Employee'),
),
migrations.AlterModelTable(
name='messagehistory',
table='chat_message_history',
),
migrations.AlterModelTable(
name='telegrambot',
table='chat_telegram_bot',
),
]

4
clientsideapp/views.py

@ -29,9 +29,9 @@ def pays(request):
def services(request):
try:
abon = Abon.objects.get(pk=request.user.pk)
all_tarifs = abon.group.tariffs.filter(is_admin=False)
all_tarifs = Tariff.objects.get_tariffs_by_group(abon.group.pk)
current_service = abon.active_tariff()
except:
except Abon.DoesNotExist:
all_tarifs = None
current_service = None
return render(request, 'clientsideapp/services.html', {

5
devapp/forms.py

@ -28,10 +28,7 @@ class DeviceForm(forms.ModelForm):
'comment': forms.TextInput(attrs={
'required': True
}),
'man_passw': forms.PasswordInput(render_value=True),
'user_group': forms.Select(attrs={
'class': 'form-control'
})
'man_passw': forms.PasswordInput(render_value=True)
}

4
devapp/locale/ru/LC_MESSAGES/django.po

@ -411,7 +411,7 @@ msgid "You have redirected to existing device"
msgstr "Вы были переадресованы на существующее устройство"
#: views.py:113 views.py:329 views.py:419
msgid "Please attach user group for device"
msgid "Please attach group for device"
msgstr "Пожалуйста назначте устройству группу в настройках"
#: views.py:117 views.py:275 views.py:304 views.py:421
@ -424,7 +424,7 @@ msgid "Duplicate user and port: %s"
msgstr "Пользователь с таким портом и устройством уже есть: %s"
#: views.py:159 views.py:198
msgid "Device is not have a group, please fix that"
msgid "Device does not have a group, please fix that"
msgstr "У устройства нет группы, пожалуйста, исправьте это"
#: views.py:164 views.py:231 views.py:316

62
devapp/migrations/0001_initial.py

@ -0,0 +1,62 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2018-02-26 00:20
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import djing.fields
import mydefs
class Migration(migrations.Migration):
initial = True
dependencies = [
('group_app', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Device',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('ip_address', mydefs.MyGenericIPAddressField(max_length=8, protocol='ipv4', verbose_name='Ip address')),
('mac_addr', djing.fields.MACAddressField(blank=True, integer=True, null=True, unique=True, verbose_name='Mac address')),
('comment', models.CharField(max_length=256, verbose_name='Comment')),
('devtype', models.CharField(choices=[('Dl', 'DLink switch'), ('Pn', 'PON OLT'), ('On', 'PON ONU'), ('Ex', 'Eltex switch')], default='Dl', max_length=2, verbose_name='Device type')),
('man_passw', models.CharField(blank=True, max_length=16, null=True, verbose_name='SNMP password')),
('snmp_item_num', models.PositiveSmallIntegerField(blank=True, default=0, verbose_name='SNMP Number')),
('status', models.CharField(choices=[('und', 'Undefined'), ('up', 'Up'), ('unr', 'Unreachable'), ('dwn', 'Down')], default='und', max_length=3, verbose_name='Status')),
('is_noticeable', models.BooleanField(default=False, verbose_name='Send notify when monitoring state changed')),
('group', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='group_app.Group', verbose_name='Device group')),
('parent_dev', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='devapp.Device', verbose_name='Parent device')),
],
options={
'verbose_name': 'Device',
'verbose_name_plural': 'Devices',
'db_table': 'dev',
'ordering': ['comment'],
'permissions': (('can_view_device', 'Can view device'),),
},
),
migrations.CreateModel(
name='Port',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('num', models.PositiveSmallIntegerField(default=0, verbose_name='Number')),
('descr', models.CharField(blank=True, max_length=60, null=True, verbose_name='Description')),
('device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='devapp.Device', verbose_name='Device')),
],
options={
'verbose_name': 'Port',
'verbose_name_plural': 'Ports',
'db_table': 'dev_port',
'permissions': (('can_toggle_ports', 'Can toggle ports'),),
},
),
migrations.AlterUniqueTogether(
name='port',
unique_together=set([('device', 'num')]),
),
]

90
devapp/migrations/0001_squashed_0007_auto_20170816_1109.py

@ -1,90 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-09-04 16:14
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import djing.fields
import mydefs
class Migration(migrations.Migration):
initial = True
dependencies = [
('mapapp', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Device',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('ip_address', mydefs.MyGenericIPAddressField(max_length=8, protocol='ipv4')),
('comment', models.CharField(max_length=256)),
('devtype', models.CharField(choices=[('Dl', "Свич D'Link")], default='Dl', max_length=2)),
('man_passw', models.CharField(blank=True, max_length=16, null=True)),
],
),
migrations.CreateModel(
name='Port',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('num', models.PositiveSmallIntegerField(default=0)),
('speed', models.CharField(choices=[('h', '100Mbps'), ('k', '1Gbps'), ('d', '10Gbps')], default='h', max_length=1)),
('device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='devapp.Device')),
],
),
migrations.AlterUniqueTogether(
name='port',
unique_together=set([('device', 'num')]),
),
migrations.AlterModelTable(
name='device',
table='dev',
),
migrations.AlterModelTable(
name='port',
table='dev_port',
),
migrations.AddField(
model_name='device',
name='map_dot',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='mapapp.Dot'),
),
migrations.AlterField(
model_name='device',
name='devtype',
field=models.CharField(choices=[('Dl', 'DLink switch'), ('Pn', 'PON OLT')], default='Dl', max_length=2),
),
migrations.RemoveField(
model_name='port',
name='speed',
),
migrations.AddField(
model_name='device',
name='mac_addr',
field=djing.fields.MACAddressField(blank=True, integer=True, null=True, unique=True),
),
migrations.AddField(
model_name='device',
name='parent_dev',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='devapp.Device'),
),
migrations.AddField(
model_name='port',
name='descr',
field=models.CharField(blank=True, max_length=60, null=True),
),
migrations.AlterField(
model_name='device',
name='devtype',
field=models.CharField(choices=[('Dl', 'DLink switch'), ('Pn', 'PON OLT'), ('On', 'PON ONU')], default='Dl', max_length=2),
),
migrations.AlterField(
model_name='device',
name='devtype',
field=models.CharField(choices=[('Dl', 'DLink switch'), ('Pn', 'PON OLT'), ('On', 'PON ONU'), ('Ex', 'Eltex switch')], default='Dl', max_length=2),
),
]

22
devapp/migrations/0002_device_user_group.py

@ -1,22 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-09-04 16:16
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0001_squashed_0022_auto_20170816_1109'),
('devapp', '0001_squashed_0007_auto_20170816_1109'),
]
operations = [
migrations.AddField(
model_name='device',
name='user_group',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='abonapp.AbonGroup'),
),
]

23
devapp/migrations/0003_auto_20170927_1838.py

@ -1,23 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-09-27 18:38
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('devapp', '0002_device_user_group'),
]
operations = [
migrations.AlterModelOptions(
name='device',
options={'permissions': (('can_view_device', 'Can view device'),), 'verbose_name': 'Device', 'verbose_name_plural': 'Devices'},
),
migrations.AlterModelOptions(
name='port',
options={'permissions': (('can_toggle_ports', 'Can toggle ports'),), 'verbose_name': 'Port', 'verbose_name_plural': 'Ports'},
),
]

72
devapp/migrations/0004_auto_20171103_0006.py

@ -1,72 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-11-03 00:06
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import djing.fields
import mydefs
class Migration(migrations.Migration):
dependencies = [
('devapp', '0003_auto_20170927_1838'),
]
operations = [
migrations.RemoveField(
model_name='device',
name='map_dot',
),
migrations.AlterField(
model_name='device',
name='comment',
field=models.CharField(max_length=256, verbose_name='Comment'),
),
migrations.AlterField(
model_name='device',
name='devtype',
field=models.CharField(choices=[('Dl', 'DLink switch'), ('Pn', 'PON OLT'), ('On', 'PON ONU'), ('Ex', 'Eltex switch')], default='Dl', max_length=2, verbose_name='Device type'),
),
migrations.AlterField(
model_name='device',
name='ip_address',
field=mydefs.MyGenericIPAddressField(max_length=8, protocol='ipv4', verbose_name='Ip address'),
),
migrations.AlterField(
model_name='device',
name='mac_addr',
field=djing.fields.MACAddressField(blank=True, integer=True, null=True, unique=True, verbose_name='Mac address'),
),
migrations.AlterField(
model_name='device',
name='man_passw',
field=models.CharField(blank=True, max_length=16, null=True, verbose_name='SNMP password'),
),
migrations.AlterField(
model_name='device',
name='parent_dev',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='devapp.Device', verbose_name='Parent device'),
),
migrations.AlterField(
model_name='device',
name='user_group',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='abonapp.AbonGroup', verbose_name='User group'),
),
migrations.AlterField(
model_name='port',
name='descr',
field=models.CharField(blank=True, max_length=60, null=True, verbose_name='Description'),
),
migrations.AlterField(
model_name='port',
name='device',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='devapp.Device', verbose_name='Device'),
),
migrations.AlterField(
model_name='port',
name='num',
field=models.PositiveSmallIntegerField(default=0, verbose_name='Number'),
),
]

20
devapp/migrations/0005_device_snmp_item_num.py

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-11-07 16:19
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('devapp', '0004_auto_20171103_0006'),
]
operations = [
migrations.AddField(
model_name='device',
name='snmp_item_num',
field=models.PositiveSmallIntegerField(default=0),
),
]

34
devapp/migrations/0006_auto_20180129_1625.py

@ -1,34 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2018-01-29 16:25
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('devapp', '0005_device_snmp_item_num'),
]
operations = [
migrations.AlterModelOptions(
name='device',
options={'ordering': ['comment'], 'permissions': (('can_view_device', 'Can view device'),), 'verbose_name': 'Device', 'verbose_name_plural': 'Devices'},
),
migrations.AddField(
model_name='device',
name='is_noticeable',
field=models.BooleanField(default=False, verbose_name='Send notify when monitoring state changed'),
),
migrations.AddField(
model_name='device',
name='status',
field=models.CharField(choices=[('und', 'Undefined'), ('up', 'Up'), ('unr', 'Unreachable'), ('dwn', 'Down')], default='und', max_length=3, verbose_name='Status'),
),
migrations.AlterField(
model_name='device',
name='snmp_item_num',
field=models.PositiveSmallIntegerField(blank=True, default=0, verbose_name='SNMP Number'),
),
]

4
devapp/models.py

@ -9,6 +9,7 @@ from subprocess import run
from django.conf import settings
from django.utils.translation import gettext_lazy as _
from json.decoder import JSONDecodeError
from group_app.models import Group
DEVICE_TYPES = (
@ -51,7 +52,7 @@ class Device(models.Model):
comment = models.CharField(_('Comment'), max_length=256)
devtype = models.CharField(_('Device type'), max_length=2, default=DEVICE_TYPES[0][0], choices=MyChoicesAdapter(DEVICE_TYPES))
man_passw = models.CharField(_('SNMP password'), max_length=16, null=True, blank=True)
user_group = models.ForeignKey('abonapp.AbonGroup', verbose_name=_('User group'), on_delete=models.SET_NULL, null=True, blank=True)
group = models.ForeignKey(Group, on_delete=models.SET_NULL, null=True, blank=True, verbose_name=_('Device group'))
parent_dev = models.ForeignKey('self', verbose_name=_('Parent device'), blank=True, null=True, on_delete=models.SET_NULL)
snmp_item_num = models.PositiveSmallIntegerField(_('SNMP Number'), default=0, blank=True)
@ -106,6 +107,7 @@ class Device(models.Model):
def update_dhcp(self):
if self.devtype not in ('On','Dl'):
return
# FIXME: переделать это безобразие
grp = self.user_group.id
code = ''
if grp == 87:

2
devapp/templates/devapp/add_dev.html

@ -40,7 +40,7 @@
{% bootstrap_field form.man_passw addon_before=ic %}
{% bootstrap_icon 'subscript' as ic %}
{% bootstrap_field form.user_group addon_before=ic %}
{% bootstrap_field form.group addon_before=ic %}
<div class="form-group">
<label for="id_parent_dev">{% trans 'Parent device' %}</label>

2
devapp/templates/devapp/custom_dev_page/olt.html

@ -23,7 +23,7 @@
</thead>
<tbody>
{% with dip=dev.ip_address grp=dev.user_group.pk %}
{% with dip=dev.ip_address grp=dev.group.pk %}
{% for port in ports %}
<tr>
<td>{% if port.st %}<span class="glyphicon glyphicon-ok text-success"></span>

2
devapp/templates/devapp/custom_dev_page/onu.html

@ -30,7 +30,7 @@
{% endfor %}
{% if dev.parent_dev %}
<li class="list-group-item">
{% with pdev=dev.parent_dev pdgrp=dev.parent_dev.user_group %}
{% with pdev=dev.parent_dev pdgrp=dev.parent_dev.group %}
{% trans 'Parent device' %}:<a href="{% url 'devapp:view' pdgrp.pk pdev.pk %}"
title="{{ pdev.mac_addr|default:'' }}"
target="_blank">{{ pdev.ip_address }} {{ pdev.comment }}</a>

4
devapp/templates/devapp/custom_dev_page/ports.html

@ -41,11 +41,11 @@
<b>{{ port.num }}</b>
</a>
{% if port.st %}
<a href="{% url 'devapp:port_toggle' dev.user_group.pk|default:0 dev.id port.num 0 %}" class="btn btn-xs btn-danger" title="{% trans 'Disable port' %}">
<a href="{% url 'devapp:port_toggle' dev.group.pk|default:0 dev.id port.num 0 %}" class="btn btn-xs btn-danger" title="{% trans 'Disable port' %}">
<span class="glyphicon glyphicon-off"></span>
</a>
{% else %}
<a href="{% url 'devapp:port_toggle' dev.user_group.pk|default:0 dev.id port.num 1 %}" class="btn btn-xs btn-success" title="{% trans 'Enable port' %}">
<a href="{% url 'devapp:port_toggle' dev.group.pk|default:0 dev.id port.num 1 %}" class="btn btn-xs btn-success" title="{% trans 'Enable port' %}">
<span class="glyphicon glyphicon-ok"></span>
</a>
{% endif %}

2
devapp/templates/devapp/dev.html

@ -27,7 +27,7 @@
{% bootstrap_field form.man_passw addon_before=ic %}
{% bootstrap_icon 'subscript' as ic %}
{% bootstrap_field form.user_group addon_before=ic %}
{% bootstrap_field form.group addon_before=ic %}
<div class="form-group">
<label for="id_parent_dev">{% trans 'Parent device' %}</label>

8
devapp/templates/devapp/devices.html

@ -41,7 +41,7 @@
</thead>
<tbody>
{% with can_del_dev=perms.devapp.delete_device can_ch_dev=perms.devapp.change_device %}
{% with can_del_dev=perms.devapp.delete_device can_ch_dev=perms.devapp.change_device grpid=dev.group.pk %}
{% for dev in devices %}
<tr>
@ -57,19 +57,19 @@
{% endif %}
{% endif %}
</td>
<td><a href="{% url 'devapp:view' dev.user_group.pk dev.pk %}">{{ dev.ip_address }}</a></td>
<td><a href="{% url 'devapp:view' grpid dev.pk %}">{{ dev.ip_address }}</a></td>
<td>{{ dev.comment }}</td>
<td>{{ dev.mac_addr|default:_('Not assigned') }}</td>
{# <td class="hidden-xs hidden-sm">{{ dev.mon.plugin_output|default:'&ndash;' }}</td> #}
<td>{{ dev.get_devtype_display }}</td>
<td class="btn-group btn-group-xs btn-group-justified">
{% if can_del_dev %}
<a href="{% url 'devapp:del' dev.user_group.pk dev.pk %}" class="btn btn-danger">
<a href="{% url 'devapp:del' grpid dev.pk %}" class="btn btn-danger">
<span class="glyphicon glyphicon-remove"></span>
</a>
{% endif %}
{% if can_ch_dev %}
<a href="{% url 'devapp:edit' dev.user_group.pk dev.id %}" class="btn btn-default">
<a href="{% url 'devapp:edit' grpid dev.id %}" class="btn btn-default">
<span class="glyphicon glyphicon-edit"></span>
</a>
{% endif %}

6
devapp/templates/devapp/devices_null_group.html

@ -41,17 +41,17 @@
{% with can_del_dev=perms.devapp.delete_device can_change_dev=perms.devapp.change_device %}
{% for dev in devices %}
<tr>
<td><a href="{% url 'devapp:view' dev.user_group.pk|default:0 dev.pk %}">{{ dev.ip_address }}</a></td>
<td><a href="{% url 'devapp:view' 0 dev.pk %}">{{ dev.ip_address }}</a></td>
<td>{{ dev.comment }}</td>
<td>{{ dev.get_devtype_display }}</td>
<td class="btn-group btn-group-sm">
{% if can_del_dev %}
<a href="{% url 'devapp:del' dev.user_group.pk|default:0 dev.pk %}" class="btn btn-danger btn-sm">
<a href="{% url 'devapp:del' 0 dev.pk %}" class="btn btn-danger btn-sm">
<span class="glyphicon glyphicon-remove"></span>
</a>
{% endif %}
{% if can_change_dev %}
<a href="{% url 'devapp:edit' dev.user_group.pk|default:0 dev.pk %}" class="btn btn-default btn-sm">
<a href="{% url 'devapp:edit' 0 dev.pk %}" class="btn btn-default btn-sm">
<span class="glyphicon glyphicon-edit"></span>
</a>
{% endif %}

10
devapp/templates/devapp/ext.htm

@ -5,8 +5,8 @@
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'devapp:group_list' %}">{% trans 'Groups' %}</a></li>
{% if dev.user_group %}
<li><a href="{% url 'devapp:devs' dev.user_group.pk %}">{{ dev.user_group.title }}</a></li>
{% if dev.group %}
<li><a href="{% url 'devapp:devs' dev.group.pk %}">{{ dev.group.title }}</a></li>
{% else %}
<li>{% trans 'Not assigned' %}</li>
{% endif %}
@ -21,7 +21,7 @@
<ul class="nav nav-tabs">
{% url 'devapp:view' dev.user_group.pk|default:0 dev.pk as devapp_view %}
{% url 'devapp:view' dev.group.pk|default:0 dev.pk as devapp_view %}
<li{% if devapp_view == request.path %} class="active"{% endif %}>
<a href="{{ devapp_view }}">
{% trans 'Ports' %} {{ dev.ip_address }}
@ -29,12 +29,12 @@
</li>
{% if perms.devapp.change_device %}
{% url 'devapp:edit' dev.user_group.pk|default:0 dev.pk as devapp_edit %}
{% url 'devapp:edit' dev.group.pk|default:0 dev.pk as devapp_edit %}
<li{% if devapp_edit == request.path %} class="active"{% endif %}>
<a href="{{ devapp_edit }}">{% trans 'Edit' %}</a>
</li>
{% url 'devapp:manage_ports' dev.user_group.pk|default:0 dev.pk as devapp_mports %}
{% url 'devapp:manage_ports' dev.group.pk|default:0 dev.pk as devapp_mports %}
<li{% if devapp_mports == request.path %} class="active"{% endif %}>
<a href="{{ devapp_mports }}">{% trans 'Ports' %}</a>
</li>

6
devapp/templates/devapp/fix_dev_group.html

@ -36,12 +36,12 @@
{% bootstrap_field form.man_passw addon_before=ic %}
<div class="form-group">
<label class="control-label" for="{{ form.user_group.id_for_label }}">{{ form.user_group.label }}</label>
<div class="input-group{% if not dev.user_group %} has-error{% endif %}">
<label class="control-label" for="{{ form.group.id_for_label }}">{{ form.group.label }}</label>
<div class="input-group{% if not dev.group %} has-error{% endif %}">
<span class="input-group-addon">
{% bootstrap_icon 'subscript' %}
</span>
{{ form.user_group }}
{{ form.group }}
</div>
</div>

19
devapp/templates/devapp/group_list.html

@ -7,17 +7,13 @@
<li class="active">{% trans 'Groups' %}</li>
</ol>
<h3>{% trans 'Groups' %}</h3>
{% include 'message_block.html' %}
<div class="table-responsive">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans 'Group title' %}</h3>
</div>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>{% trans 'Group title' %}</th>
</tr>
</thead>
<tbody>
{% for gr in groups %}
<tr>
@ -31,12 +27,7 @@
</tbody>
<tfoot>
<tr>
<td class="btn-group">
{% if perms.abonapp.add_abongroup %}
<a href="{% url 'abonapp:add_group' %}" class="btn btn-success btn-sm">
<span class="glyphicon glyphicon-plus"></span> <span class="hidden-xs">{% trans 'Add group' %}</span>
</a>
{% endif %}
<td>
<a href="{% url 'devapp:devices_null_group' %}" class="btn btn-primary btn-sm">
<span class="glyphicon glyphicon-list-alt"></span> {% trans 'Devices without group' %}
</a>

8
devapp/templates/devapp/manage_ports/add_ports.html

@ -5,8 +5,8 @@
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'devapp:group_list' %}">{% trans 'Groups' %}</a></li>
<li><a href="{% url 'devapp:devs' dev.user_group.pk %}">{{ dev.user_group.title }}</a></li>
<li><a href="{% url 'devapp:view' dev.user_group.pk dev.pk %}">{{ dev.comment }}</a></li>
<li><a href="{% url 'devapp:devs' dev.group.pk %}">{{ dev.group.title }}</a></li>
<li><a href="{% url 'devapp:view' dev.group.pk dev.pk %}">{{ dev.comment }}</a></li>
<li class="active">{% trans 'Add ports' %}</li>
</ol>
@ -22,7 +22,7 @@
</div>
<div class="panel-body">
<form class="table-responsive" role="form" action="{% url 'devapp:add_ports' dev.user_group.pk dev.pk %}" method="post">{% csrf_token %}
<form class="table-responsive" role="form" action="{% url 'devapp:add_ports' dev.group.pk dev.pk %}" method="post">{% csrf_token %}
<table class="table table-striped table-bordered">
<thead>
@ -34,7 +34,7 @@
</tr>
</thead>
<tbody>
{% with gid=dev.user_group.pk did=dev.pk can_del_port=perms.devapp.delete_port %}
{% with gid=dev.group.pk did=dev.pk can_del_port=perms.devapp.delete_port %}
{% for port in ports %}
<tr>
<td>{% if port.status %}

4
devapp/templates/devapp/manage_ports/fix_abon_device.html

@ -5,8 +5,8 @@
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'devapp:group_list' %}">{% trans 'Groups' %}</a></li>
<li><a href="{% url 'devapp:devs' user_group.pk %}">{{ user_group.title }}</a></li>
<li><a href="{% url 'devapp:view' user_group.pk device.pk %}">{{ device.comment }}</a></li>
<li><a href="{% url 'devapp:devs' group.pk %}">{{ group.title }}</a></li>
<li><a href="{% url 'devapp:view' group.pk device.pk %}">{{ device.comment }}</a></li>
<li class="active">{% trans 'Fix subscriber ports conflict' %}</li>
</ol>

8
devapp/templates/devapp/manage_ports/list.html

@ -16,19 +16,19 @@
</thead>
<tbody>
{% with gid=dev.user_group.pk did=dev.pk can_del_port=perms.devapp.delete_port can_edit_port=perms.devapp.change_port %}
{% with gid=dev.group.pk did=dev.pk can_del_port=perms.devapp.delete_port can_edit_port=perms.devapp.change_port %}
{% for port in ports %}
<tr>
<td>{{ port.num }}</td>
<td>{{ port.descr }}</td>
{% if port.num_abons > 1 %}
{% url 'devapp:fix_port_conflict' dev.user_group.id dev.id port.id as fixurl %}
{% url 'devapp:fix_port_conflict' gid did port.id as fixurl %}
<td class="text-danger"><b>{{ port.num_abons }}</b>. {% blocktrans with furl=fixurl %}Port should not have more than one subscriber, <a href='{{ furl }}'>fix that</a>{% endblocktrans %}</td>
{% else %}
<td>{{ port.num_abons }}</td>
{% endif %}
<td class="btn-group btn-group-sm">
<a href="{% url 'devapp:show_subscriber_on_port' dev.user_group.id dev.id port.id %}" class="btn btn-default btn-modal" title="{% trans 'Show subscriber on port' %}" data-toggle="tooltip">
<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>
{% if can_del_port %}
@ -54,7 +54,7 @@
<tr>
<td colspan="4" class="btn-group">
{% if perms.devapp.add_port %}
<a href="{% url 'devapp:add_ports' dev.user_group.pk dev.pk %}" class="btn btn-sm btn-default" title="{% trans 'Add' %}">
<a href="{% url 'devapp:add_ports' dev.group.pk dev.pk %}" class="btn btn-sm btn-default" title="{% trans 'Add' %}">
<span class="glyphicon glyphicon-plus"></span> {% trans 'Add ports' %}
</a>
{% endif %}

81
devapp/views.py

@ -14,7 +14,9 @@ from easysnmp import EasySNMPTimeoutError, EasySNMPError
from django.views.generic import ListView, DetailView
from mydefs import res_success, res_error, only_admins, ping, ip_addr_regex
from abonapp.models import AbonGroup, Abon
from abonapp.models import Abon
from group_app.models import Group
from accounts_app.models import UserProfile
from django.conf import settings
from guardian.decorators import permission_required_or_403 as permission_required
from guardian.shortcuts import get_objects_for_user
@ -27,9 +29,6 @@ from .forms import DeviceForm, PortForm
from mydefs import safe_int
PAGINATION_ITEMS_PER_PAGE = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10)
class BaseDeviceListView(ListView):
http_method_names = ['get']
paginate_by = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10)
@ -42,15 +41,15 @@ class DevicesListView(BaseDeviceListView, OrderingMixin):
def get_queryset(self):
group_id = safe_int(self.kwargs.get('group_id'))
queryset = Device.objects.filter(user_group__pk=group_id) \
.select_related('user_group') \
.only('comment', 'mac_addr', 'devtype', 'user_group', 'pk', 'ip_address')
queryset = Device.objects.filter(group__pk=group_id) \
.select_related('group') \
.only('comment', 'mac_addr', 'devtype', 'group', 'pk', 'ip_address')
return queryset
def get_context_data(self, **kwargs):
group_id = safe_int(self.kwargs.get('group_id'))
context = super(DevicesListView, self).get_context_data(**kwargs)
context['group'] = get_object_or_404(AbonGroup, pk=group_id)
context['group'] = get_object_or_404(Group, pk=group_id)
return context
def dispatch(self, request, *args, **kwargs):
@ -66,7 +65,7 @@ class DevicesListView(BaseDeviceListView, OrderingMixin):
class DevicesWithoutGroupsListView(BaseDeviceListView, OrderingMixin):
context_object_name = 'devices'
template_name = 'devapp/devices_null_group.html'
queryset = Device.objects.filter(user_group=None).only('comment', 'devtype', 'user_group', 'pk', 'ip_address')
queryset = Device.objects.filter(group=None).only('comment', 'devtype', 'pk', 'ip_address')
@login_required
@ -74,7 +73,7 @@ class DevicesWithoutGroupsListView(BaseDeviceListView, OrderingMixin):
def devdel(request, device_id):
try:
dev = Device.objects.get(pk=device_id)
back_url = resolve_url('devapp:devs', group_id=dev.user_group.pk if dev.user_group else 0)
back_url = resolve_url('devapp:devs', group_id=dev.group.pk if dev.group else 0)
dev.delete()
return res_success(request, back_url)
except Device.DoesNotExist:
@ -86,8 +85,8 @@ def devdel(request, device_id):
@login_required
@permission_required('devapp.can_view_device')
def dev(request, group_id, device_id=0):
user_group = get_object_or_404(AbonGroup, pk=group_id)
if not request.user.has_perm('abonapp.can_view_abongroup', user_group):
device_group = get_object_or_404(Group, pk=group_id)
if not request.user.has_perm('group_app.can_view_group', device_group):
raise PermissionDenied
devinst = get_object_or_404(Device, id=device_id) if device_id != 0 else None
already_dev = None
@ -106,11 +105,11 @@ def dev(request, group_id, device_id=0):
# check if that device is exist
try:
already_dev = Device.objects.exclude(pk=device_id).get(mac_addr=request.POST.get('mac_addr'))
if already_dev.user_group:
if already_dev.group:
messages.warning(request, _('You have redirected to existing device'))
return redirect('devapp:view', already_dev.user_group.pk, already_dev.pk)
return redirect('devapp:view', already_dev.group.pk, already_dev.pk)
else:
messages.warning(request, _('Please attach user group for device'))
messages.warning(request, _('Please attach group for device'))
return redirect('devapp:fix_device_group', already_dev.pk)
except Device.DoesNotExist:
pass
@ -120,7 +119,7 @@ def dev(request, group_id, device_id=0):
# change device info in dhcpd.conf
ndev.update_dhcp()
messages.success(request, _('Device info has been saved'))
return redirect('devapp:edit', ndev.user_group.pk, ndev.pk)
return redirect('devapp:edit', ndev.group.pk, ndev.pk)
else:
messages.error(request, _('Form is invalid, check fields and try again'))
except IntegrityError as e:
@ -131,7 +130,7 @@ def dev(request, group_id, device_id=0):
else:
if devinst is None:
frm = DeviceForm(initial={
'user_group': user_group,
'group': device_group,
'devtype': request.GET.get('t'),
'mac_addr': request.GET.get('mac'),
'comment': request.GET.get('c'),
@ -145,7 +144,7 @@ def dev(request, group_id, device_id=0):
if devinst is None:
return render(request, 'devapp/add_dev.html', {
'form': frm,
'group': user_group,
'group': device_group,
'already_dev': already_dev
})
else:
@ -153,7 +152,7 @@ def dev(request, group_id, device_id=0):
'form': frm,
'dev': devinst,
'selected_parent_dev': devinst.parent_dev,
'group': user_group,
'group': device_group,
'already_dev': already_dev
})
@ -163,8 +162,8 @@ def dev(request, group_id, device_id=0):
def manage_ports(request, device_id):
try:
dev = Device.objects.get(pk=device_id)
if dev.user_group is None:
messages.error(request, _('Device is not have a group, please fix that'))
if dev.group is None:
messages.error(request, _('Device does not have a group, please fix that'))
return redirect('devapp:fix_device_group', dev.pk)
ports = Port.objects.filter(device=dev).annotate(num_abons=Count('abon'))
@ -212,13 +211,13 @@ def add_ports(request, device_id):
return self.pid
def __str__(self):
return "p:%d\tM:%s\tT:%s" % (self.pid, self.text)
return "p:%d\tT:%s" % (self.pid, self.text)
try:
res_ports = list()
dev = Device.objects.get(pk=device_id)
if dev.user_group is None:
messages.error(request, _('Device is not have a group, please fix that'))
if dev.group is None:
messages.error(request, _('Device does not have a group, please fix that'))
return redirect('devapp:fix_device_group', dev.pk)
if request.method == 'POST':
ports = zip(
@ -348,8 +347,8 @@ def devview(request, device_id):
ports, manager = None, None
dev = get_object_or_404(Device, id=device_id)
if not dev.user_group:
messages.warning(request, _('Please attach user group for device'))
if not dev.group:
messages.warning(request, _('Please attach group for device'))
return redirect('devapp:fix_device_group', dev.pk)
template_name = 'ports.html'
@ -401,18 +400,18 @@ def toggle_port(request, device_id, portid, status=0):
messages.error(request, _('wait for a reply from the SNMP Timeout'))
except EasySNMPError as e:
messages.error(request, e)
return redirect('devapp:view', dev.user_group.pk if dev.user_group is not None else 0, device_id)
return redirect('devapp:view', dev.group.pk if dev.group is not None else 0, device_id)
@method_decorator([login_required, only_admins], name='dispatch')
class GroupsListView(BaseDeviceListView):
context_object_name = 'groups'
template_name = 'devapp/group_list.html'
model = AbonGroup
model = Group
def get_queryset(self):
groups = super(GroupsListView, self).get_queryset()
groups = get_objects_for_user(self.request.user, 'abonapp.can_view_abongroup', klass=groups,
groups = get_objects_for_user(self.request.user, 'group_app.can_view_group', klass=groups,
accept_global_perms=False)
return groups
@ -438,11 +437,11 @@ def fix_device_group(request, device_id):
frm = DeviceForm(request.POST, instance=dev)
if frm.is_valid():
ch_dev = frm.save()
if ch_dev.user_group:
if ch_dev.group:
messages.success(request, _('Device fixed'))
return redirect('devapp:devs', ch_dev.user_group.pk)
return redirect('devapp:devs', ch_dev.group.pk)
else:
messages.error(request, _('Please attach user group for device'))
messages.error(request, _('Please attach group for device'))
else:
messages.error(request, _('Form is invalid, check fields and try again'))
else:
@ -470,6 +469,7 @@ def fix_onu(request):
text = '<span class="glyphicon glyphicon-ok"></span> <span class="hidden-xs">%s</span>' %\
(_('Device with mac address %(mac)s does not exist') % {'mac': mac})
for srcmac, snmpnum in ports:
# convert bytes mac address to str presentation mac address
real_mac = ':'.join(['%x' % ord(i) for i in srcmac])
if mac == real_mac:
onu.snmp_item_num = snmpnum
@ -489,13 +489,13 @@ def fix_onu(request):
@login_required
def fix_port_conflict(request, group_id, device_id, port_id):
user_group = get_object_or_404(AbonGroup, pk=group_id)
dev_group = get_object_or_404(Group, pk=group_id)
device = get_object_or_404(Device, pk=device_id)
port = get_object_or_404(Port, pk=port_id)
abons = Abon.objects.filter(device__id=device_id, dev_port__id=port_id)
return render(request, 'devapp/manage_ports/fix_abon_device.html', {
'abons': abons,
'user_group': user_group,
'group': dev_group,
'device': device,
'port': port
})
@ -519,19 +519,14 @@ class OnDevDown(AllowedSubnetMixin, HashAuthView):
if not bool(re.match(ip_addr_regex, dev_ip)):
return {'text': 'ip address %s is not valid' % dev_ip}
possible_devices = Device.objects.filter(ip_address=dev_ip)
if possible_devices.count() < 1:
return {
'text': 'Devices with ip %s does not exist' % dev_ip
}
else:
device_down = possible_devices[0]
device_down = Device.objects.filter(ip_address=dev_ip).first()
if device_down is None:
return {'text': 'Devices with ip %s does not exist' % dev_ip}
if not device_down.is_noticeable:
return {'text': 'Notification for %s is unnecessary' % device_down.ip_address}
recipients = device_down.user_group.profiles.all()
recipients = UserProfile.objects.get_profiles_by_group(device_down.group.pk)
names = list()
if dev_status == 'UP':

37
dialing_app/migrations/0001_initial.py

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-05-30 13:33
# Generated by Django 1.11 on 2018-02-26 00:20
from __future__ import unicode_literals
from django.db import migrations, models
@ -38,6 +38,41 @@ class Migration(migrations.Migration):
],
options={
'db_table': 'cdr',
'ordering': ['-calldate'],
'managed': False,
},
),
migrations.CreateModel(
name='SMSModel',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('when', models.DateTimeField(auto_now_add=True)),
('who', models.CharField(max_length=32)),
('dev', models.CharField(max_length=20)),
('text', models.CharField(max_length=255)),
],
options={
'verbose_name': 'SMS',
'verbose_name_plural': 'SMS',
'db_table': 'sms',
'ordering': ['-when'],
'permissions': (('can_view_sms', 'Can view sms'),),
},
),
migrations.CreateModel(
name='SMSOut',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('when', models.DateTimeField(auto_now_add=True, verbose_name='When')),
('dst', models.CharField(max_length=16, verbose_name='Telephone')),
('text', models.CharField(max_length=255, verbose_name='Text')),
('status', models.CharField(choices=[('nw', 'New'), ('st', 'Sent'), ('fd', 'Failed')], default='nw', max_length=2, verbose_name='Status')),
],
options={
'verbose_name': 'Out SMS',
'verbose_name_plural': 'Out SMS',
'db_table': 'out_sms',
'permissions': (('can_view_sms', 'Can view sms'), ('can_send_sms', 'Can send sms')),
},
),
]

35
dialing_app/migrations/0002_auto_20171229_1353.py

@ -1,35 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-12-29 13:53
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dialing_app', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='SMSModel',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('when', models.DateTimeField(auto_now_add=True)),
('who', models.CharField(max_length=32)),
('dev', models.CharField(max_length=20)),
('text', models.CharField(max_length=255)),
],
options={
'verbose_name': 'SMS',
'verbose_name_plural': 'SMS',
'db_table': 'sms',
'permissions': (('can_view_sms', 'Can view sms'),),
},
),
migrations.AlterModelOptions(
name='asteriskcdr',
options={'managed': False},
),
]

31
dialing_app/migrations/0003_smsout.py

@ -1,31 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2018-01-04 18:16
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dialing_app', '0002_auto_20171229_1353'),
]
operations = [
migrations.CreateModel(
name='SMSOut',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('when', models.DateTimeField(auto_now_add=True, verbose_name='When')),
('dst', models.CharField(max_length=16, verbose_name='Telephone')),
('text', models.CharField(max_length=255, verbose_name='Text')),
('status', models.CharField(choices=[('nw', 'New'), ('st', 'Sent'), ('fd', 'Failed')], default='nw', max_length=2, verbose_name='Status')),
],
options={
'verbose_name': 'Out SMS',
'verbose_name_plural': 'Out SMS',
'db_table': 'out_sms',
'permissions': (('can_view_sms', 'Can view sms'), ('can_send_sms', 'Can send sms')),
},
),
]

10
dialing_app/views.py

@ -3,7 +3,8 @@ from subprocess import run
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.contrib.gis.shortcuts import render_to_text
from django.shortcuts import render, redirect
from django.db import ProgrammingError
from django.shortcuts import redirect
from django.utils.translation import gettext_lazy as _
from django.utils.decorators import method_decorator
from django.views.generic import ListView
@ -28,6 +29,13 @@ class LastCallsListView(BaseListView):
context_object_name = 'logs'
queryset = AsteriskCDR.objects.exclude(userfield='request')
def get(self, request, *args, **kwargs):
try:
return super(LastCallsListView, self).get(request, *args, **kwargs)
except ProgrammingError as e:
messages.error(self.request, e)
return redirect('abonapp:group_list')
def get_context_data(self, **kwargs):
context = super(LastCallsListView, self).get_context_data(**kwargs)
context['title'] = _('Last calls')

2
djing/settings.py

@ -51,11 +51,11 @@ INSTALLED_APPS = [
'chatbot',
'msg_app',
'dialing_app',
'group_app',
'guardian',
'pinax_theme_bootstrap',
'bootstrapform',
'bootstrap3'
]
MIDDLEWARE = [

1
djing/urls.py

@ -17,6 +17,7 @@ urlpatterns = [
url(r'^client/', include('clientsideapp.urls', namespace='client_side')),
url(r'^msg/', include('msg_app.urls', namespace='msg_app')),
url(r'^dialing/', include('dialing_app.urls', namespace='dialapp')),
url(r'^groups/', include('group_app.urls', namespace='group_app')),
url(r'^admin/', admin.site.urls)
]

0
group_app/__init__.py

4
group_app/admin.py

@ -0,0 +1,4 @@
from django.contrib import admin
from . import models
admin.site.register(models.Group)

5
group_app/apps.py

@ -0,0 +1,5 @@
from django.apps import AppConfig
class GroupAppConfig(AppConfig):
name = 'group_app'

8
group_app/forms.py

@ -0,0 +1,8 @@
from django import forms
from . import models
class GroupForm(forms.ModelForm):
class Meta:
model = models.Group
fields = ['title']

69
group_app/locale/ru/LC_MESSAGES/django.po

@ -0,0 +1,69 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2018-02-26 01:47+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Dmitry Novikov <nerosketch@gmail.com>\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
"%100>=11 && n%100<=14)? 2 : 3);\n"
#: models.py:7
msgid "Title"
msgstr "Название"
#: models.py:16
msgid "Can view group"
msgstr "Может видеть группы"
#: models.py:18
msgid "Group"
msgstr "Группа"
#: models.py:19 templates/group_app/ext.html:7 templates/group_app/ext.html:8
#: templates/group_app/ext.html:14 templates/group_app/group_list.html:7
#: templates/group_app/group_list.html:10
msgid "Groups"
msgstr "Группы"
#: templates/group_app/add_group.html:9 templates/group_app/group_list.html:49
msgid "Add group"
msgstr "Добавить группу"
#: templates/group_app/add_group.html:16
msgid "Add"
msgstr "Добавить"
#: templates/group_app/edit_group.html:4 templates/group_app/edit_group.html:9
msgid "Edit group"
msgstr "Изменить группу"
#: templates/group_app/edit_group.html:16
msgid "Save"
msgstr "Сохранить"
#: templates/group_app/group_list.html:41
msgid "Groups was not found"
msgstr "Не найдено ни одной группы"
#: views.py:31
msgid "Group changes has been saved"
msgstr "Изменения сохранены"
#: views.py:35 views.py:51
msgid "Please fix form errors"
msgstr "Исправьте ошибки формы"
#: views.py:47
msgid "New group are created"
msgstr "Новая группа успешно создана"

30
group_app/migrations/0001_initial.py

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2018-02-26 00:20
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Group',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=127, unique=True, verbose_name='Title')),
],
options={
'verbose_name': 'Group',
'verbose_name_plural': 'Groups',
'db_table': 'groups',
'ordering': ['title'],
'permissions': (('can_view_group', 'Can view group'),),
},
),
]

0
group_app/migrations/__init__.py

23
group_app/models.py

@ -0,0 +1,23 @@
from django.utils.translation import gettext_lazy as _
from django.shortcuts import resolve_url
from django.db import models
class Group(models.Model):
title = models.CharField(_('Title'), max_length=127, unique=True)
def get_absolute_url(self):
url = resolve_url('group_app:edit', self.pk)
return url
class Meta:
db_table = 'groups'
permissions = (
('can_view_group', _('Can view group')),
)
verbose_name = _('Group')
verbose_name_plural = _('Groups')
ordering = ['title']
def __str__(self):
return self.title

20
group_app/templates/group_app/add_group.html

@ -0,0 +1,20 @@
{% extends request.is_ajax|yesno:'nullcont.htm,group_app/ext.html' %}
{% load i18n %}
{% load bootstrap3 %}
{% block active_text %}{% trans 'Add group' %}{% endblock %}
{% block content %}
<form action="{% url 'group_app:add' %}" method="post">{% csrf_token %}
<div class="modal-header success">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title"><span class="glyphicon glyphicon-info-sign"></span>{% trans 'Add group' %}</h4>
</div>
<div class="modal-body">
{% bootstrap_form form %}
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-success">
<span class="glyphicon glyphicon-plus"></span> {% trans 'Add' %}
</button>
</div>
</form>
{% endblock %}

20
group_app/templates/group_app/edit_group.html

@ -0,0 +1,20 @@
{% extends request.is_ajax|yesno:'nullcont.htm,group_app/ext.html' %}
{% load i18n %}
{% load bootstrap3 %}
{% block active_text %}{% trans 'Edit group' %}{% endblock %}
{% block content %}
<form action="{% url 'group_app:edit' object.pk %}" method="post">{% csrf_token %}
<div class="modal-header primary">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title"><span class="glyphicon glyphicon-info-sign"></span>{% trans 'Edit group' %}</h4>
</div>
<div class="modal-body">
{% bootstrap_form form %}
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">
<span class="glyphicon glyphicon-save"></span> {% trans 'Save' %}
</button>
</div>
</form>
{% endblock %}

23
group_app/templates/group_app/ext.html

@ -0,0 +1,23 @@
{% extends request.is_ajax|yesno:'bajax.html,base.html' %}
{% load i18n %}
{% block main %}
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'group_app:group_list' %}">{% trans 'Groups' %}</a></li>
<li class="active">{% block active_text %}{% trans 'Groups' %}{% endblock %}</li>
</ol>
{% include 'message_block.html' %}
<div class="page-header">
<h2>{% trans 'Groups' %}</h2>
</div>
<div class="panel panel-default">
<div class="panel-body">
{% block content %}{% endblock %}
</div>
</div>
{% endblock %}

59
group_app/templates/group_app/group_list.html

@ -0,0 +1,59 @@
{% extends 'base.html' %}
{% load i18n %}
{% block main %}
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li class="active">{% trans 'Groups' %}</li>
</ol>
<h3>{% trans 'Groups' %}</h3>
{% include 'message_block.html' %}
<div class="table-responsive">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th width="50">#</th>
<th>
<a href="{% url 'group_app:group_list' %}?order_by=title&dir={{ dir|default:'down' }}">
{% trans 'Title' %}
</a>
{% if order_by == 'title' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
</th>
<th width="100">#</th>
</tr>
</thead>
<tbody>
{% for gr in groups %}
<tr>
<td>{{ gr.pk }}</td>
<td><a href="{% url 'group_app:edit' gr.pk %}" class="btn-modal">{{ gr.title }}</a></td>
<td class="btn-group">
<a href="{% url 'group_app:edit' gr.pk %}" class="btn btn-sm btn-default btn-modal">
<span class="glyphicon glyphicon-cog"></span>
</a>
</td>
</tr>
{% empty %}
<tr>
<td colspan="3"><a href="#">{% trans 'Groups was not found' %}</a></td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<td colspan="3" class="btn-group btn-group-sm">
<a href="{% url 'group_app:add' %}" class="btn btn-success btn-modal">
<span class="glyphicon glyphicon-plus"></span> <span class="hidden-xs">{% trans 'Add group' %}</span>
</a>
</td>
</tr>
</tfoot>
</table>
</div>
{% include 'pagination.html' %}
{% endblock %}

3
group_app/tests.py

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

10
group_app/urls.py

@ -0,0 +1,10 @@
from django.conf.urls import url
from . import views
app_name = 'group_app'
urlpatterns = [
url(r'^$', views.GroupListView.as_view(), name='group_list'),
url(r'^add/$', views.AddGroupView.as_view(), name='add'),
url(r'^(?P<group_id>\d{1,6})/edit/$', views.EditGroupView.as_view(), name='edit')
]

52
group_app/views.py

@ -0,0 +1,52 @@
from django.views.generic import ListView, UpdateView, CreateView
from django.contrib.auth.decorators import login_required
from django.utils.translation import gettext_lazy as _
from django.utils.decorators import method_decorator
from django.urls import reverse_lazy
from django.contrib import messages
from django.conf import settings
from . import models
from . import forms
@method_decorator(login_required, name='dispatch')
class GroupListView(ListView):
http_method_names = ['get']
paginate_by = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10)
template_name = 'group_app/group_list.html'
model = models.Group
context_object_name = 'groups'
@method_decorator(login_required, name='dispatch')
class EditGroupView(UpdateView):
http_method_names = ['get', 'post']
template_name = 'group_app/edit_group.html'
form_class = forms.GroupForm
model = models.Group
pk_url_kwarg = 'group_id'
success_url = reverse_lazy('group_app:group_list')
def form_valid(self, form):
messages.success(self.request, _('Group changes has been saved'))
return super(EditGroupView, self).form_valid(form)
def form_invalid(self, form):
messages.success(self.request, _('Please fix form errors'))
return super(EditGroupView, self).form_invalid(form)
@method_decorator(login_required, name='dispatch')
class AddGroupView(CreateView):
http_method_names = ['get', 'post']
template_name = 'group_app/add_group.html'
form_class = forms.GroupForm
success_url = reverse_lazy('group_app:group_list')
def form_valid(self, form):
messages.success(self.request, _('New group are created'))
return super(AddGroupView, self).form_valid(form)
def form_invalid(self, form):
messages.success(self.request, _('Please fix form errors'))
return super(AddGroupView, self).form_invalid(form)

66
locale/ru/LC_MESSAGES/django.po

@ -7,10 +7,9 @@
msgid ""
msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-01-26 19:22+0300\n"
"POT-Creation-Date: 2018-02-26 02:06+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Dmitry Novikov nerosketch@gmail.com\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -19,37 +18,13 @@ msgstr ""
"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
"%100>=11 && n%100<=14)? 2 : 3);\n"
#: agent/commands/dhcp.py:19
msgid "User settings is not dynamic"
msgstr ""
#: agent/commands/dhcp.py:29
#, python-format
msgid "User with device '%s' does not exist"
msgstr ""
#: agent/commands/dhcp.py:31
#, python-format
msgid "Device with mac %s not found"
msgstr ""
#: agent/commands/dhcp.py:33
#, python-format
msgid "Port %d on device with mac %s does not exist"
msgstr ""
#: cron.py:30
#, python-format
msgid "Service '%(service_name)s' has expired"
msgstr "Срок действия услуги '%(service_name)s' истёк"
#: djing/formfields.py:13
msgid "Enter a valid integer."
msgstr ""
msgstr "Введите число"
#: djing/formfields.py:22
msgid "Enter a valid MAC Address."
msgstr ""
msgstr "Введите мак адрес"
#: templates/403.html:5
msgid "Permission denied"
@ -67,3 +42,38 @@ msgstr "У вас нет прав просматривать эту страни
#: templates/403_for_modal.html:11
msgid "Close"
msgstr "Закрыть"
#: templates/base.html:28
msgid "Administrators"
msgstr "Сотрудники"
#: templates/base.html:35
msgid "Subscribers"
msgstr "Абоненты"
#: templates/base.html:41
msgid "Tasks"
msgstr "Задачи"
#: templates/base.html:48
msgid "Groups"
msgstr "Группы"
#: templates/base.html:54
msgid "Services"
msgstr "Тарифы"
#: templates/base.html:61
msgid "Map settings"
msgstr "Настройки карты"
#: templates/base.html:68
msgid "Messages"
msgstr "Сообщения"
#: templates/base.html:85
msgid "Devices"
msgstr "Устрофства"
#~ msgid "Service '%(service_name)s' has expired"
#~ msgstr "Срок действия услуги '%(service_name)s' истёк"

16
mapapp/migrations/0001_initial.py

@ -1,5 +1,7 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-01-25 16:02
# Generated by Django 1.11 on 2018-02-26 00:20
from __future__ import unicode_literals
from django.db import migrations, models
@ -8,6 +10,7 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
('devapp', '0001_initial'),
]
operations = [
@ -15,12 +18,17 @@ class Migration(migrations.Migration):
name='Dot',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=127)),
('latitude', models.FloatField()),
('longitude', models.FloatField()),
('title', models.CharField(max_length=127, verbose_name='Map point title')),
('latitude', models.FloatField(verbose_name='Latitude')),
('longitude', models.FloatField(verbose_name='Longitude')),
('attachment', models.FileField(blank=True, null=True, upload_to='map_attachments/%Y_%m_%d', verbose_name='Attachment')),
('devices', models.ManyToManyField(db_table='dot_device', to='devapp.Device', verbose_name='Devices')),
],
options={
'verbose_name': 'Map point',
'verbose_name_plural': 'Map points',
'db_table': 'dots',
'permissions': (('can_view', 'Can view'),),
},
),
]

45
mapapp/migrations/0002_auto_20171103_0006.py

@ -1,45 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-11-03 00:06
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('devapp', '0004_auto_20171103_0006'),
('mapapp', '0001_initial'),
]
operations = [
migrations.AlterModelOptions(
name='dot',
options={'permissions': (('can_view', 'Can view'),), 'verbose_name': 'Map dot', 'verbose_name_plural': 'Map dots'},
),
migrations.AddField(
model_name='dot',
name='attachment',
field=models.FileField(blank=True, null=True, upload_to='map_attachments/%Y_%m_%d', verbose_name='Attachment'),
),
migrations.AddField(
model_name='dot',
name='devices',
field=models.ManyToManyField(db_table='dot_device', to='devapp.Device', verbose_name='Devices'),
),
migrations.AlterField(
model_name='dot',
name='latitude',
field=models.FloatField(verbose_name='Latitude'),
),
migrations.AlterField(
model_name='dot',
name='longitude',
field=models.FloatField(verbose_name='Longitude'),
),
migrations.AlterField(
model_name='dot',
name='title',
field=models.CharField(max_length=127, verbose_name='Map point title'),
),
]

10
mapapp/templates/maps/dot.html

@ -66,8 +66,8 @@
{% for dev in dot.devices.all %}
<tr>
<td>
{% if dev.user_group %}
<a href="{% url 'devapp:view' dev.user_group.pk dev.pk %}">{{ dev.comment }}</a>
{% if dev.group %}
<a href="{% url 'devapp:view' dev.group.pk dev.pk %}">{{ dev.comment }}</a>
{% else %}
<a href="{% url 'devapp:view' 0 dev.pk %}">{{ dev.comment }}</a>
{% endif %}
@ -75,9 +75,9 @@
<td>{{ dev.ip_address }}</td>
<td>{{ dev.get_comment_display }}</td>
<td>
{% if dev.user_group %}
<a href="{% url 'abonapp:people_list' dev.user_group.pk %}">
{{ dev.user_group }}
{% if dev.group %}
<a href="{% url 'abonapp:people_list' dev.group.pk %}">
{{ dev.group }}
</a>
{% else %}
{% trans 'User group has no attached' %}

2
mapapp/templates/maps/map_tooltip.html

@ -2,7 +2,7 @@
<h4>{{ dot.title }}</h4>
<div class="list-group">
{% for dev in devs %}
<a class="list-group-item" href="{% url 'devapp:view' dev.user_group.pk dev.pk %}" target="_blank" title="{{ dev.mon.plugin_output }}">
<a class="list-group-item" href="{% url 'devapp:view' dev.group.pk dev.pk %}" target="_blank" title="{{ dev.mon.plugin_output }}">
{% if dev.mon.current_state == '0' %}
<span class="glyphicon glyphicon-ok-circle text-success"></span>
{% else %}

2
mapapp/templates/maps/ya_index.html

@ -145,7 +145,7 @@
<h4 class="modal-title">{% trans 'Layers' %}</h4>
</div>
<div class="list-group">
{% for grp in abon_groups %}
{% for grp in groups %}
<button type="button" data-href="{% url 'mapapp:resolve_dots_by_group' grp.pk %}" class="list-group-item mapbtns">{{ grp.title }}</button>
{% endfor %}
</div>

17
mapapp/views.py

@ -9,12 +9,12 @@ from django.utils.decorators import method_decorator
from django.db.models import Count
from django.views.generic import ListView
from django.conf import settings
from group_app.models import Group
from .models import Dot
from .forms import DotForm
from mydefs import safe_int
from devapp.models import Device
from guardian.decorators import permission_required
from abonapp.models import AbonGroup
from json import dumps
@ -28,10 +28,10 @@ def home(request):
if not request.user.is_superuser:
return redirect('/')
dots = Dot.objects.all()
groups = AbonGroup.objects.all()
groups = Group.objects.all()
return render(request, 'maps/ya_index.html', {
'dots': dots,
'abon_groups': groups
'groups': groups
})
@ -144,8 +144,7 @@ def preload_devices(request):
return HttpResponseForbidden('you have not super user')
grp = request.GET.get('grp')
dot = request.GET.get('dot')
#user_group = AbonGroup.objects.get(pk=grp)
all_devices = Device.objects.filter(user_group__id=grp)
all_devices = Device.objects.filter(group__id=grp)
dot_devices = Device.objects.filter(dot__id=dot)
dot_devices_ids = [dev.pk for dev in dot_devices]
@ -179,7 +178,7 @@ def dot_tooltip(request):
def add_dev(request, did):
if not request.user.is_superuser:
return redirect('/')
groups = AbonGroup.objects.all()
groups = Group.objects.all()
dot = get_object_or_404(Dot, pk=did)
param_user_group = safe_int(request.GET.get('grp'))
@ -187,7 +186,7 @@ def add_dev(request, did):
selected_devs = request.POST.getlist('dv')
selected_user_group = safe_int(request.POST.get('selected_user_group'))
existing_devs = Device.objects.filter(user_group__id=selected_user_group or param_user_group)
existing_devs = Device.objects.filter(group__id=selected_user_group or param_user_group)
if existing_devs.count() > 0:
dot.devices.remove(*[dev.pk for dev in existing_devs])
dot.devices.add(*selected_devs)
@ -195,7 +194,7 @@ def add_dev(request, did):
url = resolve_url('mapapp:add_dev', did=dot.pk)
return HttpResponseRedirect("%s?grp=%d" % (url, selected_user_group or param_user_group))
else:
existing_devs = Device.objects.filter(user_group=param_user_group)
existing_devs = Device.objects.filter(group=param_user_group)
return render(request, 'maps/add_device.html', {
'groups': groups,
'dot': dot,
@ -209,7 +208,7 @@ def add_dev(request, did):
def resolve_dots_by_group(request, grp_id):
if not request.user.is_superuser:
return HttpResponseForbidden('you have not super user')
devs = Device.objects.filter(user_group__id=grp_id)
devs = Device.objects.filter(group__id=grp_id)
dots = Dot.objects.filter(devices__in=devs).annotate(devcount=Count('devices')).only('pk')
res = [dot.pk for dot in dots]
return HttpResponse(dumps(res), content_type='application/json')

2
msg_app/migrations/0001_initial.py

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-10-04 17:44
# Generated by Django 1.11 on 2018-02-26 00:20
from __future__ import unicode_literals
from django.conf import settings

4
photo_app/migrations/0001_initial.py

@ -1,10 +1,12 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2016-06-28 23:51
# Generated by Django 1.11 on 2018-02-26 00:20
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [

18
statistics/migrations/0001_initial.py

@ -1,12 +1,14 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2016-06-28 23:51
# Generated by Django 1.11 on 2018-02-26 00:20
from __future__ import unicode_literals
from django.db import migrations, models
import mydefs
import statistics.fields
class Migration(migrations.Migration):
initial = True
dependencies = [
@ -14,19 +16,15 @@ class Migration(migrations.Migration):
operations = [
migrations.CreateModel(
name='StatElem',
name='StatCache',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('src_ip', mydefs.MyGenericIPAddressField(max_length=8, protocol='ipv4')),
('dst_ip', mydefs.MyGenericIPAddressField(max_length=8, protocol='ipv4')),
('proto', models.PositiveSmallIntegerField(default=0)),
('src_port', models.PositiveIntegerField(default=0)),
('dst_port', models.PositiveIntegerField(default=0)),
('last_time', statistics.fields.UnixDateTimeField()),
('ip', mydefs.MyGenericIPAddressField(max_length=8, primary_key=True, protocol='ipv4', serialize=False)),
('octets', models.PositiveIntegerField(default=0)),
('packets', models.PositiveIntegerField(default=0)),
],
options={
'db_table': 'flowstat',
'db_table': 'flowcache',
},
),
]

34
statistics/migrations/0002_statcache.py

@ -1,34 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-05-31 17:37
from __future__ import unicode_literals
from django.db import migrations, models
import mydefs
import statistics.fields
class Migration(migrations.Migration):
initial = True
dependencies = [
('statistics', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='StatCache',
fields=[
('last_time', statistics.fields.UnixDateTimeField()),
('ip', mydefs.MyGenericIPAddressField(max_length=8, primary_key=True, protocol='ipv4', serialize=False)),
('octets', models.PositiveIntegerField(default=0)),
('packets', models.PositiveIntegerField(default=0)),
],
options={
'db_table': 'flowcache',
},
),
migrations.DeleteModel(
name='StatElem',
),
]

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save