bashmak 9 years ago
parent
commit
b78ba60ba4
  1. 1
      abonapp/admin.py
  2. 21
      abonapp/forms.py
  3. 82
      abonapp/locale/ru/LC_MESSAGES/django.po
  4. 108
      abonapp/migrations/0001_initial.py
  5. 318
      abonapp/migrations/0001_squashed_0022_auto_20170816_1109.py
  6. 23
      abonapp/migrations/0002_auto_20161206_2135.py
  7. 52
      abonapp/migrations/0002_auto_20170905_1248.py
  8. 20
      abonapp/migrations/0003_abongroup_profiles.py
  9. 43
      abonapp/migrations/0003_auto_20170927_1838.py
  10. 19
      abonapp/migrations/0004_auto_20161220_0102.py
  11. 25
      abonapp/migrations/0005_auto_20161226_0054.py
  12. 41
      abonapp/migrations/0006_auto_20170128_1626.py
  13. 42
      abonapp/migrations/0007_auto_20170131_1650.py
  14. 27
      abonapp/migrations/0008_auto_20170209_0002.py
  15. 20
      abonapp/migrations/0009_abontariff_death_line.py
  16. 43
      abonapp/migrations/0010_auto_20170220_1630.py
  17. 24
      abonapp/migrations/0011_auto_20170222_2224.py
  18. 24
      abonapp/migrations/0012_auto_20170227_1718.py
  19. 21
      abonapp/migrations/0013_abongroup_tariffs.py
  20. 42
      abonapp/migrations/0014_auto_20170330_1452.py
  21. 35
      abonapp/migrations/0015_passportinfo.py
  22. 32
      abonapp/migrations/0016_auto_20170415_1311.py
  23. 22
      abonapp/migrations/0017_auto_20170416_1029.py
  24. 26
      abonapp/migrations/0018_auto_20170418_1236.py
  25. 21
      abonapp/migrations/0019_abon_ip_address.py
  26. 25
      abonapp/migrations/0020_auto_20170517_1655.py
  27. 42
      abonapp/migrations/0021_auto_20170705_1403.py
  28. 41
      abonapp/migrations/0022_auto_20170816_1109.py
  29. 121
      abonapp/models.py
  30. 4
      abonapp/pay_systems.py
  31. 58
      abonapp/templates/abonapp/complete_service.html
  32. 20
      abonapp/templates/abonapp/editAbon.html
  33. 6
      abonapp/templates/abonapp/group_list.html
  34. 35
      abonapp/templates/abonapp/modal_add_phone.html
  35. 37
      abonapp/templates/abonapp/modal_additional_telephones.html
  36. 13
      abonapp/templates/abonapp/payHistory.html
  37. 24
      abonapp/templates/abonapp/peoples.html
  38. 2
      abonapp/templates/abonapp/viewAbon.html
  39. 8
      abonapp/templatetags/dpagination.py
  40. 4
      abonapp/urls.py
  41. 7
      abonapp/urls_abon.py
  42. 255
      abonapp/views.py
  43. 30
      accounts_app/forms.py
  44. 70
      accounts_app/locale/ru/LC_MESSAGES/django.po
  45. 19
      accounts_app/migrations/0008_auto_20170927_1838.py
  46. 23
      accounts_app/models.py
  47. 4
      accounts_app/templates/accounts/acc_list.html
  48. 34
      accounts_app/templates/accounts/ext.htm
  49. 50
      accounts_app/templates/accounts/group.html
  50. 58
      accounts_app/templates/accounts/group_list.html
  51. 34
      accounts_app/templates/accounts/perms/objects_of_type.html
  52. 36
      accounts_app/templates/accounts/perms/objects_types.html
  53. 71
      accounts_app/templates/accounts/perms/perms_edit.html
  54. 6
      accounts_app/templates/accounts/profile_chgroup.html
  55. 25
      accounts_app/templates/accounts/set_abon_groups_permission.html
  56. 11
      accounts_app/templates/accounts/settings/ext.htm
  57. 14
      accounts_app/templates/accounts/settings/permissions.html
  58. 14
      accounts_app/templates/accounts/settings/test.html
  59. 1
      accounts_app/templatetags/__init__.py
  60. 18
      accounts_app/templatetags/acc_tags.py
  61. 8
      accounts_app/urls.py
  62. 135
      accounts_app/views.py
  63. 26
      agent/core.py
  64. 46
      agent/mod_mikrotik.py
  65. 4
      clientsideapp/templates/clientsideapp/ext.html
  66. 30
      cron.py
  67. 9
      devapp/locale/ru/LC_MESSAGES/django.po
  68. 51
      devapp/migrations/0001_initial.py
  69. 90
      devapp/migrations/0001_squashed_0007_auto_20170816_1109.py
  70. 22
      devapp/migrations/0002_auto_20160909_1018.py
  71. 6
      devapp/migrations/0002_device_user_group.py
  72. 23
      devapp/migrations/0003_auto_20170927_1838.py
  73. 20
      devapp/migrations/0003_device_map_dot.py
  74. 20
      devapp/migrations/0005_auto_20170502_2232.py
  75. 48
      devapp/migrations/0006_auto_20170705_1403.py
  76. 20
      devapp/migrations/0007_auto_20170816_1109.py
  77. 11
      devapp/models.py
  78. 37
      devapp/templates/devapp/custom_dev_page/onu.html
  79. 12
      devapp/templates/devapp/devices_null_group.html
  80. 34
      devapp/views.py
  81. 2
      dialing_app/models.py
  82. 14
      dialing_app/templates/index.html
  83. 2
      dialing_app/views.py
  84. 3
      django_messages/__init__.py
  85. 112
      django_messages/admin.py
  86. 6
      django_messages/apps.py
  87. 7
      django_messages/context_processors.py
  88. 21
      django_messages/fields.py
  89. 67
      django_messages/forms.py
  90. 317
      django_messages/locale/ar/LC_MESSAGES/django.po
  91. 398
      django_messages/locale/cs/LC_MESSAGES/django.po
  92. 367
      django_messages/locale/da/LC_MESSAGES/django.po
  93. 321
      django_messages/locale/de/LC_MESSAGES/django.po
  94. 291
      django_messages/locale/el/LC_MESSAGES/django.po
  95. 314
      django_messages/locale/es/LC_MESSAGES/django.po
  96. 312
      django_messages/locale/es_AR/LC_MESSAGES/django.po
  97. 357
      django_messages/locale/fa/LC_MESSAGES/django.po
  98. 408
      django_messages/locale/fr/LC_MESSAGES/django.po
  99. 317
      django_messages/locale/it/LC_MESSAGES/django.po
  100. 292
      django_messages/locale/ko/LC_MESSAGES/django.po

1
abonapp/admin.py

@ -14,3 +14,4 @@ admin.site.register(models.AbonRawPassword)
admin.site.register(models.ExtraFieldsModel) admin.site.register(models.ExtraFieldsModel)
admin.site.register(models.AllPayLog) admin.site.register(models.AllPayLog)
admin.site.register(models.PassportInfo) admin.site.register(models.PassportInfo)
admin.site.register(models.AdditionalTelephone)

21
abonapp/forms.py

@ -6,6 +6,10 @@ from django.contrib.auth.hashers import make_password
from random import choice from random import choice
from string import digits, ascii_lowercase from string import digits, ascii_lowercase
from . import models from . import models
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_username(length=6, chars=digits, split=2, delimiter=''):
@ -57,7 +61,7 @@ class AbonForm(forms.ModelForm):
}), }),
'telephone': forms.TextInput(attrs={ 'telephone': forms.TextInput(attrs={
'placeholder': _('telephone placeholder'), 'placeholder': _('telephone placeholder'),
'pattern': r'^\+[7,8,9,3]\d{10,11}$',
'pattern': TELEPHONE_REGEXP,
'required': '', 'required': '',
'class': 'form-control' 'class': 'form-control'
}), }),
@ -131,3 +135,18 @@ class AbonStreetForm(forms.ModelForm):
'name': forms.TextInput(attrs={'class': 'form-control', 'required':'', 'autofocus':''}), 'name': forms.TextInput(attrs={'class': 'form-control', 'required':'', 'autofocus':''}),
'group': forms.Select(attrs={'class': 'form-control'}) 'group': forms.Select(attrs={'class': 'form-control'})
} }
class AdditionalTelephoneForm(forms.ModelForm):
class Meta:
model = models.AdditionalTelephone
exclude = ['abon']
widgets = {
'telephone': forms.TextInput(attrs={
'placeholder': _('telephone placeholder'),
'pattern': TELEPHONE_REGEXP,
'required': '',
'class': 'form-control'
}),
'owner_name': forms.TextInput(attrs={'class': 'form-control', 'required':''})
}

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

@ -339,7 +339,7 @@ msgstr "куда"
#: abonapp/templates/abonapp/dial_log.html:12 #: abonapp/templates/abonapp/dial_log.html:12
msgid "duration" msgid "duration"
msgstr "продолжительность"
msgstr "прод."
#: abonapp/templates/abonapp/dial_log.html:13 #: abonapp/templates/abonapp/dial_log.html:13
msgid "start" msgid "start"
@ -389,10 +389,6 @@ msgstr "Дом"
msgid "Is active" msgid "Is active"
msgstr "Активен" msgstr "Активен"
#: abonapp/templates/abonapp/editAbon.html:106
msgid "Send account info to user"
msgstr "Отправить данные абоненту"
#: abonapp/templates/abonapp/editAbon.html:109 #: abonapp/templates/abonapp/editAbon.html:109
#: abonapp/templates/abonapp/editAbon.html:110 #: abonapp/templates/abonapp/editAbon.html:110
#, fuzzy #, fuzzy
@ -473,7 +469,7 @@ msgstr "Принадлежность услуг к группам"
#: abonapp/templates/abonapp/invoiceForPayment.html:10 #: abonapp/templates/abonapp/invoiceForPayment.html:10
#: abonapp/templates/abonapp/payHistory.html:39 #: abonapp/templates/abonapp/payHistory.html:39
msgid "Debts" msgid "Debts"
msgstr "Долги"
msgstr "Квитанции (долги)"
#: abonapp/templates/abonapp/invoiceForPayment.html:15 #: abonapp/templates/abonapp/invoiceForPayment.html:15
msgid "Debtor" msgid "Debtor"
@ -606,10 +602,6 @@ msgstr "Балланс"
msgid "Subscribers not found" msgid "Subscribers not found"
msgstr "Абоненты не найдены" msgstr "Абоненты не найдены"
#: abonapp/templates/abonapp/peoples.html:130
msgid "Refresh subscribers on NAS"
msgstr "Обновить абонентов в NAS"
#: abonapp/templates/abonapp/peoples.html:133 #: abonapp/templates/abonapp/peoples.html:133
msgid "Tariffs in groups" msgid "Tariffs in groups"
msgstr "Тарифы в группах" msgstr "Тарифы в группах"
@ -736,10 +728,6 @@ msgstr "Адрес"
msgid "delete abon success msg" msgid "delete abon success msg"
msgstr "Абонент успешно удалён" msgstr "Абонент успешно удалён"
#: abonapp/views.py:180
msgid "I not know what to delete"
msgstr "Не понятно что удалять"
#: abonapp/views.py:184 #: abonapp/views.py:184
#, python-format #, python-format
msgid "NAS says: '%s'" msgid "NAS says: '%s'"
@ -951,3 +939,69 @@ msgstr "Пользователь, который не является перс
msgid "Ip not passed" msgid "Ip not passed"
msgstr "Ip адрес не передан" msgstr "Ip адрес не передан"
msgid "Additional telephone"
msgstr "Дополнительный телефон"
msgid "Additional telephones"
msgstr "Дополнительные телефоны"
msgid "Abon group"
msgstr "Группа абонентов"
msgid "Abon groups"
msgstr "Группы абонентов"
msgid "Abon service"
msgstr "Услуга абонента"
msgid "Abon services"
msgstr "Услуги абонентов"
msgid "Abon"
msgstr "Абонент"
msgid "Abons"
msgstr "Абоненты"
msgid "New telephone has been saved"
msgstr "Новый телефон сохранен"
msgid "Add telephone"
msgstr "Добавить номер телефона"
msgid "Telephone owner"
msgstr "Владелец телефона"
msgid "Additional telephones not found"
msgstr "Дополнительные телефоны не найдены"
msgid "Additional telephone successfully deleted"
msgstr "Номер телефона успешно удалён"
msgid "Telephone not found"
msgstr "Телефон не найден"
msgid "Can view subscriber group"
msgstr "Может просматривать группу абонентов"
msgid "Permission denied"
msgstr "Доступ запрещён"
msgid "Can view subscriber logs"
msgstr "Может видеть логи абонента"
msgid "Can view invoice for payment"
msgstr "Может видеть назначенные платежи"
msgid "Debt"
msgstr "Квитанция (долг)"
msgid "Passport Info"
msgstr "Паспортные данные"
msgid "Can ping"
msgstr "Может пинговать"
msgid "Can view additional telephones"
msgstr "Может видеть дополнительные телефоны"

108
abonapp/migrations/0001_initial.py

@ -1,108 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2016-06-28 23:51
from django.conf import settings
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('accounts_app', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('tariff_app', '0001_initial'),
]
operations = [
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)),
],
options={
'db_table': 'abonent',
},
bases=('accounts_app.userprofile',),
),
migrations.CreateModel(
name='AbonGroup',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=127)),
('address', models.CharField(blank=True, max_length=256, null=True)),
],
options={
'db_table': 'abonent_groups',
},
),
migrations.CreateModel(
name='AbonLog',
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)),
],
options={
'db_table': 'abonent_log',
},
),
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')),
('tariff', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='linkto_tariff',
to='tariff_app.Tariff')),
],
options={
'ordering': ('tariff_priority',),
'db_table': 'abonent_tariff',
},
),
migrations.CreateModel(
name='InvoiceForPayment',
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(on_delete=django.db.models.deletion.CASCADE, related_name='+',
to=settings.AUTH_USER_MODEL)),
],
options={
'ordering': ('date_create',),
'db_table': 'abonent_inv_pay',
},
),
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={('abon', 'tariff', 'tariff_priority')},
),
]

318
abonapp/migrations/0001_squashed_0022_auto_20170816_1109.py

@ -0,0 +1,318 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-09-04 16:15
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
import mydefs
import re
class Migration(migrations.Migration):
initial = True
dependencies = [
('devapp', '0001_squashed_0007_auto_20170816_1109'),
('tariff_app', '0002_tariff_descr'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('accounts_app', '0001_initial'),
('tariff_app', '0001_initial'),
]
operations = [
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)),
],
options={
'db_table': 'abonent',
},
bases=('accounts_app.userprofile',),
),
migrations.CreateModel(
name='AbonGroup',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=127, unique=True)),
],
options={
'db_table': 'abonent_groups',
},
),
migrations.CreateModel(
name='AbonLog',
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)),
],
options={
'db_table': 'abonent_log',
},
),
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')),
('tariff', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='linkto_tariff', to='tariff_app.Tariff')),
],
options={
'ordering': ('tariff_priority',),
'db_table': 'abonent_tariff',
},
),
migrations.CreateModel(
name='InvoiceForPayment',
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)),
],
options={
'ordering': ('date_create',),
'db_table': 'abonent_inv_pay',
},
),
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=[
('pay_id', models.CharField(max_length=64, primary_key=True, serialize=False)),
('date_action', models.DateTimeField(auto_now_add=True)),
('summ', models.FloatField(default=0.0)),
('pay_system_name', models.CharField(max_length=16)),
],
options={
'db_table': 'all_pay_log',
'ordering': ('date_action',),
},
),
migrations.CreateModel(
name='AllTimePayLog',
fields=[
('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)),
],
options={
'db_table': 'all_time_pay_log',
'ordering': ('date_add',),
},
),
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.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',
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)),
],
options={
'db_table': 'abon_extra_fields',
},
),
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=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('series', models.CharField(max_length=4, validators=[django.core.validators.RegexValidator(re.compile('^-?\\d+\\Z', 32), code='invalid', message='Enter a valid integer.')])),
('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')),
],
),
migrations.CreateModel(
name='AbonDevice',
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')),
],
options={
'db_table': 'abon_device',
},
),
migrations.AlterUniqueTogether(
name='abondevice',
unique_together=set([('abon', 'device')]),
),
migrations.AlterField(
model_name='abondevice',
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='abon',
name='ip_address',
field=mydefs.MyGenericIPAddressField(blank=True, max_length=8, null=True, protocol='ipv4'),
),
migrations.AddField(
model_name='abon',
name='dev_port',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='devapp.Port'),
),
migrations.AddField(
model_name='abon',
name='device',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='devapp.Device'),
),
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', 'Снятие со счёта средств'),)},
),
migrations.RemoveField(
model_name='abon',
name='current_tariffs',
),
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',
),
]

23
abonapp/migrations/0002_auto_20161206_2135.py

@ -1,23 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2016-12-06 18:35
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='abongroup',
name='address',
),
migrations.AlterField(
model_name='abongroup',
name='title',
field=models.CharField(max_length=127, unique=True),
),
]

52
abonapp/migrations/0002_auto_20170905_1248.py

@ -0,0 +1,52 @@
# -*- 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'),
),
]

20
abonapp/migrations/0003_abongroup_profiles.py

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2016-12-16 19:14
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('abonapp', '0002_auto_20161206_2135'),
]
operations = [
migrations.AddField(
model_name='abongroup',
name='profiles',
field=models.ManyToManyField(related_name='abon_groups', to=settings.AUTH_USER_MODEL),
),
]

43
abonapp/migrations/0003_auto_20170927_1838.py

@ -0,0 +1,43 @@
# -*- 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',
),
]

19
abonapp/migrations/0004_auto_20161220_0102.py

@ -1,19 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2016-12-19 22:02
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0003_abongroup_profiles'),
]
operations = [
migrations.AlterField(
model_name='abongroup',
name='profiles',
field=models.ManyToManyField(blank=True, related_name='abon_groups', to=settings.AUTH_USER_MODEL),
),
]

25
abonapp/migrations/0005_auto_20161226_0054.py

@ -1,25 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2016-12-25 21:54
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0004_auto_20161220_0102'),
]
operations = [
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', 'Активация услуги абонента'))},
),
]

41
abonapp/migrations/0006_auto_20170128_1626.py

@ -1,41 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-01-28 13:26
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0005_auto_20161226_0054'),
]
operations = [
migrations.CreateModel(
name='AbonStreets',
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.AbonStreets'),
),
]

42
abonapp/migrations/0007_auto_20170131_1650.py

@ -1,42 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-01-31 13:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0006_auto_20170128_1626'),
]
operations = [
migrations.CreateModel(
name='AllPayLog',
fields=[
('pay_id', models.CharField(max_length=64, primary_key=True, serialize=False)),
('date_action', models.DateTimeField(auto_now_add=True)),
('summ', models.FloatField(default=0.0)),
('pay_system_name', models.CharField(max_length=16)),
],
options={
'db_table': 'all_pay_log',
'ordering': ('date_action',),
},
),
migrations.CreateModel(
name='AllTimePayLog',
fields=[
('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)),
],
options={
'db_table': 'all_time_pay_log',
'ordering': ('date_add',),
},
),
migrations.RenameModel(
old_name='AbonStreets',
new_name='AbonStreet',
),
]

27
abonapp/migrations/0008_auto_20170209_0002.py

@ -1,27 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-02-08 21:02
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0007_auto_20170131_1650'),
]
operations = [
migrations.CreateModel(
name='AbonRawPassword',
fields=[
('account', models.OneToOneField(primary_key=True, serialize=False, to='abonapp.Abon')),
('passw_text', models.CharField(max_length=64)),
],
options={
'db_table': 'abon_raw_password',
},
),
migrations.AlterModelTable(
name='abonstreet',
table='abon_street',
),
]

20
abonapp/migrations/0009_abontariff_death_line.py

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-02-16 12:22
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0008_auto_20170209_0002'),
]
operations = [
migrations.AddField(
model_name='abontariff',
name='deadline',
field=models.DateTimeField(blank=True, default=None, null=True),
),
]

43
abonapp/migrations/0010_auto_20170220_1630.py

@ -1,43 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-02-20 13:30
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0009_abontariff_death_line'),
]
operations = [
migrations.CreateModel(
name='ExtraFieldsModel',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('field_type', models.CharField(choices=[('int', 'Digital field'), ('str', 'Text field'), ('dbl', 'Floating field')], max_length=3)),
('data', models.CharField(blank=True, max_length=64, null=True)),
],
options={
'db_table': 'abon_extra_fields',
},
),
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.AddField(
model_name='extrafieldsmodel',
name='account',
field=models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='abonapp.Abon'),
),
]

24
abonapp/migrations/0011_auto_20170222_2224.py

@ -1,24 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-02-22 19:24
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0010_auto_20170220_1630'),
]
operations = [
migrations.AlterModelOptions(
name='abon',
options={'permissions': (('can_buy_tariff', 'Покупка тарифа абоненту'), ('can_view_passport', 'Может просматривать паспортные данные'))},
),
migrations.AlterField(
model_name='extrafieldsmodel',
name='field_type',
field=models.CharField(choices=[('int', 'Цифровое поле'), ('str', 'Текстовое поле'), ('dbl', 'Дробное с плавающей точкой')], max_length=3),
),
]

24
abonapp/migrations/0012_auto_20170227_1718.py

@ -1,24 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-03-02 18:41
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0011_auto_20170222_2224'),
]
operations = [
migrations.RemoveField(
model_name='extrafieldsmodel',
name='account',
),
migrations.AddField(
model_name='abon',
name='extra_fields',
field=models.ManyToManyField(to='abonapp.ExtraFieldsModel'),
),
]

21
abonapp/migrations/0013_abongroup_tariffs.py

@ -1,21 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-03-21 11:30
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tariff_app', '0002_tariff_descr'),
('abonapp', '0012_auto_20170227_1718'),
]
operations = [
migrations.AddField(
model_name='abongroup',
name='tariffs',
field=models.ManyToManyField(blank=True, related_name='tariff_groups', to='tariff_app.Tariff'),
),
]

42
abonapp/migrations/0014_auto_20170330_1452.py

@ -1,42 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-03-30 11:52
from __future__ import unicode_literals
import django.db.models.deletion
import djing.fields
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0013_abongroup_tariffs'),
]
operations = [
migrations.CreateModel(
name='Opt82',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('mac', djing.fields.MACAddressField(integer=True)),
('port', models.PositiveSmallIntegerField(default=0)),
],
options={
'db_table': 'opt_82',
},
),
migrations.AlterField(
model_name='abon',
name='extra_fields',
field=models.ManyToManyField(blank=True, to='abonapp.ExtraFieldsModel'),
),
migrations.AlterUniqueTogether(
name='opt82',
unique_together=set([('mac', 'port')]),
),
migrations.AddField(
model_name='abon',
name='opt82',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='abonapp.Opt82'),
),
]

35
abonapp/migrations/0015_passportinfo.py

@ -1,35 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-04-11 10:43
from __future__ import unicode_literals
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
import re
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0014_auto_20170330_1452'),
]
operations = [
migrations.CreateModel(
name='PassportInfo',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('series', models.CharField(max_length=4, validators=[django.core.validators.RegexValidator(re.compile('^-?\\d+\\Z', 32), code='invalid', message='Enter a valid integer.')])),
('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')),
],
),
migrations.AlterField(
model_name='abon',
name='opt82',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL,
to='abonapp.Opt82'),
)
]

32
abonapp/migrations/0016_auto_20170415_1311.py

@ -1,32 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-04-15 10:11
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('devapp', '0004_device_user_group'),
('abonapp', '0015_passportinfo'),
]
operations = [
migrations.CreateModel(
name='AbonDevice',
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')),
],
options={
'db_table': 'abon_device',
},
),
migrations.AlterUniqueTogether(
name='abondevice',
unique_together=set([('abon', 'device')]),
),
]

22
abonapp/migrations/0017_auto_20170416_1029.py

@ -1,22 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-04-16 07:29
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 = [
('abonapp', '0016_auto_20170415_1311'),
]
operations = [
migrations.AlterField(
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),
),
]

26
abonapp/migrations/0018_auto_20170418_1236.py

@ -1,26 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-04-18 09:36
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0017_auto_20170416_1029'),
]
operations = [
migrations.AlterField(
model_name='abondevice',
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'),
),
]

21
abonapp/migrations/0019_abon_ip_address.py

@ -1,21 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-05-10 23:17
from __future__ import unicode_literals
from django.db import migrations
import mydefs
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0018_auto_20170418_1236'),
]
operations = [
migrations.AddField(
model_name='abon',
name='ip_address',
field=mydefs.MyGenericIPAddressField(blank=True, max_length=8, null=True, protocol='ipv4'),
),
]

25
abonapp/migrations/0020_auto_20170517_1655.py

@ -1,25 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-05-17 13:55
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0019_abon_ip_address'),
]
operations = [
migrations.AddField(
model_name='extrafieldsmodel',
name='title',
field=models.CharField(default='no title', max_length=16),
),
migrations.AlterField(
model_name='extrafieldsmodel',
name='field_type',
field=models.CharField(choices=[('int', 'Цифровое поле'), ('str', 'Текстовое поле'), ('dbl', 'Дробное с плавающей точкой'), ('ipa', 'IP Адрес')], default='str', max_length=3),
),
]

42
abonapp/migrations/0021_auto_20170705_1403.py

@ -1,42 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-07-05 14:03
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('devapp', '0006_auto_20170705_1403'),
('abonapp', '0020_auto_20170517_1655'),
]
operations = [
migrations.RemoveField(
model_name='abon',
name='opt82',
),
migrations.DeleteModel(
name='Opt82',
),
migrations.AddField(
model_name='abon',
name='dev_port',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='devapp.Port'),
),
migrations.AddField(
model_name='abon',
name='device',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='devapp.Device'),
),
migrations.AddField(
model_name='abon',
name='is_dynamic_ip',
field=models.BooleanField(default=False),
),
migrations.DeleteModel(
name='AbonDevice',
),
]

41
abonapp/migrations/0022_auto_20170816_1109.py

@ -1,41 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-08-16 11:09
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0021_auto_20170705_1403'),
]
operations = [
migrations.AlterModelOptions(
name='abontariff',
options={'permissions': (('can_complete_service', 'Снятие со счёта средств'),)},
),
migrations.RemoveField(
model_name='abon',
name='current_tariffs',
),
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',
),
]

121
abonapp/models.py

@ -1,14 +1,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
from django.db.models.signals import post_save, post_delete, pre_delete, post_init
from django.dispatch import receiver
from django.utils import timezone from django.utils import timezone
from django.db import models from django.db import models
from django.core import validators from django.core import validators
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from agent import Transmitter, AbonStruct, TariffStruct, NasFailedResult, NasNetworkError from agent import Transmitter, AbonStruct, TariffStruct, NasFailedResult, NasNetworkError
from tariff_app.models import Tariff from tariff_app.models import Tariff
from accounts_app.models import UserProfile
from accounts_app.models import UserProfile, MyUserManager
from mydefs import MyGenericIPAddressField, ip2int, LogicError, ip_addr_regex from mydefs import MyGenericIPAddressField, ip2int, LogicError, ip_addr_regex
from djing import settings
from django.conf import settings
TELEPHONE_REGEXP = getattr(settings, 'TELEPHONE_REGEXP', r'^\+[7,8,9,3]\d{10,11}$')
class AbonGroup(models.Model): class AbonGroup(models.Model):
@ -19,8 +25,10 @@ class AbonGroup(models.Model):
class Meta: class Meta:
db_table = 'abonent_groups' db_table = 'abonent_groups'
permissions = ( permissions = (
('can_add_ballance', _('fill account')),
('can_view_abongroup', _('Can view subscriber group')),
) )
verbose_name = _('Abon group')
verbose_name_plural = _('Abon groups')
def __str__(self): def __str__(self):
return self.title return self.title
@ -35,6 +43,9 @@ class AbonLog(models.Model):
class Meta: class Meta:
db_table = 'abonent_log' db_table = 'abonent_log'
permissions = (
('can_view_abonlog', _('Can view subscriber logs')),
)
def __str__(self): def __str__(self):
return self.comment return self.comment
@ -68,6 +79,8 @@ class AbonTariff(models.Model):
permissions = ( permissions = (
('can_complete_service', _('finish service perm')), ('can_complete_service', _('finish service perm')),
) )
verbose_name = _('Abon service')
verbose_name_plural = _('Abon services')
class AbonStreet(models.Model): class AbonStreet(models.Model):
@ -79,6 +92,8 @@ class AbonStreet(models.Model):
class Meta: class Meta:
db_table = 'abon_street' db_table = 'abon_street'
verbose_name = _('Street')
verbose_name_plural = _('Streets')
class ExtraFieldsModel(models.Model): class ExtraFieldsModel(models.Model):
@ -123,6 +138,13 @@ class ExtraFieldsModel(models.Model):
db_table = 'abon_extra_fields' db_table = 'abon_extra_fields'
class AbonManager(MyUserManager):
def get_queryset(self):
return super(MyUserManager, self).get_queryset().filter(is_admin=False)
class Abon(UserProfile): class Abon(UserProfile):
current_tariff = models.ForeignKey(AbonTariff, null=True, blank=True, on_delete=models.SET_NULL) 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) group = models.ForeignKey(AbonGroup, models.SET_NULL, blank=True, null=True)
@ -140,12 +162,18 @@ class Abon(UserProfile):
def active_tariff(self): def active_tariff(self):
return self.current_tariff return self.current_tariff
objects = AbonManager()
class Meta: class Meta:
db_table = 'abonent' db_table = 'abonent'
permissions = ( permissions = (
('can_buy_tariff', _('Buy service perm')), ('can_buy_tariff', _('Buy service perm')),
('can_view_passport', _('Can view passport'))
('can_view_passport', _('Can view passport')),
('can_add_ballance', _('fill account')),
('can_ping', _('Can ping'))
) )
verbose_name = _('Abon')
verbose_name_plural = _('Abons')
# Платим за что-то # Платим за что-то
def make_pay(self, curuser, how_match_to_pay=0.0): def make_pay(self, curuser, how_match_to_pay=0.0):
@ -203,6 +231,8 @@ class Abon(UserProfile):
# Производим расчёт услуги абонента, т.е. завершаем если пришло время # Производим расчёт услуги абонента, т.е. завершаем если пришло время
def bill_service(self, author): def bill_service(self, author):
abon_tariff = self.active_tariff() abon_tariff = self.active_tariff()
if abon_tariff is None:
return
nw = timezone.now() nw = timezone.now()
# если услуга просрочена # если услуга просрочена
if nw > abon_tariff.deadline: if nw > abon_tariff.deadline:
@ -226,7 +256,7 @@ class Abon(UserProfile):
return return
abon_tariff = self.active_tariff() abon_tariff = self.active_tariff()
if abon_tariff is None: if abon_tariff is None:
agent_trf = TariffStruct()
agent_trf = None
else: else:
trf = abon_tariff.tariff trf = abon_tariff.tariff
agent_trf = TariffStruct(trf.id, trf.speedIn, trf.speedOut) agent_trf = TariffStruct(trf.id, trf.speedIn, trf.speedOut)
@ -247,7 +277,12 @@ class PassportInfo(models.Model):
date_of_acceptance = models.DateField() date_of_acceptance = models.DateField()
abon = models.OneToOneField(Abon, on_delete=models.SET_NULL, blank=True, null=True) abon = models.OneToOneField(Abon, on_delete=models.SET_NULL, blank=True, null=True)
def __unicode__(self):
class Meta:
db_table = 'passport_info'
verbose_name = _('Passport Info')
verbose_name_plural = _('Passport Info')
def __str__(self):
return "%s %s" % (self.series, self.number) return "%s %s" % (self.series, self.number)
@ -273,6 +308,11 @@ class InvoiceForPayment(models.Model):
class Meta: class Meta:
ordering = ('date_create',) ordering = ('date_create',)
db_table = 'abonent_inv_pay' db_table = 'abonent_inv_pay'
permissions = (
('can_view_invoiceforpayment', _('Can view invoice for payment')),
)
verbose_name = _('Debt')
verbose_name_plural = _('Debts')
# Log for pay system "AllTime" # Log for pay system "AllTime"
@ -315,7 +355,32 @@ class AbonRawPassword(models.Model):
db_table = 'abon_raw_password' db_table = 'abon_raw_password'
def abon_post_save(sender, instance, **kwargs):
class AdditionalTelephone(models.Model):
abon = models.ForeignKey(Abon, related_name='additional_telephones')
telephone = models.CharField(
max_length=16,
verbose_name=_('Telephone'),
# unique=True,
validators=[RegexValidator(TELEPHONE_REGEXP)]
)
owner_name = models.CharField(max_length=127)
def __str__(self):
return "%s - (%s)" % (self.owner_name, self.telephone)
class Meta:
db_table = 'additional_telephones'
ordering = ('owner_name',)
permissions = (
('can_view_additionaltelephones', _('Can view additional telephones')),
)
verbose_name = _('Additional telephone')
verbose_name_plural = _('Additional telephones')
@receiver(post_save, sender=Abon)
def abon_post_save(sender, **kwargs):
instance, created = kwargs["instance"], kwargs["created"]
timeout = None timeout = None
if hasattr(instance, 'is_dhcp') and instance.is_dhcp: if hasattr(instance, 'is_dhcp') and instance.is_dhcp:
timeout = getattr(settings, 'DHCP_TIMEOUT', 14400) timeout = getattr(settings, 'DHCP_TIMEOUT', 14400)
@ -324,21 +389,23 @@ def abon_post_save(sender, instance, **kwargs):
return True return True
try: try:
tm = Transmitter() tm = Transmitter()
if kwargs['created']:
if created:
# создаём абонента # создаём абонента
tm.add_user(agent_abon, ip_timeout=timeout) tm.add_user(agent_abon, ip_timeout=timeout)
else: else:
# обновляем абонента на NAS # обновляем абонента на NAS
tm.update_user(agent_abon, ip_timeout=timeout) tm.update_user(agent_abon, ip_timeout=timeout)
except (NasFailedResult, NasNetworkError) as e:
except (NasFailedResult, NasNetworkError, ConnectionResetError) as e:
print('ERROR:', e) print('ERROR:', e)
return True return True
def abon_del_signal(sender, instance, **kwargs):
@receiver(post_delete, sender=Abon)
def abon_del_signal(sender, **kwargs):
abon = kwargs["instance"]
try: try:
ab = instance.build_agent_struct()
ab = abon.build_agent_struct()
if ab is None: if ab is None:
return True return True
# подключаемся к NAS'у # подключаемся к NAS'у
@ -349,14 +416,28 @@ def abon_del_signal(sender, instance, **kwargs):
return True return True
def abon_tariff_post_init(sender, instance, **kwargs):
if getattr(instance, 'time_start') is None:
instance.time_start = timezone.now()
calc_obj = instance.tariff.get_calc_type()(instance)
if getattr(instance, 'deadline') is None:
instance.deadline = calc_obj.calc_deadline()
@receiver(post_init, sender=AbonTariff)
def abon_tariff_post_init(sender, **kwargs):
abon_tariff = kwargs["instance"]
if getattr(abon_tariff, 'time_start') is None:
abon_tariff.time_start = timezone.now()
calc_obj = abon_tariff.tariff.get_calc_type()(abon_tariff)
if getattr(abon_tariff, 'deadline') is None:
abon_tariff.deadline = calc_obj.calc_deadline()
models.signals.post_save.connect(abon_post_save, sender=Abon)
models.signals.post_delete.connect(abon_del_signal, sender=Abon)
models.signals.post_init.connect(abon_tariff_post_init, sender=AbonTariff)
@receiver(pre_delete, sender=AbonTariff)
def abontariff_pre_delete(sender, **kwargs):
abon_tariff = kwargs["instance"]
try:
abon = Abon.objects.get(current_tariff=abon_tariff)
ab = abon.build_agent_struct()
if ab is None:
return True
tm = Transmitter()
tm.remove_user(ab)
except Abon.DoesNotExist:
print('ERROR: Abon.DoesNotExist')
except (NasFailedResult, NasNetworkError, ConnectionResetError) as e:
print('NetErr:', e)
return True

4
abonapp/pay_systems.py

@ -6,8 +6,8 @@ from django.db import DatabaseError
from django.conf import settings from django.conf import settings
SECRET = getattr(settings, 'pay_SECRET')
SERV_ID = getattr(settings, 'pay_SERV_ID')
SECRET = getattr(settings, 'PAY_SECRET')
SERV_ID = getattr(settings, 'PAY_SERV_ID')
#?ACT=1&PAY_ACCOUNT=960849&SERVICE_ID=y832r92y8f9e&PAY_ID=3561234&TRADE_POINT=377&SIGN=32e533a72389fe4e93746509f9d672f8 #?ACT=1&PAY_ACCOUNT=960849&SERVICE_ID=y832r92y8f9e&PAY_ID=3561234&TRADE_POINT=377&SIGN=32e533a72389fe4e93746509f9d672f8

58
abonapp/templates/abonapp/complete_service.html

@ -1,58 +0,0 @@
{% 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 '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 class="active">{% trans 'Finish service' %}</li>
</ol>
{% include 'message_block.html' %}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans 'Finish service' %}</h3>
</div>
<div class="panel-body">
<form role="form" action="{% url 'abonapp:compl_srv' abon_group.id abon.id abtar.id %}" method="post">{% csrf_token %}
<input name="finish_confirm" value="yes" type="hidden">
<p>
{% blocktrans %}Early completion of the current service will cause that user will be denied access to services Resources (Net closes)
To continue to use the resources necessary to connect the required service{% endblocktrans %}
</p>
<p>{% blocktrans %}Details: <br/>
You complete tariff{% endblocktrans %}
{% if perms.tariff_app.change_tariff %}
<a href="{% url 'tarifs:edit' abtar.tariff.id %}" target="_blank">{{ abtar.tariff.title }}</a>.<br/>
{% else %}
{{ abtar.tariff.title }}.<br/>
{% endif %}
{% now "d F Y, H: i: s" as today %}
{% blocktrans with time_start=abtar.time_start|date:'d F Y, H: i: s' amount=abtar.tariff.amount %}The service has been connected: {{ time_start }}<br/>
Today: {{ today }}<br/>
Time of use: {{ time_use }}<br/>
The total cost of the service: {{ amount }}<br/>
Total cost: {{ tcost }}<br/>
Cashback: {{ cashback }}{% endblocktrans %}
</p>
<div class="btn-group">
<button type="submit" class="btn btn-sm btn-primary">
<span class="glyphicon glyphicon-save"></span> {% trans 'Save' %}
</button>
</div>
</form>
</div>
</div>
{% endblock %}

20
abonapp/templates/abonapp/editAbon.html

@ -1,5 +1,6 @@
{% extends request.is_ajax|yesno:'nullcont.htm,abonapp/ext.htm' %} {% extends request.is_ajax|yesno:'nullcont.htm,abonapp/ext.htm' %}
{% load i18n %} {% load i18n %}
{% load guardian_tags %}
{% block content %} {% block content %}
<div class="row"> <div class="row">
@ -31,9 +32,15 @@
<div class="input-group input-group-sm"> <div class="input-group input-group-sm">
{{ form.telephone }}{{ form.telephone.errors }} {{ form.telephone }}{{ form.telephone.errors }}
<span class="input-group-btn"> <span class="input-group-btn">
<a href="sip:{{ form.telephone.value }}" class="btn btn-default" title="{% trans 'Call to' %}">
<a href="sip:{{ form.telephone.value }}" class="btn btn-default" data-toggle="tooltip" title="{% trans 'Call to' %}">
<span class="glyphicon glyphicon-earphone"></span> <span class="glyphicon glyphicon-earphone"></span>
</a> </a>
<a href="{% url 'abonapp:telephones' abon_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' %}">
<span class="glyphicon glyphicon-plus"></span>
</a>
</span> </span>
</div> </div>
</div> </div>
@ -102,9 +109,6 @@
<button type="submit" class="btn btn-primary btn-sm"> <button type="submit" class="btn btn-primary btn-sm">
<span class="glyphicon glyphicon-floppy-disk"></span> {% trans 'Save' %} <span class="glyphicon glyphicon-floppy-disk"></span> {% trans 'Save' %}
</button> </button>
<!--<a href="#" class="btn btn-default btn-sm" onclick="showPrimary('<h3>Надо ещё придумать чем будем абонентам отправлять оповещения</h3> Ну кроме смс');">
<span class="glyphicon glyphicon-send"></span> {% trans 'Send account info to user' %}
</a>-->
{% if perms.taskapp.add_task %} {% if perms.taskapp.add_task %}
<a href="{% url 'taskapp:add' %}?uid={{ abon.username }}" class="btn btn-sm btn-success" title="{% trans 'Add new task' %}"> <a href="{% url 'taskapp:add' %}?uid={{ abon.username }}" class="btn btn-sm btn-success" title="{% trans 'Add new task' %}">
<span class="glyphicon glyphicon-plus"></span> {% trans 'Add new task' %} <span class="glyphicon glyphicon-plus"></span> {% trans 'Add new task' %}
@ -113,7 +117,7 @@
</div> </div>
</div> </div>
{% if ip %}
{% if ip and perms.abonapp.can_ping %}
<div class="form-group-sm"> <div class="form-group-sm">
<div class="col-sm-offset-4 col-sm-8 btn-group btn-group-sm"> <div class="col-sm-offset-4 col-sm-8 btn-group btn-group-sm">
<a href="{% url 'abonapp:ping' %}" class="btn btn-sm btn-default btn-cmd" title="Ping" data-param="{{ ip }}"> <a href="{% url 'abonapp:ping' %}" class="btn btn-sm btn-default btn-cmd" title="Ping" data-param="{{ ip }}">
@ -128,6 +132,7 @@
</div> </div>
</div> </div>
<div class="col-sm-6"> <div class="col-sm-6">
{% if perms.abonapp.change_abon %}
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<h3 class="panel-title">{% trans 'Select the device' %}</h3> <h3 class="panel-title">{% trans 'Select the device' %}</h3>
@ -140,7 +145,7 @@
<label for="id_method" class="col-sm-2 control-label">{% trans 'Device' %}</label> <label for="id_method" class="col-sm-2 control-label">{% trans 'Device' %}</label>
<div class="col-sm-10 btn-group btn-group-sm"> <div class="col-sm-10 btn-group btn-group-sm">
{% if device %} {% 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 }}">
<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 }}">
<span class="glyphicon glyphicon-hdd"></span> {{ device.comment|truncatechars:11 }} {{ device.ip_address }} <span class="glyphicon glyphicon-hdd"></span> {{ device.comment|truncatechars:11 }} {{ device.ip_address }}
</a> </a>
<a href="{% url 'abonapp:clear_dev' abon_group.pk abon.pk %}" class="btn btn-sm btn-danger"> <a href="{% url 'abonapp:clear_dev' abon_group.pk abon.pk %}" class="btn btn-sm btn-danger">
@ -193,6 +198,8 @@
</form> </form>
</div> </div>
</div> </div>
{% endif %}
{% if perms.abonapp.add_extrafieldsmodel %}
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<h3 class="panel-title">{% trans 'Extra fields' %}</h3> <h3 class="panel-title">{% trans 'Extra fields' %}</h3>
@ -236,6 +243,7 @@
</form> </form>
</div> </div>
</div> </div>
{% endif %}
</div> </div>
</div> </div>

6
abonapp/templates/abonapp/group_list.html

@ -38,7 +38,7 @@
<td class="btn-group"> <td class="btn-group">
{% if perms.abonapp.delete_abongroup %} {% if perms.abonapp.delete_abongroup %}
{% if gr.usercount == 0 %} {% if gr.usercount == 0 %}
<a href="{% url 'abonapp:del_group' %}?t=a&id={{ gr.pk }}" class="btn btn-sm btn-danger">
<a href="{% url 'abonapp:del_group' %}?id={{ gr.pk }}" class="btn btn-sm btn-danger">
<span class="glyphicon glyphicon-remove-circle"></span> <span class="glyphicon glyphicon-remove-circle"></span>
</a> </a>
{% endif %} {% endif %}
@ -63,12 +63,16 @@
<span class="glyphicon glyphicon-plus"></span> {% trans 'Add group' %} <span class="glyphicon glyphicon-plus"></span> {% trans 'Add group' %}
</a> </a>
{% endif %} {% endif %}
{% if perms.abonapp.can_view_abonlog %}
<a href="{% url 'abonapp:log' %}" class="btn btn-default btn-sm"> <a href="{% url 'abonapp:log' %}" class="btn btn-default btn-sm">
<span class="glyphicon glyphicon-record"></span> {% trans 'Subscribers actions' %} <span class="glyphicon glyphicon-record"></span> {% trans 'Subscribers actions' %}
</a> </a>
{% endif %}
{% if perms.abonapp.can_view_invoiceforpayment %}
<a href="{% url 'abonapp:debtors' %}" class="btn btn-default btn-sm"> <a href="{% url 'abonapp:debtors' %}" class="btn btn-default btn-sm">
<span class="glyphicon glyphicon-exclamation-sign"></span> {% trans 'List of debtors' %} <span class="glyphicon glyphicon-exclamation-sign"></span> {% trans 'List of debtors' %}
</a> </a>
{% endif %}
</td> </td>
</tr> </tr>
</tfoot> </tfoot>

35
abonapp/templates/abonapp/modal_add_phone.html

@ -0,0 +1,35 @@
{% load i18n %}
<form role="form" action="{% url 'abonapp:telephone_new' gid uid %}" 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-earphone"></span>{% trans 'Add telephone' %}</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label for="id_telephone">{% trans 'Telephone' %}</label>
<div class="input-group">
<span class="input-group-addon"><span class="glyphicon glyphicon-earphone"></span></span>
{{ form.telephone }}{{ form.telephone.errors }}
</div>
</div>
<div class="form-group">
<label for="id_owner_name">{% trans 'Telephone owner' %}</label>
<div class="input-group">
<span class="input-group-addon"><span class="glyphicon glyphicon-user"></span></span>
{{ form.owner_name }}{{ form.owner_name.errors }}
</div>
</div>
<div class="btn-group">
<button type="submit" class="btn btn-success">
<span class="glyphicon glyphicon-plus"></span> {% trans 'Add' %}
</button>
<button type="reset" class="btn btn-default">
<span class="glyphicon glyphicon-remove-circle"></span> {% trans 'Reset' %}
</button>
</div>
</div>
</form>

37
abonapp/templates/abonapp/modal_additional_telephones.html

@ -0,0 +1,37 @@
{% load i18n %}
<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-earphone"></span>{% trans 'Additional telephones' %}</h4>
</div>
<div class="modal-body">
<table class="table">
<thead>
<tr>
<th>{% trans 'Telephone owner' %}</th>
<th>{% trans 'Telephone' %}</th>
<th></th>
</tr>
</thead>
<tbody>
{% for t in telephones %}
<tr>
<td>{{ t.owner_name }}</td>
<td><a href="sip:{{ t.telephone }}" class="btn btn-link">{{ t.telephone }}</a></td>
<td>
<a href="{% url 'abonapp:telephone_del' gid uid %}?tid={{ t.pk }}" class="btn btn-default btn-sm" title="{% trans 'Delete' %}">
<span class="glyphicon glyphicon-remove-circle"></span>
</a>
</td>
</tr>
{% empty %}
<tr>
<td colspan="3">{% trans 'Additional telephones not found' %}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>

13
abonapp/templates/abonapp/payHistory.html

@ -1,5 +1,6 @@
{% extends request.is_ajax|yesno:'nullcont.htm,abonapp/ext.htm' %} {% extends request.is_ajax|yesno:'nullcont.htm,abonapp/ext.htm' %}
{% load i18n %} {% load i18n %}
{% load guardian_tags %}
{% block content %} {% block content %}
<table class="table table-striped table-bordered"> <table class="table table-striped table-bordered">
@ -31,11 +32,15 @@
<tr> <tr>
<td colspan="5" class="btn-group btn-group-sm"> <td colspan="5" class="btn-group btn-group-sm">
{% if perms.abonapp.can_add_ballance %} {% if perms.abonapp.can_add_ballance %}
<a href="{% url 'abonapp:abon_amount' abon_group.pk abon.pk %}" class="btn btn-default btn-modal">
<span class="glyphicon glyphicon-credit-card"></span> {% trans 'Fill account' %}
</a>
<a href="{% url 'abonapp:abon_amount' abon_group.pk abon.pk %}" class="btn btn-default btn-modal">
<span class="glyphicon glyphicon-credit-card"></span> {% trans 'Fill account' %}
</a>
{% else %}
<a href="#" class="btn btn-default" title="{% trans 'Permission denied' %}" disabled>
<span class="glyphicon glyphicon-credit-card"></span> {% trans 'Fill account' %}
</a>
{% endif %} {% endif %}
<a href="{% url 'abonapp:abon_debts' abon_group.pk abon.pk %}"class="btn btn-default">
<a href="{% url 'abonapp:abon_debts' abon_group.pk abon.pk %}" class="btn btn-default">
<span class="glyphicon glyphicon-gbp"></span> {% trans 'Debts' %} <span class="glyphicon glyphicon-gbp"></span> {% trans 'Debts' %}
</a> </a>
</td> </td>

24
abonapp/templates/abonapp/peoples.html

@ -1,5 +1,6 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load i18n %} {% load i18n %}
{% load dpagination %}
{% block main %} {% block main %}
@ -20,32 +21,32 @@
<tr> <tr>
<th>#</th> <th>#</th>
<th> <th>
<a href="{% url 'abonapp:people_list' abon_group.pk %}?order_by=username&dir={{ dir|default:"down" }}">
<a href="{% url 'abonapp:people_list' abon_group.pk %}?{% url_replace request order_by=username dir=dir|default:"down" %}">
{% trans 'Sub' %} {% trans 'Sub' %}
</a> </a>
{% if order_by == 'username' %}<span class="glyphicon glyphicon-filter"></span>{% endif %} {% if order_by == 'username' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
</th> </th>
<th>{% trans 'Last traffic' %}</th> <th>{% trans 'Last traffic' %}</th>
<th> <th>
<a href="{% url 'abonapp:people_list' abon_group.pk %}?order_by=ip_address&dir={{ dir|default:"down" }}">
<a href="{% url 'abonapp:people_list' abon_group.pk %}?{% url_replace request order_by=ip_address dir=dir|default:"down" %}">
{% trans 'Ip address' %} {% trans 'Ip address' %}
</a> </a>
{% if order_by == 'ip_address' %}<span class="glyphicon glyphicon-filter"></span>{% endif %} {% if order_by == 'ip_address' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
</th> </th>
<th> <th>
<a href="{% url 'abonapp:people_list' abon_group.pk %}?order_by=fio&dir={{ dir|default:"down" }}">
<a href="{% url 'abonapp:people_list' abon_group.pk %}?{% url_replace request order_by=fio dir=dir|default:"down" %}">
{% trans 'fio' %} {% trans 'fio' %}
</a> </a>
{% if order_by == 'fio' %}<span class="glyphicon glyphicon-filter"></span>{% endif %} {% if order_by == 'fio' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
</th> </th>
<th> <th>
<a href="{% url 'abonapp:people_list' abon_group.pk %}?order_by=street&dir={{ dir|default:"down" }}">
<a href="{% url 'abonapp:people_list' abon_group.pk %}?{% url_replace request order_by=street dir=dir|default:"down" %}">
{% trans 'Street' %} {% trans 'Street' %}
</a> </a>
{% if order_by == 'street' %}<span class="glyphicon glyphicon-filter"></span>{% endif %} {% if order_by == 'street' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
</th> </th>
<th width="100"> <th width="100">
<a href="{% url 'abonapp:people_list' abon_group.pk %}?order_by=house&dir={{ dir|default:"down" }}">
<a href="{% url 'abonapp:people_list' abon_group.pk %}?{% url_replace request order_by=house dir=dir|default:"down" %}">
{% trans 'Apartment' %} {% trans 'Apartment' %}
</a> </a>
{% if order_by == 'house' %}<span class="glyphicon glyphicon-filter"></span>{% endif %} {% if order_by == 'house' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
@ -53,7 +54,7 @@
<th width="150">{% trans 'Telephone' %}</th> <th width="150">{% trans 'Telephone' %}</th>
<th width="150">{% trans 'Service' %}</th> <th width="150">{% trans 'Service' %}</th>
<th width="50"> <th width="50">
<a href="{% url 'abonapp:people_list' abon_group.pk %}?order_by=ballance&dir={{ dir|default:"down" }}">
<a href="{% url 'abonapp:people_list' abon_group.pk %}?{% url_replace request order_by=ballance dir=dir|default:"down" %}">
{% trans 'Ballance' %} {% trans 'Ballance' %}
</a> </a>
{% if order_by == 'ballance' %}<span class="glyphicon glyphicon-filter"></span>{% endif %} {% if order_by == 'ballance' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
@ -104,7 +105,7 @@
<td>{{ human.ballance }}</td> <td>{{ human.ballance }}</td>
<td> <td>
{% if can_del_trf %} {% if can_del_trf %}
<a href="{% url 'abonapp:del_abon' %}?t=a&id={{ human.pk }}" class="btn btn-danger btn-sm">
<a href="{% url 'abonapp:del_abon' %}?id={{ human.pk }}" class="btn btn-danger btn-sm">
<span class="glyphicon glyphicon-remove"></span> <span class="glyphicon glyphicon-remove"></span>
</a> </a>
{% endif %} {% endif %}
@ -126,14 +127,11 @@
<tr> <tr>
<td colspan="11" class="btn-group"> <td colspan="11" class="btn-group">
{% if perms.abonapp.add_abon %} {% if perms.abonapp.add_abon %}
<a href="{% url 'abonapp:add_abon' abon_group.pk %}" class="btn btn-sm btn-default" title="Добавить">
<a href="{% url 'abonapp:add_abon' abon_group.pk %}" class="btn btn-sm btn-default" title="{% trans 'Add' %}" data-toggle="tooltip">
<span class="glyphicon glyphicon-plus"></span> {% trans 'Add abon' %} <span class="glyphicon glyphicon-plus"></span> {% trans 'Add abon' %}
</a> </a>
{% endif %} {% endif %}
<a href="{% url 'abonapp:update_nas' abon_group.pk %}" class="btn btn-sm btn-default">
<span class="glyphicon glyphicon-refresh"></span> {% trans 'Refresh subscribers on NAS' %}
</a>
<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' abon_group.pk %}" class="btn btn-sm btn-default" title="{% trans 'User groups' %}" data-toggle="tooltip">
<span class="glyphicon glyphicon-subscript"></span> {% trans 'Tariffs in groups' %} <span class="glyphicon glyphicon-subscript"></span> {% trans 'Tariffs in groups' %}
</a> </a>
</td> </td>
@ -147,7 +145,7 @@
<div class="panel-heading">{% trans 'Streets' %}</div> <div class="panel-heading">{% trans 'Streets' %}</div>
<div class="list-group"> <div class="list-group">
{% for street in streets %} {% for street in streets %}
<a href="{% url 'abonapp:people_list' abon_group.pk %}?street={{ street.pk }}" class="list-group-item{% if street_id == street.pk %} active{% endif %}">{{ street.name }}</a>
<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>
{% empty %} {% empty %}
<a href="#" class="list-group-item">{% trans 'No streets found for that group' %}</a> <a href="#" class="list-group-item">{% trans 'No streets found for that group' %}</a>
{% endfor %} {% endfor %}

2
abonapp/templates/abonapp/viewAbon.html

@ -61,6 +61,7 @@
</div> </div>
</div> </div>
{% if perms.abonapp.can_view_passport %}
<div class="col-sm-6"> <div class="col-sm-6">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
@ -86,6 +87,7 @@
</div> </div>
</div> </div>
</div> </div>
{% endif %}
</div> </div>
{% endblock %} {% endblock %}

8
abonapp/templatetags/dpagination.py

@ -8,3 +8,11 @@ def url_page_replace(request, field, value):
dict_ = request.GET.copy() dict_ = request.GET.copy()
dict_[field] = value dict_[field] = value
return dict_.urlencode() return dict_.urlencode()
@register.simple_tag
def url_replace(request, *args, **kwargs):
dict_ = request.GET.copy()
for k, v in kwargs.items():
dict_[k] = v
return dict_.urlencode()

4
abonapp/urls.py

@ -13,7 +13,7 @@ urlpatterns = [
url(r'^log$', views.log_page, name='log'), url(r'^log$', views.log_page, name='log'),
url(r'^del$', views.delentity, name='del_abon'),
url(r'^del$', views.del_abon, name='del_abon'),
url(r'^pay$', views.terminal_pay, name='terminal_pay'), url(r'^pay$', views.terminal_pay, name='terminal_pay'),
@ -21,8 +21,6 @@ urlpatterns = [
url(r'^ping$', views.abon_ping, name='ping'), url(r'^ping$', views.abon_ping, name='ping'),
url(r'^refresh_group_nas(?P<group_id>\d+)$', views.update_nas, name='update_nas'),
# Api's # Api's
url(r'^api/abons$', views.abons), url(r'^api/abons$', views.abons),
url(r'^api/abon_filter$', views.search_abon) url(r'^api/abon_filter$', views.search_abon)

7
abonapp/urls_abon.py

@ -19,7 +19,6 @@ urlpatterns = [
url(r'^(?P<uid>\d+)/addinvoice$', views.add_invoice, name='add_invoice'), url(r'^(?P<uid>\d+)/addinvoice$', views.add_invoice, name='add_invoice'),
url(r'^(?P<uid>\d+)/pick$', views.pick_tariff, name='pick_tariff'), url(r'^(?P<uid>\d+)/pick$', views.pick_tariff, name='pick_tariff'),
url(r'^(?P<uid>\d+)/passport_view$', views.passport_view, name='passport_view'), url(r'^(?P<uid>\d+)/passport_view$', views.passport_view, name='passport_view'),
url(r'^(?P<uid>\d+)/complete_service(?P<srvid>\d+)$', views.complete_service, name='compl_srv'),
url(r'^(?P<uid>\d+)/chart$', views.charts, name='charts'), url(r'^(?P<uid>\d+)/chart$', views.charts, name='charts'),
url(r'^(?P<uid>\d+)/dials$', views.dials, name='dials'), url(r'^(?P<uid>\d+)/dials$', views.dials, name='dials'),
url(r'^(?P<uid>\d+)/extra_field$', views.make_extra_field, name='extra_field'), url(r'^(?P<uid>\d+)/extra_field$', views.make_extra_field, name='extra_field'),
@ -33,5 +32,9 @@ urlpatterns = [
url(r'^(?P<uid>\d+)/clear_dev/$', views.clear_dev, name='clear_dev'), url(r'^(?P<uid>\d+)/clear_dev/$', views.clear_dev, name='clear_dev'),
url(r'^(?P<uid>\d+)/task_log$', views.task_log, name='task_log'), url(r'^(?P<uid>\d+)/task_log$', views.task_log, name='task_log'),
url(r'^(?P<uid>\d+)/user_dev$', views.save_user_dev_port, name='save_user_dev_port')
url(r'^(?P<uid>\d+)/user_dev$', views.save_user_dev_port, name='save_user_dev_port'),
url(r'^(?P<uid>\d+)/tel$', views.tels, name='telephones'),
url(r'^(?P<uid>\d+)/tel/add$', views.tel_add, name='telephone_new'),
url(r'^(?P<uid>\d+)/tel/del$', views.tel_del, name='telephone_del')
] ]

255
abonapp/views.py

@ -6,8 +6,7 @@ from django.db import IntegrityError, ProgrammingError
from django.db.models import Count, Q from django.db.models import Count, Q
from django.db.transaction import atomic from django.db.transaction import atomic
from django.shortcuts import render, redirect, get_object_or_404, resolve_url from django.shortcuts import render, redirect, get_object_or_404, resolve_url
from django.contrib.auth.decorators import login_required, permission_required
from django.utils import timezone
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse from django.http import HttpResponse
from django.contrib import messages from django.contrib import messages
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -23,17 +22,22 @@ from datetime import datetime, date
from taskapp.models import Task from taskapp.models import Task
from dialing_app.models import AsteriskCDR from dialing_app.models import AsteriskCDR
from statistics.models import getModel, get_dates from statistics.models import getModel, get_dates
from guardian.shortcuts import get_objects_for_user, assign_perm
from guardian.decorators import permission_required_or_403 as permission_required
@login_required @login_required
@mydefs.only_admins @mydefs.only_admins
def peoples(request, gid): def peoples(request, gid):
abon_group = get_object_or_404(models.AbonGroup, pk=gid)
if not request.user.has_perm('abonapp.can_view_abongroup', abon_group):
raise PermissionDenied
street_id = mydefs.safe_int(request.GET.get('street')) street_id = mydefs.safe_int(request.GET.get('street'))
peoples_list = models.Abon.objects.select_related('group', 'street') peoples_list = models.Abon.objects.select_related('group', 'street')
if street_id > 0: if street_id > 0:
peoples_list = peoples_list.filter(group=gid, street=street_id)
peoples_list = peoples_list.filter(group=abon_group, street=street_id)
else: else:
peoples_list = peoples_list.filter(group=gid)
peoples_list = peoples_list.filter(group=abon_group)
# фильтр # фильтр
dr, field = mydefs.order_helper(request) dr, field = mydefs.order_helper(request)
@ -72,7 +76,10 @@ def addgroup(request):
if request.method == 'POST': if request.method == 'POST':
frm = forms.AbonGroupForm(request.POST) frm = forms.AbonGroupForm(request.POST)
if frm.is_valid(): if frm.is_valid():
frm.save()
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')) messages.success(request, _('create group success msg'))
return redirect('abonapp:group_list') return redirect('abonapp:group_list')
else: else:
@ -91,6 +98,7 @@ def addgroup(request):
@mydefs.only_admins @mydefs.only_admins
def grouplist(request): def grouplist(request):
groups = models.AbonGroup.objects.annotate(usercount=Count('abon')).order_by('title') groups = models.AbonGroup.objects.annotate(usercount=Count('abon')).order_by('title')
groups = get_objects_for_user(request.user, 'abonapp.can_view_abongroup', klass=groups, accept_global_perms=False)
# фильтр # фильтр
directory, field = mydefs.order_helper(request) directory, field = mydefs.order_helper(request)
@ -107,11 +115,13 @@ def grouplist(request):
@login_required @login_required
@permission_required('abonapp.delete_abongroup')
def delgroup(request): def delgroup(request):
try: try:
agd = mydefs.safe_int(request.GET.get('id')) agd = mydefs.safe_int(request.GET.get('id'))
get_object_or_404(models.AbonGroup, pk=agd).delete()
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')) messages.success(request, _('delete group success msg'))
return mydefs.res_success(request, 'abonapp:group_list') return mydefs.res_success(request, 'abonapp:group_list')
except (NasFailedResult, NasNetworkError) as e: except (NasFailedResult, NasNetworkError) as e:
@ -119,6 +129,8 @@ def delgroup(request):
except mydefs.MultipleException as errs: except mydefs.MultipleException as errs:
for err in errs.err_list: for err in errs.err_list:
messages.add_message(request, messages.constants.ERROR, err) 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') return mydefs.res_error(request, 'abonapp:group_list')
@ -129,10 +141,17 @@ def addabon(request, gid):
group = None group = None
try: try:
group = get_object_or_404(models.AbonGroup, pk=gid) group = get_object_or_404(models.AbonGroup, pk=gid)
if not request.user.has_perm('abonapp.can_view_abongroup', group):
raise PermissionDenied
if request.method == 'POST': if request.method == 'POST':
frm = forms.AbonForm(request.POST, initial={'group': group}) frm = forms.AbonForm(request.POST, initial={'group': group})
if frm.is_valid(): if frm.is_valid():
abon = frm.save() abon = frm.save()
assign_perm("abonapp.change_abon", request.user, abon)
assign_perm("abonapp.delete_abon", request.user, abon)
assign_perm("abonapp.can_buy_tariff", request.user, abon)
assign_perm("abonapp.can_view_passport", request.user, abon)
assign_perm('abonapp.can_add_ballance', request.user, abon)
messages.success(request, _('create abon success msg')) messages.success(request, _('create abon success msg'))
return redirect('abonapp:abon_home', group.id, abon.pk) return redirect('abonapp:abon_home', group.id, abon.pk)
else: else:
@ -159,26 +178,18 @@ def addabon(request, gid):
@login_required @login_required
@mydefs.only_admins @mydefs.only_admins
def delentity(request):
typ = request.GET.get('t')
def del_abon(request):
uid = request.GET.get('id') uid = request.GET.get('id')
try: try:
if typ == 'a':
if not request.user.has_perm('abonapp.delete_abon'):
raise PermissionDenied
abon = get_object_or_404(models.Abon, pk=uid)
gid = abon.group.id
abon.delete()
messages.success(request, _('delete abon success msg'))
return mydefs.res_success(request, resolve_url('abonapp:people_list', gid=gid))
elif typ == 'g':
if not request.user.has_perm('abonapp.delete_abongroup'):
raise PermissionDenied
get_object_or_404(models.AbonGroup, pk=uid).delete()
messages.success(request, _('delete group success msg'))
return mydefs.res_success(request, 'abonapp:group_list')
else:
messages.warning(request, _('I not know what to delete'))
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):
raise PermissionDenied
gid = abon.group.id
abon.delete()
messages.success(request, _('delete abon success msg'))
return mydefs.res_success(request, resolve_url('abonapp:people_list', gid=gid))
except NasNetworkError as e: except NasNetworkError as e:
messages.error(request, e) messages.error(request, e)
except NasFailedResult as e: except NasFailedResult as e:
@ -218,6 +229,7 @@ def abonamount(request, gid, uid):
@login_required @login_required
@mydefs.only_admins @mydefs.only_admins
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
def invoice_for_payment(request, gid, uid): def invoice_for_payment(request, gid, uid):
abon = get_object_or_404(models.Abon, pk=uid) abon = get_object_or_404(models.Abon, pk=uid)
invoices = models.InvoiceForPayment.objects.filter(abon=abon) invoices = models.InvoiceForPayment.objects.filter(abon=abon)
@ -231,6 +243,7 @@ def invoice_for_payment(request, gid, uid):
@login_required @login_required
@mydefs.only_admins @mydefs.only_admins
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
def pay_history(request, gid, uid): def pay_history(request, gid, uid):
abon = get_object_or_404(models.Abon, pk=uid) abon = get_object_or_404(models.Abon, pk=uid)
pay_history = models.AbonLog.objects.filter(abon=abon).order_by('-id') pay_history = models.AbonLog.objects.filter(abon=abon).order_by('-id')
@ -246,6 +259,8 @@ def pay_history(request, gid, uid):
@mydefs.only_admins @mydefs.only_admins
def abon_services(request, gid, uid): def abon_services(request, gid, uid):
grp = get_object_or_404(models.AbonGroup, pk=gid) grp = get_object_or_404(models.AbonGroup, pk=gid)
if not request.user.has_perm('abonapp.can_view_abongroup', grp):
raise PermissionDenied
abon = get_object_or_404(models.Abon, pk=uid) abon = get_object_or_404(models.Abon, pk=uid)
return render(request, 'abonapp/service.html', { return render(request, 'abonapp/service.html', {
@ -261,6 +276,8 @@ def abon_services(request, gid, uid):
def abonhome(request, gid, uid): def abonhome(request, gid, uid):
abon = get_object_or_404(models.Abon, pk=uid) abon = get_object_or_404(models.Abon, pk=uid)
abon_group = get_object_or_404(models.AbonGroup, pk=gid) abon_group = get_object_or_404(models.AbonGroup, pk=gid)
if not request.user.has_perm('abonapp.can_view_abongroup', abon_group):
raise PermissionDenied
frm = None frm = None
passw = None passw = None
try: try:
@ -394,71 +411,13 @@ def pick_tariff(request, gid, uid):
}) })
@login_required
@permission_required('abonapp.can_complete_service')
@atomic
def complete_service(request, gid, uid, srvid):
abtar = get_object_or_404(models.AbonTariff, pk=srvid)
abon = abtar.abon
# считаем не использованные ресурсы
calc_obj = abtar.tariff.get_calc_type()(abtar)
# получаем сколько использовано
res_amount = calc_obj.calc_amount()
cashback = abtar.tariff.amount - res_amount
if abtar.abon.group is None:
abon.group = get_object_or_404(models.AbonGroup, pk=gid)
abon.save(update_fields=['group'])
if int(abtar.abon.pk) != int(uid) or int(abtar.abon.group.pk) != int(gid):
# если что-то написали в урле вручную, то вернём на путь истинный
return redirect('abonapp:compl_srv', gid=abtar.abon.group.pk, uid=abtar.abon.pk, srvid=srvid)
time_use = None
try:
if request.method == 'POST':
# досрочно завершаем услугу
if request.POST.get('finish_confirm') == 'yes':
if cashback > 0.5:
# возвращаем деньги, которые абонент не использовал
abon.add_ballance(
request.user,
cashback,
_('Refunds for unused resources')
)
abon.save(update_fields=['ballance'])
# удаляем запись о текущей услуге.
abtar.delete()
messages.success(request, _('Service has been finished successfully'))
return redirect('abonapp:abon_services', gid, uid)
else:
raise mydefs.LogicError(_('Not confirmed'))
time_use = mydefs.RuTimedelta(timezone.now() - abtar.time_start)
except (mydefs.LogicError, NasFailedResult) as e:
messages.error(request, e)
except NasNetworkError as e:
messages.warning(request, e)
return redirect('abonapp:abon_home', gid, uid)
except mydefs.MultipleException as errs:
for err in errs.err_list:
messages.add_message(request, messages.constants.ERROR, err)
return render(request, 'abonapp/complete_service.html', {
'abtar': abtar,
'abon': abon,
'time_use': time_use,
'abon_group': get_object_or_404(models.AbonGroup, pk=gid),
'tcost': round(res_amount, 4),
'cashback': round(cashback, 4)
})
@login_required @login_required
@permission_required('abonapp.delete_abontariff') @permission_required('abonapp.delete_abontariff')
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
def unsubscribe_service(request, gid, uid, abon_tariff_id): def unsubscribe_service(request, gid, uid, abon_tariff_id):
try: try:
get_object_or_404(models.AbonTariff, pk=int(abon_tariff_id)).delete()
abon_tariff = get_object_or_404(models.AbonTariff, pk=int(abon_tariff_id))
abon_tariff.delete()
messages.success(request, _('User has been detached from service')) messages.success(request, _('User has been detached from service'))
except NasFailedResult as e: except NasFailedResult as e:
messages.error(request, e) messages.error(request, e)
@ -471,7 +430,7 @@ def unsubscribe_service(request, gid, uid, abon_tariff_id):
@login_required @login_required
@mydefs.only_admins
@permission_required('abonapp.can_view_abonlog')
def log_page(request): def log_page(request):
logs = models.AbonLog.objects.all() logs = models.AbonLog.objects.all()
logs = mydefs.pag_mn(request, logs) logs = mydefs.pag_mn(request, logs)
@ -481,42 +440,17 @@ def log_page(request):
@login_required @login_required
@mydefs.only_admins
@permission_required('abonapp.can_view_invoiceforpayment')
def debtors(request): def debtors(request):
# peoples_list = models.Abon.objects.filter(invoiceforpayment__status=True)
# peoples_list = mydefs.pag_mn(request, peoples_list)
invs = models.InvoiceForPayment.objects.filter(status=True) invs = models.InvoiceForPayment.objects.filter(status=True)
invs = mydefs.pag_mn(request, invs) invs = mydefs.pag_mn(request, invs)
return render(request, 'abonapp/debtors.html', { return render(request, 'abonapp/debtors.html', {
# 'peoples': peoples_list
'invoices': invs 'invoices': invs
}) })
@login_required @login_required
@mydefs.only_admins
def update_nas(request, group_id):
users = models.Abon.objects.filter(group=group_id)
try:
tm = Transmitter()
for usr in users:
if not usr.ip_address:
continue
agent_abon = usr.build_agent_struct()
if agent_abon is not None:
tm.update_user(agent_abon)
except NasFailedResult as e:
messages.error(request, e)
except NasNetworkError as e:
messages.warning(request, e)
except mydefs.MultipleException as errs:
for err in errs.err_list:
messages.add_message(request, messages.constants.ERROR, err)
return redirect('abonapp:people_list', gid=group_id)
@login_required
@mydefs.only_admins
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
def task_log(request, gid, uid): def task_log(request, gid, uid):
abon = get_object_or_404(models.Abon, pk=uid) abon = get_object_or_404(models.Abon, pk=uid)
tasks = Task.objects.filter(abon=abon) tasks = Task.objects.filter(abon=abon)
@ -528,7 +462,7 @@ def task_log(request, gid, uid):
@login_required @login_required
@mydefs.only_admins
@permission_required('abonapp.can_view_passport')
def passport_view(request, gid, uid): def passport_view(request, gid, uid):
try: try:
abon = models.Abon.objects.get(pk=uid) abon = models.Abon.objects.get(pk=uid)
@ -566,6 +500,8 @@ def passport_view(request, gid, uid):
@mydefs.only_admins @mydefs.only_admins
def chgroup_tariff(request, gid): def chgroup_tariff(request, gid):
grp = get_object_or_404(models.AbonGroup, pk=gid) grp = get_object_or_404(models.AbonGroup, pk=gid)
if not request.user.has_perm('abonapp.change_abongroup', grp):
raise PermissionDenied
if request.method == 'POST': if request.method == 'POST':
tr = request.POST.getlist('tr') tr = request.POST.getlist('tr')
grp.tariffs.clear() grp.tariffs.clear()
@ -579,7 +515,7 @@ def chgroup_tariff(request, gid):
@login_required @login_required
@mydefs.only_admins
@permission_required('abonapp.change_abon')
def dev(request, gid, uid): def dev(request, gid, uid):
abon_dev = None abon_dev = None
try: try:
@ -605,7 +541,8 @@ def dev(request, gid, uid):
@login_required @login_required
@mydefs.only_admins
@permission_required('abonapp.change_abon')
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
def clear_dev(request, gid, uid): def clear_dev(request, gid, uid):
try: try:
abon = models.Abon.objects.get(pk=uid) abon = models.Abon.objects.get(pk=uid)
@ -619,7 +556,7 @@ def clear_dev(request, gid, uid):
@login_required @login_required
@mydefs.only_admins
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
def charts(request, gid, uid): def charts(request, gid, uid):
high = 100 high = 100
@ -673,7 +610,7 @@ def charts(request, gid, uid):
@login_required @login_required
@permission_required('abonapp.add_extra_fields_model')
@permission_required('abonapp.add_extrafieldsmodel')
def make_extra_field(request, gid, uid): def make_extra_field(request, gid, uid):
abon = get_object_or_404(models.Abon, pk=uid) abon = get_object_or_404(models.Abon, pk=uid)
try: try:
@ -733,6 +670,7 @@ def extra_field_delete(request, gid, uid, fid):
@login_required @login_required
@permission_required('abonapp.can_ping')
def abon_ping(request): def abon_ping(request):
ip = request.GET.get('cmd_param') ip = request.GET.get('cmd_param')
status = False status = False
@ -753,7 +691,8 @@ def abon_ping(request):
text = '<span class="glyphicon glyphicon-ok"></span> %s' % _('ok ping, %d/%d loses') % ping_result text = '<span class="glyphicon glyphicon-ok"></span> %s' % _('ok ping, %d/%d loses') % ping_result
status = True status = True
else: else:
text = '<span class="glyphicon glyphicon-exclamation-sign"></span> %s' % _('no ping, %d/%d loses') % ping_result
text = '<span class="glyphicon glyphicon-exclamation-sign"></span> %s' % _(
'no ping, %d/%d loses') % ping_result
else: else:
text = '<span class="glyphicon glyphicon-ok"></span> %s' % _('ping ok') + ' ' + str(ping_result) text = '<span class="glyphicon glyphicon-ok"></span> %s' % _('ping ok') + ' ' + str(ping_result)
status = True status = True
@ -773,6 +712,8 @@ def abon_ping(request):
@mydefs.only_admins @mydefs.only_admins
def dials(request, gid, uid): def dials(request, gid, uid):
abon = get_object_or_404(models.Abon, pk=uid) abon = get_object_or_404(models.Abon, pk=uid)
if not request.user.has_perm('abonapp.can_view_abongroup', abon.group):
raise PermissionDenied
if hasattr(abon.group, 'pk') and abon.group.pk != int(gid): if hasattr(abon.group, 'pk') and abon.group.pk != int(gid):
return redirect('abonapp:dials', abon.group.pk, abon.pk) return redirect('abonapp:dials', abon.group.pk, abon.pk)
if abon.telephone is not None and abon.telephone != '': if abon.telephone is not None and abon.telephone != '':
@ -791,7 +732,7 @@ def dials(request, gid, uid):
@login_required @login_required
@mydefs.only_admins
@permission_required('abonapp.change_abon')
def save_user_dev_port(request, gid, uid): def save_user_dev_port(request, gid, uid):
if request.method != 'POST': if request.method != 'POST':
messages.error(request, _('Method is not POST')) messages.error(request, _('Method is not POST'))
@ -820,6 +761,7 @@ def save_user_dev_port(request, gid, uid):
@login_required @login_required
@permission_required('abonapp.add_abonstreet') @permission_required('abonapp.add_abonstreet')
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
def street_add(request, gid): def street_add(request, gid):
if request.method == 'POST': if request.method == 'POST':
frm = forms.AbonStreetForm(request.POST) frm = forms.AbonStreetForm(request.POST)
@ -839,10 +781,12 @@ def street_add(request, gid):
@login_required @login_required
@permission_required('abonapp.change_abonstreet') @permission_required('abonapp.change_abonstreet')
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
def street_edit(request, gid): def street_edit(request, gid):
try: try:
if request.method == 'POST': if request.method == 'POST':
streets_pairs = [(int(sid), sname) for sid, sname in zip(request.POST.getlist('sid'), request.POST.getlist('sname'))]
streets_pairs = [(int(sid), sname) for sid, sname in
zip(request.POST.getlist('sid'), request.POST.getlist('sname'))]
for sid, sname in streets_pairs: for sid, sname in streets_pairs:
street = models.AbonStreet.objects.get(pk=sid) street = models.AbonStreet.objects.get(pk=sid)
street.name = sname street.name = sname
@ -862,6 +806,7 @@ def street_edit(request, gid):
@login_required @login_required
@permission_required('abonapp.delete_abonstreet') @permission_required('abonapp.delete_abonstreet')
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
def street_del(request, gid, sid): def street_del(request, gid, sid):
try: try:
models.AbonStreet.objects.get(pk=sid, group=gid).delete() models.AbonStreet.objects.get(pk=sid, group=gid).delete()
@ -871,22 +816,70 @@ def street_del(request, gid, sid):
return redirect('abonapp:people_list', gid) return redirect('abonapp:people_list', gid)
@login_required
@permission_required('abonapp.can_view_additionaltelephones')
@permission_required('abonapp.can_view_abongroup', (models.AbonGroup, 'pk', 'gid'))
def tels(request, gid, uid):
abon = get_object_or_404(models.Abon, pk=uid)
telephones = abon.additional_telephones.all()
return render_to_text('abonapp/modal_additional_telephones.html', {
'telephones': telephones,
'gid': gid,
'uid': uid
}, request=request)
@login_required
@permission_required('abnapp.add_additionaltelephone')
def tel_add(request, gid, uid):
if request.method == 'POST':
frm = forms.AdditionalTelephoneForm(request.POST)
if frm.is_valid():
new_tel = frm.save(commit=False)
abon = get_object_or_404(models.Abon, pk=uid)
new_tel.abon = abon
new_tel.save()
messages.success(request, _('New telephone has been saved'))
return redirect('abonapp:abon_home', gid, uid)
else:
messages.error(request, _('fix form errors'))
else:
frm = forms.AdditionalTelephoneForm()
return render_to_text('abonapp/modal_add_phone.html', {
'form': frm,
'gid': gid,
'uid': uid
}, request=request)
@login_required
@permission_required('abnapp.delete_additionaltelephone')
def tel_del(request, gid, uid):
try:
tid = mydefs.safe_int(request.GET.get('tid'))
tel = models.AdditionalTelephone.objects.get(pk=tid)
tel.delete()
messages.success(request, _('Additional telephone successfully deleted'))
except models.AdditionalTelephone.DoesNotExist:
messages.error(request, _('Telephone not found'))
return redirect('abonapp:abon_home', gid, uid)
# API's # API's
def abons(request): def abons(request):
ablist = [{ ablist = [{
'id': abn.pk,
'tarif_id': abn.active_tariff().tariff.pk if abn.active_tariff() is not None else 0,
'ip': abn.ip_address.int_ip(),
'is_active': abn.is_active
} for abn in models.Abon.objects.all()]
'id': abn.pk,
'tarif_id': abn.active_tariff().tariff.pk if abn.active_tariff() is not None else 0,
'ip': abn.ip_address.int_ip(),
'is_active': abn.is_active
} for abn in models.Abon.objects.all()]
tarlist = [{ tarlist = [{
'id': trf.pk,
'speedIn': trf.speedIn,
'speedOut': trf.speedOut
} for trf in Tariff.objects.all()]
'id': trf.pk,
'speedIn': trf.speedIn,
'speedOut': trf.speedOut
} for trf in Tariff.objects.all()]
data = { data = {
'subscribers': ablist, 'subscribers': ablist,

30
accounts_app/forms.py

@ -1,12 +1,24 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django import forms
from .models import UserProfile
from guardian.forms import UserObjectPermissionsForm
from guardian.shortcuts import assign_perm, remove_perm
class SetupPerms(forms.ModelForm):
class Meta:
model = UserProfile
fields = ['user_permissions']
widgets = {
'user_permissions': forms.CheckboxSelectMultiple()
}
class MyUserObjectPermissionsForm(UserObjectPermissionsForm):
def save_obj_perms(self):
"""
Saves selected object permissions by creating new ones and removing
those which were not selected but already exists.
Should be called *after* form is validated.
"""
perms = set(self.cleaned_data[self.get_obj_perms_field_name()])
model_perms = set([c[0] for c in self.get_obj_perms_field_choices()])
init_perms = set(self.get_obj_perms_field_initial())
to_remove = (model_perms - perms) & init_perms
for perm in to_remove:
remove_perm(perm, self.user, self.obj)
for perm in perms - init_perms:
assign_perm(perm, self.user, self.obj)

70
accounts_app/locale/ru/LC_MESSAGES/django.po

@ -33,18 +33,6 @@ msgstr "Администраторы"
msgid "Groups" msgid "Groups"
msgstr "Группы" msgstr "Группы"
#: accounts_app/templates/accounts/group.html:16
msgid "The current distribution of rights for groups"
msgstr "Действующее распределение прав для группы"
#: accounts_app/templates/accounts/group.html:22
msgid "Available rights"
msgstr "Доступные права"
#: accounts_app/templates/accounts/group.html:36
msgid "Rights for the group"
msgstr "Права группы"
#: accounts_app/templates/accounts/group.html:44 #: accounts_app/templates/accounts/group.html:44
#: accounts_app/templates/accounts/profile_chgroup.html:20 #: accounts_app/templates/accounts/profile_chgroup.html:20
#: accounts_app/templates/accounts/settings/ch_info.html:66 #: accounts_app/templates/accounts/settings/ch_info.html:66
@ -58,22 +46,6 @@ msgstr "Сохранить"
msgid "Reset" msgid "Reset"
msgstr "Сбросить" msgstr "Сбросить"
#: accounts_app/templates/accounts/group_list.html:11
msgid "Admin groups list"
msgstr "Список групп администраторов"
#: accounts_app/templates/accounts/group_list.html:20
msgid "Group"
msgstr "Группа"
#: accounts_app/templates/accounts/group_list.html:40
msgid "Groups does not found"
msgstr "Нет групп"
#: accounts_app/templates/accounts/group_list.html:47
msgid "Add group"
msgstr "Добавить группу"
#: accounts_app/templates/accounts/index.html:8 #: accounts_app/templates/accounts/index.html:8
#: accounts_app/templates/accounts/settings/ch_info.html:37 #: accounts_app/templates/accounts/settings/ch_info.html:37
msgid "Telephone" msgid "Telephone"
@ -186,11 +158,47 @@ msgstr "Настройка прав"
msgid "Edit" msgid "Edit"
msgstr "Редактировать" msgstr "Редактировать"
msgid "Set a task"
msgstr "Дать задачу"
msgid "Please select an image" msgid "Please select an image"
msgstr "Пожалуйста выберите изображение" msgstr "Пожалуйста выберите изображение"
msgid "Avatar successfully changed" msgid "Avatar successfully changed"
msgstr "Аватар успешно изменён" msgstr "Аватар успешно изменён"
msgid "Access to groups"
msgstr "Доступ к группам"
msgid "The list of user groups to which the account has access"
msgstr "Список групп абонентов, к которым учётка имеет доступ"
msgid "The responsibility of the staff of the group of subscribers"
msgstr "Ответственность работника за группы абонентов"
msgid "Not set"
msgstr "Не найдено"
msgid "Change permission for that object"
msgstr "Изменение прав доступа для выбранного объекта"
msgid "Permissions has successfully updated"
msgstr "Права успешно обновлены"
msgid "Profile is superuser, permissions to change it makes no sense"
msgstr "Учётная запись является суперпользователем, разрешения менять нет смысла"
msgid "Staff account profile"
msgstr "Учётная запись работника"
msgid "Staff account profiles"
msgstr "Учётные записи работников"
msgid "Can view staff profile"
msgstr "Может просматривать учётку сотрудника"
msgid "Pick object for edit permissions"
msgstr "Выберите объект для редактирования прав доступа"
msgid "Pick the type of object"
msgstr "Выберите тип объекта"
msgid "Profile has been deleted"
msgstr "Учётная запись удалена"

19
accounts_app/migrations/0008_auto_20170927_1838.py

@ -0,0 +1,19 @@
# -*- 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': 'Учётные записи работников'},
),
]

23
accounts_app/models.py

@ -1,4 +1,5 @@
# -*- coding:utf-8 -*- # -*- coding:utf-8 -*-
import os
from django.db import models from django.db import models
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser, PermissionsMixin from django.contrib.auth.models import BaseUserManager, AbstractBaseUser, PermissionsMixin
from django.core.validators import RegexValidator from django.core.validators import RegexValidator
@ -7,7 +8,7 @@ from django.conf import settings
from photo_app.models import Photo from photo_app.models import Photo
DEFAULT_PICTURE = getattr(settings, 'DEFAULT_PICTURE', '/static/images/default-avatar.png')
DEFAULT_PICTURE = getattr(settings, 'DEFAULT_PICTURE', '/static/img/user_ava.gif')
TELEPHONE_REGEXP = getattr(settings, 'TELEPHONE_REGEXP', r'^\+[7,8,9,3]\d{10,11}$') TELEPHONE_REGEXP = getattr(settings, 'TELEPHONE_REGEXP', r'^\+[7,8,9,3]\d{10,11}$')
@ -79,15 +80,31 @@ class UserProfile(AbstractBaseUser, PermissionsMixin):
def get_big_ava(self): def get_big_ava(self):
if self.avatar: if self.avatar:
return self.avatar.big()
path = self.avatar.big()
if os.path.exists(path):
return path
else:
return DEFAULT_PICTURE
else: else:
return DEFAULT_PICTURE return DEFAULT_PICTURE
def get_min_ava(self): def get_min_ava(self):
if self.avatar: if self.avatar:
return self.avatar.min()
url_path = self.avatar.min()
real_path = url_path[1:]
if os.path.exists(real_path):
return url_path
else:
return DEFAULT_PICTURE
else: else:
return DEFAULT_PICTURE return DEFAULT_PICTURE
def __str__(self): def __str__(self):
return self.get_full_name() return self.get_full_name()
class Meta:
permissions = (
('can_view_userprofile', _('Can view staff profile')),
)
verbose_name = _('Staff account profile')
verbose_name_plural = _('Staff account profiles')

4
accounts_app/templates/accounts/acc_list.html

@ -25,7 +25,7 @@
{% for usr in users %} {% for usr in users %}
<tr> <tr>
<td><a href="{% url 'acc_app:other_profile' usr.id %}"> <td><a href="{% url 'acc_app:other_profile' usr.id %}">
<img width="50" src="{{ usr.avatar.min|default:"/static/img/user_ava.gif" }}"
<img width="50" src="{{ usr.get_min_ava }}"
alt="{{ usr.username }}"/> alt="{{ usr.username }}"/>
</a></td> </a></td>
<td><a href="{% url 'acc_app:other_profile' usr.id %}">{{ usr.username }}</a></td> <td><a href="{% url 'acc_app:other_profile' usr.id %}">{{ usr.username }}</a></td>
@ -39,7 +39,7 @@
title="Дать задание"> title="Дать задание">
<span class="glyphicon glyphicon-tasks"></span> <span class="glyphicon glyphicon-tasks"></span>
</a> </a>
<a href="{% url 'django_messages:messages_compose' %}?a={{ usr.id }}" class="btn btn-sm btn-info"
<a href="{ % url 'django_messages:messages_compose' % }?a={{ usr.id }}" class="btn btn-sm btn-info"
title="Отправить сообщение"> title="Отправить сообщение">
<span class="glyphicon glyphicon-envelope"></span> <span class="glyphicon glyphicon-envelope"></span>
</a> </a>

34
accounts_app/templates/accounts/ext.htm

@ -14,19 +14,32 @@
<div class="col-sm-3"> <div class="col-sm-3">
<div class="thumbnail"> <div class="thumbnail">
{% if userprofile.avatar %} {% if userprofile.avatar %}
<a href="{{ userprofile.avatar.big }}" class="thumbnail" target="_blank">
<img alt="ava" src="{{ userprofile.avatar.min }}"/>
<a href="{{ userprofile.get_big_ava }}" class="thumbnail" target="_blank">
<img alt="ava" src="{{ userprofile.get_min_ava }}"/>
</a> </a>
{% else %} {% else %}
<img alt="ava" src="/static/img/user_ava.gif"/> <img alt="ava" src="/static/img/user_ava.gif"/>
{% endif %} {% endif %}
<div class="caption btn-group btn-group-sm"> <div class="caption btn-group btn-group-sm">
{% if userprofile == request.user %} {% if userprofile == request.user %}
<a href="{% url 'acc_app:setup_info' %}" class="btn btn-primary btn-sm" role="button">
<span class="glyphicon glyphicon-edit"></span> {% trans 'Edit' %}</a>
<a href="{% url 'acc_app:setup_info' %}" class="btn btn-primary" role="button">
<span class="glyphicon glyphicon-edit"></span>
{% trans 'Edit' %}
</a>
{% endif %}
{% if request.user.is_superuser %}
{% if userprofile.is_superuser %}
<a href="{% url 'acc_app:setup_perms' userprofile.pk %}" class="btn btn-default" title="{% trans 'Profile is superuser, permissions to change it makes no sense' %}" data-toggle="tooltip">
<span class="glyphicon glyphicon-lock"></span>
{% trans 'Permission options' %}
</a>
{% else %}
<a href="{% url 'acc_app:setup_perms' userprofile.pk %}" class="btn btn-default btn-sm">
<span class="glyphicon glyphicon-lock"></span>
{% trans 'Permission options' %}
</a>
{% endif %}
{% endif %} {% endif %}
<a href="#" class="btn btn-default btn-sm disabled" role="button">
<span class="glyphicon glyphicon-star-empty"></span> {% trans 'Set a task' %}</a>
</div> </div>
</div> </div>
</div> </div>
@ -46,6 +59,15 @@
{% trans 'Groups' %} {% trans 'Groups' %}
</a> </a>
</li> </li>
{% if request.user.is_superuser %}
{% url 'acc_app:set_abon_groups_permission' uid as set_ag_perm %}
<li{% if set_ag_perm == request.path %} class="active"{% endif %}>
<a href="{{ set_ag_perm }}">
<span class="glyphicon glyphicon-lock"></span>
{% trans 'Access to groups' %}
</a>
</li>
{% endif %}
</ul> </ul>
<div class="tab-content"> <div class="tab-content">
<div class="tab-pane active"> <div class="tab-pane active">

50
accounts_app/templates/accounts/group.html

@ -1,50 +0,0 @@
{% extends 'base.html' %}
{% load i18n %}
{% block main %}
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'acc_app:accounts_list' %}">{% trans 'Administrators' %}</a></li>
<li><a href="{% url 'acc_app:groups_list' %}">{% trans 'Groups' %}</a></li>
<li class="active">{{ group.name }}</li>
</ol>
{% include 'message_block.html' %}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans 'The current distribution of rights for groups' %} <b>{{ group.name }}</b></h3>
</div>
<div class="panel-body">
<form role="form" action="{% url 'acc_app:group_link' group.id %}" method="post">{% csrf_token %}
<div class="choice_wrapper">
<label for="sel_left">{% trans 'Available rights' %}</label>
<select name="allrights" multiple id="sel_left">
{% for rgt in all_rights %}
<option value="{{ rgt.id }}">{{ rgt.content_type }} &lt;{{ rgt.name }}&gt;</option>
{% endfor %}
</select>
</div>
<ul class="select_choose">
<li><a href="javascript:chooser_select('sel_left','sel_right');" class="btn btn-blue"><i
class="black icon-arrow-right"></i></a></li>
<li><a href="javascript:chooser_select('sel_right','sel_left');" class="btn btn-blue"><i
class="black icon-arrow-left"></i></a></li>
</ul>
<div class="choice_wrapper">
<label for="sel_right">{% trans 'Rights for the group' %}</label>
<select name="group_rights" multiple id="sel_right">
{% for rgt in grp_rights %}
<option value="{{ rgt.id }}">{{ rgt.content_type }} &lt;{{ rgt.name }}&gt;</option>
{% endfor %}
</select>
</div>
<br/>
<input type="submit" value="{% trans 'Save' %}"> <input type="reset" value="{% trans 'Reset' %}">
</form>
</div>
</div>
{% endblock %}

58
accounts_app/templates/accounts/group_list.html

@ -1,58 +0,0 @@
{% extends 'base.html' %}
{% load i18n %}
{% block main %}
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'acc_app:accounts_list' %}">{% trans 'Administrators' %}</a></li>
<li class="active">{% trans 'Groups' %}</li>
</ol>
<h3>{% trans 'Admin groups list' %}</h3>
{% include 'message_block.html' %}
<div class="table-responsive">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th width="50">#</th>
<th>{% trans 'Group' %}</th>
<th class="col-sm-1">&mdash;</th>
</tr>
</thead>
<tbody>
{% for grp in groups %}
<tr>
<td>{{ grp.id }}</td>
<td><a href="{% url 'acc_app:group_link' grp.id %}">{{ grp.name }}</a></td>
<td class="btn-group">
<a href="#" class="btn btn-sm btn-info">
<span class="glyphicon glyphicon-edit"></span>
</a>
<a href="#" class="btn btn-sm btn-danger">
<span class="glyphicon glyphicon-remove"></span>
</a>
</td>
</tr>
{% empty %}
<tr>
<td colspan="3"><a href="#">{% trans 'Groups does not found' %}</a></td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<td colspan="3">
<a href="#" class="btn btn-primary btn-sm disabled" title="{% trans 'Add group' %}">
<span class="glyphicon glyphicon-plus"></span>
</a>
</td>
</tr>
</tfoot>
</table>
</div>
{% include 'toolbar_page.html' with pag=groups %}
{% endblock %}

34
accounts_app/templates/accounts/perms/objects_of_type.html

@ -0,0 +1,34 @@
{% extends 'base.html' %}
{% load i18n %}
{% block main %}
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'acc_app:accounts_list' %}">{% trans 'Administrators' %}</a></li>
<li><a href="{% url 'acc_app:other_profile' userprofile.pk %}">{{ userprofile.username }}</a></li>
<li><a href="{% url 'acc_app:perms_klasses' userprofile.pk klass %}">{% trans 'Permission options' %}</a></li>
<li class="active">&lt;{{ klass }}&gt; {{ klass_name }}</li>
</ol>
<h3>{% trans 'Pick object for edit permissions' %}</h3>
{% include 'message_block.html' %}
<div class="table-responsive">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>obj</th>
</tr>
</thead>
<tbody>
{% for obj in objects %}<tr><td>
<a href="{% url 'acc_app:perms_edit' userprofile.pk klass obj.pk %}">{{ obj }}</a>
</td></tr>{% endfor %}
</tbody>
</table>
</div>
{% include 'toolbar_page.html' with pag=objects %}
{% endblock %}

36
accounts_app/templates/accounts/perms/objects_types.html

@ -0,0 +1,36 @@
{% extends 'base.html' %}
{% load i18n %}
{% load acc_tags %}
{% block main %}
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'acc_app:accounts_list' %}">{% trans 'Administrators' %}</a></li>
<li><a href="{% url 'acc_app:other_profile' userprofile.pk %}">{{ userprofile.username }}</a></li>
<li class="active">{% trans 'Permission options' %}</li>
</ol>
<h3>{% trans 'Pick the type of object' %}</h3>
{% include 'message_block.html' %}
<div class="table-responsive">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>{% trans 'Group' %}</th>
</tr>
</thead>
<tbody>
{% for klass in klasses %}
<tr>
<td>
<a href="{% url 'acc_app:perms_klasses' userprofile.pk klass %}">&lt;{{ klass }}&gt; {% klass_name klass %}</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}

71
accounts_app/templates/accounts/perms/perms_edit.html

@ -0,0 +1,71 @@
{% extends 'base.html' %}
{% load i18n %}
{% load guardian_tags %}
{% block main %}
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'acc_app:accounts_list' %}">{% trans 'Administrators' %}</a></li>
<li><a href="{% url 'acc_app:other_profile' userprofile.pk %}">{{ userprofile.username }}</a></li>
<li><a href="{% url 'acc_app:setup_perms' userprofile.pk %}">{% trans 'Permission options' %}</a></li>
<li><a href="{% url 'acc_app:perms_klasses' userprofile.pk klass %}">&lt;{{ klass }}&gt; {{ klass_name }}</a>
</li>
<li class="active">{{ obj }}</li>
</ol>
<h3>{% trans 'Pick object for edit permissions' %}</h3>
{% include 'message_block.html' %}
{% if userprofile.is_superuser %}
<div class="alert alert-info alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
<span class="glyphicon glyphicon-info-sign"></span>
{% trans 'Profile is superuser, permissions to change it makes no sense' %}
</div>
{% endif %}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans 'Change permission for that object' %}</h3>
</div>
<div class="panel-body">
<form role="form" action="{% url 'acc_app:perms_edit' userprofile.pk klass obj.pk %}" method="post">{% csrf_token %}
{% get_obj_perms userprofile for obj as 'obj_perms' %}
{% for field in form %}
<div class="form-group">
<label for="{{ field.id_for_label }}" class="col-sm-3 control-label">{{ field.label }}</label>
<div class="col-sm-9">
<select multiple="multiple" id="{{ field.id_for_label }}" name="{{ field.html_name }}"
class="form-control">
{% for perm_value, perm_name in field.field.choices %}
{% if perm_value in obj_perms %}
<option value="{{ perm_value }}" selected>{{ perm_name }}</option>
{% else %}
<option value="{{ perm_value }}">{{ perm_name }}</option>
{% endif %}
{% empty %}
<option value="0">{% trans 'Not set' %}</option>
{% endfor %}
</select>
</div>
</div>
{% endfor %}
<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 %}

6
accounts_app/templates/accounts/profile_chgroup.html

@ -2,15 +2,15 @@
{% load i18n %} {% load i18n %}
{% block content %} {% block content %}
<legend>{% trans 'The responsibility of the administrator of the group of subscribers' %}</legend>
<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 %} <form action="{% url 'acc_app:profile_setup_group' userprofile.id %}" method="post" role="form">{% csrf_token %}
{% for ag in abongroups %} {% for ag in abongroups %}
<div class="checkbox"> <div class="checkbox">
<label> <label>
{% if userprofile in ag.profiles.all %} {% if userprofile in ag.profiles.all %}
<input name="ag" type="checkbox" value="{{ ag.id }}" checked/>
<input name="ag" type="checkbox" value="{{ ag.pk }}" checked/>
{% else %} {% else %}
<input name="ag" type="checkbox" value="{{ ag.id }}"/>
<input name="ag" type="checkbox" value="{{ ag.pk }}"/>
{% endif %} {% endif %}
{{ ag.title }} {{ ag.title }}
</label> </label>

25
accounts_app/templates/accounts/set_abon_groups_permission.html

@ -0,0 +1,25 @@
{% extends request.is_ajax|yesno:'nullcont.htm,accounts/ext.htm' %}
{% load i18n %}
{% block content %}
<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 %}
<div class="checkbox">
<label>
{% if ag.pk in picked_groups_ids %}
<input name="ag" type="checkbox" value="{{ ag.pk }}" checked/>
{% else %}
<input name="ag" type="checkbox" value="{{ ag.pk }}"/>
{% endif %}
{{ ag.title }}
</label>
</div>
{% endfor %}
<div class="btn-group">
<input type="submit" class="btn btn-primary" value="{% trans 'Save' %}">
<input type="reset" class="btn btn-default" value="{% trans 'Reset' %}">
</div>
</form>
{% endblock %}

11
accounts_app/templates/accounts/settings/ext.htm

@ -16,9 +16,7 @@
<form action="{% url 'acc_app:setup_avatar' %}" method="post" class="thumbnail" <form action="{% url 'acc_app:setup_avatar' %}" method="post" class="thumbnail"
enctype="multipart/form-data">{% csrf_token %} enctype="multipart/form-data">{% csrf_token %}
{% if user.avatar %}<img alt="ava" src="{{ user.avatar.min }}"/>
{% else %}<img alt="ava" src="/static/img/user_ava.gif"/>
{% endif %}
<img alt="ava" src="{{ user.get_min_ava }}"/>
<div class="caption"> <div class="caption">
<button type="submit" class="btn btn-primary">{% trans 'Save' %}</button> <button type="submit" class="btn btn-primary">{% trans 'Save' %}</button>
@ -36,13 +34,6 @@
{% trans 'Change self onfo' %} {% trans 'Change self onfo' %}
</a> </a>
</li> </li>
{% if user.is_superuser %}
<li>
<a href="#livetab_content" data-tab-remote="{% url 'acc_app:setup_perms' user.id %}">
{% trans 'Permission options' %}
</a>
</li>
{% endif %}
</ul> </ul>
<div class="tab-content"> <div class="tab-content">
<div class="tab-pane active"> <div class="tab-pane active">

14
accounts_app/templates/accounts/settings/permissions.html

@ -1,14 +0,0 @@
{% extends request.is_ajax|yesno:'nullcont.htm,accounts/settings/ext.htm' %}
{% block content %}
<form role="form" action="{% url 'acc_app:setup_perms' uid %}" method="post">{% csrf_token %}
{% for perm, pname in form.user_permissions.field.choices %}
<div class="checkbox">
<label>
<input type="checkbox">
{{ pname }}
</label>
</div>
{% endfor %}
</form>
{% endblock %}

14
accounts_app/templates/accounts/settings/test.html

@ -0,0 +1,14 @@
<p>
<label for="id_permissions">Permissions:</label>
<select multiple="multiple" id="id_permissions" name="permissions">
<option value="add_abongroup">Can add abon group</option>
<option value="can_add_ballance">Пополнение счёта</option>
<option value="can_view_abongroup" selected="selected">Can view subscriber group</option>
<option value="change_abongroup">Can change abon group</option>
<option value="delete_abongroup">Can delete abon group</option>
</select>
</p>

1
accounts_app/templatetags/__init__.py

@ -0,0 +1 @@
__author__ = 'bashmak'

18
accounts_app/templatetags/acc_tags.py

@ -0,0 +1,18 @@
from django import template
from django.db.models import Model
from django.apps import apps
from six import string_types, class_types
register = template.Library()
@register.simple_tag
def klass_name(klass):
if type(klass) is class_types and issubclass(klass, Model):
kl = klass
elif isinstance(klass, string_types):
app_label, model_name = klass.split('.', 1)
kl = apps.get_model(app_label, model_name)
else:
return 'Type not detected'
return kl._meta.verbose_name

8
accounts_app/urls.py

@ -20,13 +20,11 @@ urlpatterns = [
url(r'^(?P<uid>\d+)$', views.profile_show, name='other_profile'), url(r'^(?P<uid>\d+)$', views.profile_show, name='other_profile'),
url(r'^(?P<uid>\d+)/perms$', views.perms, name='setup_perms'), url(r'^(?P<uid>\d+)/perms$', views.perms, name='setup_perms'),
url(r'^(?P<uid>\d+)/perms/(?P<klass_name>[a-z_]+\.[a-zA-Z_]+)$', views.perms_klasses, name='perms_klasses'),
url(r'^(?P<uid>\d+)/perms/(?P<klass_name>[a-z_]+\.[a-zA-Z_]+)/(?P<obj_id>\d+)$', views.perms_edit, name='perms_edit'),
url(r'^(?P<uid>\d+)/chgroup$', views.chgroup, name='profile_setup_group'), url(r'^(?P<uid>\d+)/chgroup$', views.chgroup, name='profile_setup_group'),
url(r'^(?P<uid>\d+)/del$', views.delete_profile, name='delete_profile'), url(r'^(?P<uid>\d+)/del$', views.delete_profile, name='delete_profile'),
# назначить задание
url(r'^(?P<uid>\d+)/appoint_task$', views.appoint_task, name='appoint_task'),
url(r'^group/$', views.groups, name='groups_list'),
url(r'^group/(?P<uid>\d+)$', views.group, name='group_link')
url(r'^(?P<uid>\d+)/user_group_access$', views.set_abon_groups_permission, name='set_abon_groups_permission')
] ]

135
accounts_app/views.py

@ -1,10 +1,9 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.auth.decorators import login_required
from django.contrib.auth import authenticate, login, logout from django.contrib.auth import authenticate, login, logout
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import NoReverseMatch from django.core.urlresolvers import NoReverseMatch
from django.shortcuts import render, redirect, get_object_or_404, resolve_url
from django.contrib.auth.models import Group, Permission
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib import messages from django.contrib import messages
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from abonapp.models import AbonGroup from abonapp.models import AbonGroup
@ -12,6 +11,8 @@ from abonapp.models import AbonGroup
from photo_app.models import Photo from photo_app.models import Photo
from .models import UserProfile from .models import UserProfile
import mydefs import mydefs
from guardian.decorators import permission_required_or_403 as permission_required
from guardian.shortcuts import get_objects_for_user, assign_perm, remove_perm
@login_required @login_required
@ -62,6 +63,8 @@ def profile_show(request, uid=0):
return redirect('acc_app:other_profile', uid=request.user.id) return redirect('acc_app:other_profile', uid=request.user.id)
usr = get_object_or_404(UserProfile, id=uid) usr = get_object_or_404(UserProfile, id=uid)
if request.user != usr and not request.user.has_perm('accounts_app.can_view_userprofile', usr):
raise PermissionDenied
if request.method == 'POST': if request.method == 'POST':
usr.username = request.POST.get('username') usr.username = request.POST.get('username')
usr.fio = request.POST.get('fio') usr.fio = request.POST.get('fio')
@ -85,12 +88,14 @@ def chgroup(request, uid):
usr = request.user usr = request.user
else: else:
usr = get_object_or_404(UserProfile, id=uid) usr = get_object_or_404(UserProfile, id=uid)
if usr != request.user and not request.user.has_perm('accounts_app.change_userprofile', usr):
raise PermissionDenied
if request.method == 'POST': if request.method == 'POST':
ag = request.POST.getlist('ag') ag = request.POST.getlist('ag')
usr.abon_groups.clear() usr.abon_groups.clear()
usr.abon_groups.add(*[int(d) for d in ag]) usr.abon_groups.add(*[int(d) for d in ag])
usr.save() usr.save()
abongroups = AbonGroup.objects.all()
abongroups = AbonGroup.objects.only('pk', 'title')
return render(request, 'accounts/profile_chgroup.html', { return render(request, 'accounts/profile_chgroup.html', {
'uid': uid, 'uid': uid,
'userprofile': usr, 'userprofile': usr,
@ -155,7 +160,7 @@ def ch_info(request):
@login_required @login_required
@permission_required('acc_app.add_userprofile')
@permission_required('accounts_app.add_userprofile')
def create_profile(request): def create_profile(request):
if request.method == 'POST': if request.method == 'POST':
username = request.POST.get('username') username = request.POST.get('username')
@ -194,18 +199,20 @@ def create_profile(request):
@login_required @login_required
@mydefs.only_admins @mydefs.only_admins
def delete_profile(request, uid): def delete_profile(request, uid):
prf = get_object_or_404(UserProfile, id=uid)
if uid != request.user.id: if uid != request.user.id:
if not request.user.has_perm('acc_app.delete_userprofile'):
if not request.user.has_perm('acc_app.delete_userprofile', prf):
raise PermissionDenied raise PermissionDenied
prf = get_object_or_404(UserProfile, id=uid)
prf.delete() prf.delete()
messages.success(request, _('Profile has been deleted'))
return redirect('acc_app:accounts_list') return redirect('acc_app:accounts_list')
@login_required @login_required
@mydefs.only_admins @mydefs.only_admins
def acc_list(request): def acc_list(request):
users = UserProfile.objects.filter(is_admin=True)
users = UserProfile.objects.filter(is_admin=True).exclude(pk=request.user.pk)
users = get_objects_for_user(request.user, 'accounts_app.can_view_userprofile', users)
users = mydefs.pag_mn(request, users) users = mydefs.pag_mn(request, users)
return render(request, 'accounts/acc_list.html', { return render(request, 'accounts/acc_list.html', {
'users': users 'users': users
@ -213,54 +220,88 @@ def acc_list(request):
@login_required @login_required
@mydefs.only_admins
def perms(request, uid): def perms(request, uid):
profile = get_object_or_404(UserProfile, id=uid)
own_permissions = UserProfile.get_all_permissions(profile)
return render(request, 'accounts/settings/permissions.html', {
'uid': uid,
'own_permissions': own_permissions
if not request.user.is_superuser:
raise PermissionDenied
userprofile = get_object_or_404(UserProfile, id=uid)
klasses = (
'abonapp.AbonGroup', 'abonapp.Abon', 'accounts_app.UserProfile',
'abonapp.AbonTariff', 'abonapp.AbonStreet', 'devapp.Device',
'abonapp.PassportInfo', 'abonapp.AdditionalTelephone'
)
return render(request, 'accounts/perms/objects_types.html', {
'userprofile': userprofile,
'klasses': klasses
}) })
@login_required @login_required
@mydefs.only_admins
def groups(request):
grps = Group.objects.all()
grps = mydefs.pag_mn(request, grps)
return render(request, 'accounts/group_list.html', {
'groups': grps
def perms_klasses(request, uid, klass_name):
if not request.user.is_superuser:
raise PermissionDenied
from django.apps import apps
userprofile = get_object_or_404(UserProfile, pk=uid)
app_label, model_name = klass_name.split('.', 1)
klass = apps.get_model(app_label, model_name)
objects = klass.objects.all()
objects = mydefs.pag_mn(request, objects)
return render(request, 'accounts/perms/objects_of_type.html', {
'userprofile': userprofile,
'klass': klass_name,
'klass_name': klass._meta.verbose_name,
'objects': objects
}) })
@login_required @login_required
@mydefs.only_admins
def group(request, uid):
uid = mydefs.safe_int(uid)
grp = get_object_or_404(Group, id=uid)
if request.method == 'POST':
group_rights = filter(lambda x: x[0] == 'group_rights', request.POST.lists())[0][1]
grp.permissions.clear()
for grr in group_rights:
rid = mydefs.safe_int(grr)
grp.permissions.add(rid)
grp.save()
return redirect('acc_app:profile_group_link', id=uid)
grp_rights = grp.permissions.all()
all_rights = Permission.objects.exclude(group=grp)
return render(request, 'accounts/group.html', {
'group': grp,
'all_rights': all_rights,
'grp_rights': grp_rights
def perms_edit(request, uid, klass_name, obj_id):
if not request.user.is_superuser:
raise PermissionDenied
from django.apps import apps
from .forms import MyUserObjectPermissionsForm
userprofile = get_object_or_404(UserProfile, pk=uid)
app_label, model_name = klass_name.split('.', 1)
klass = apps.get_model(app_label, model_name)
obj = get_object_or_404(klass, pk=obj_id)
frm = MyUserObjectPermissionsForm(userprofile, obj, request.POST or None)
if request.method == 'POST' and frm.is_valid():
frm.save_obj_perms()
messages.success(request, _('Permissions has successfully updated'))
return render(request, 'accounts/perms/perms_edit.html', {
'userprofile': userprofile,
'obj': obj,
'form': frm,
'klass': klass_name,
'klass_name': klass._meta.verbose_name
}) })
@login_required @login_required
@mydefs.only_admins
def appoint_task(req, uid):
uid = mydefs.safe_int(uid)
url = resolve_url('taskapp:add')
return redirect("%s?rp=%d" % (url, uid))
def set_abon_groups_permission(request, uid):
# Only superuser can change object permissions
if not request.user.is_superuser:
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 = 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)
return redirect('acc_app:set_abon_groups_permission', uid)
abongroups = AbonGroup.objects.only('pk', 'title')
return render(request, 'accounts/set_abon_groups_permission.html', {
'uid': uid,
'userprofile': userprofile,
'abongroups': abongroups,
'picked_groups_ids': picked_groups
})

26
agent/core.py

@ -19,8 +19,6 @@ class NasNetworkError(Exception):
def check_input_type(*types): def check_input_type(*types):
def real_check(fn): def real_check(fn):
def wrapped(self, *args): def wrapped(self, *args):
if len(types) != len(args):
raise AttributeError("length of @types must be equivalent for length of @args")
for param_type, param in zip(types, args): for param_type, param in zip(types, args):
if not isinstance(param, param_type): if not isinstance(param, param_type):
raise TypeError("%s must be %s, but is %s" % (str(param), str(param_type), type(param))) raise TypeError("%s must be %s, but is %s" % (str(param), str(param_type), type(param)))
@ -32,12 +30,12 @@ def check_input_type(*types):
# Общается с NAS'ом # Общается с NAS'ом
class BaseTransmitter(metaclass=ABCMeta): class BaseTransmitter(metaclass=ABCMeta):
@abstractmethod @abstractmethod
@check_input_type(AbonStruct)
@check_input_type(set)
def add_user_range(self, user_list): def add_user_range(self, user_list):
"""добавляем список абонентов в NAS""" """добавляем список абонентов в NAS"""
@abstractmethod @abstractmethod
@check_input_type(AbonStruct)
@check_input_type(set)
def remove_user_range(self, users): def remove_user_range(self, users):
"""удаляем список абонентов""" """удаляем список абонентов"""
@ -97,7 +95,7 @@ class BaseTransmitter(metaclass=ABCMeta):
""" """
@abstractmethod @abstractmethod
@check_input_type(str)
@check_input_type(str, int)
def ping(self, host, count=10): def ping(self, host, count=10):
""" """
:param host: ip адрес в текстовом виде, например '192.168.0.1' :param host: ip адрес в текстовом виде, например '192.168.0.1'
@ -126,11 +124,13 @@ class BaseTransmitter(metaclass=ABCMeta):
def sync_nas(self, users_from_db): def sync_nas(self, users_from_db):
list_for_add, list_for_del = self._diff_users(users_from_db) list_for_add, list_for_del = self._diff_users(users_from_db)
print('FOR DELETE')
for ld in list_for_del:
print(ld)
print('FOR ADD')
for la in list_for_add:
print(la)
self.remove_user_range( list_for_del )
self.add_user_range( list_for_add )
if len(list_for_del) > 0:
print('FOR DELETE')
for ld in list_for_del:
print(ld)
self.remove_user_range(list_for_del)
if len(list_for_add) > 0:
print('FOR ADD')
for la in list_for_add:
print(la)
self.add_user_range(list_for_add)

46
agent/mod_mikrotik.py

@ -6,7 +6,7 @@ from hashlib import md5
from .core import BaseTransmitter, NasFailedResult, NasNetworkError from .core import BaseTransmitter, NasFailedResult, NasNetworkError
from mydefs import ping from mydefs import ping
from .structs import TariffStruct, AbonStruct, IpStruct from .structs import TariffStruct, AbonStruct, IpStruct
from . import settings
from . import settings as local_settings
from django.conf import settings from django.conf import settings
import re import re
@ -144,15 +144,17 @@ class ApiRos:
class TransmitterManager(BaseTransmitter, metaclass=ABCMeta): class TransmitterManager(BaseTransmitter, metaclass=ABCMeta):
def __init__(self, login=None, password=None, ip=None, port=None): def __init__(self, login=None, password=None, ip=None, port=None):
ip = ip or settings.NAS_IP
ip = ip or getattr(local_settings, 'NAS_IP')
if ip is None:
raise NasNetworkError('Не передан ip адрес NAS')
if not ping(ip): if not ping(ip):
raise NasNetworkError('NAS %s не пингуется' % ip) raise NasNetworkError('NAS %s не пингуется' % ip)
try: try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, port or settings.NAS_PORT))
s.connect((ip, port or getattr(local_settings, 'NAS_PORT', 8728)))
self.s = s self.s = s
self.ar = ApiRos(s) self.ar = ApiRos(s)
self.ar.login(login or settings.NAS_LOGIN, password or settings.NAS_PASSW)
self.ar.login(login or getattr(local_settings, 'NAS_LOGIN'), password or getattr(local_settings, 'NAS_PASSW'))
except ConnectionRefusedError: except ConnectionRefusedError:
raise NasNetworkError('Подключение к %s отклонено (Connection Refused)' % ip) raise NasNetworkError('Подключение к %s отклонено (Connection Refused)' % ip)
@ -246,8 +248,11 @@ class QueueManager(TransmitterManager, metaclass=ABCMeta):
return self._exec_cmd(['/queue/simple/remove', '=.id=' + getattr(q, 'queue_id', '')]) return self._exec_cmd(['/queue/simple/remove', '=.id=' + getattr(q, 'queue_id', '')])
def remove_range(self, q_ids): def remove_range(self, q_ids):
if q_ids is not None and len(q_ids) > 0:
try:
#q_ids = [q.queue_id for q in q_ids]
return self._exec_cmd(['/queue/simple/remove', '=numbers=' + ','.join(q_ids)]) return self._exec_cmd(['/queue/simple/remove', '=numbers=' + ','.join(q_ids)])
except TypeError as e:
print(e)
def update(self, user): def update(self, user):
if not isinstance(user, AbonStruct): if not isinstance(user, AbonStruct):
@ -272,10 +277,10 @@ class QueueManager(TransmitterManager, metaclass=ABCMeta):
# читаем шейпер, возващаем записи о шейпере # читаем шейпер, возващаем записи о шейпере
def read_queue_iter(self): def read_queue_iter(self):
queues = self._exec_cmd_iter(['/queue/simple/print', '=detail'])
for queue in queues:
if queue[0] == '!done': return
sobj = self._build_shape_obj(queue[1])
for code, dat in self._exec_cmd_iter(['/queue/simple/print', '=detail']):
if code == '!done':
return
sobj = self._build_shape_obj(dat)
if sobj is not None: if sobj is not None:
yield sobj yield sobj
@ -346,7 +351,7 @@ class IpAddressListManager(TransmitterManager, metaclass=ABCMeta):
if len(ids) > 0: if len(ids) > 0:
return self._exec_cmd([ return self._exec_cmd([
'/ip/firewall/address-list/remove', '/ip/firewall/address-list/remove',
'numbers=' + ','.join(ids)
'=numbers=*%s' % ',*'.join(ids)
]) ])
def find(self, ip, list_name): def find(self, ip, list_name):
@ -359,10 +364,14 @@ class IpAddressListManager(TransmitterManager, metaclass=ABCMeta):
]) ])
def read_ips_iter(self, list_name): def read_ips_iter(self, list_name):
return self._exec_cmd([
ips = self._exec_cmd_iter([
'/ip/firewall/address-list/print', 'where', '/ip/firewall/address-list/print', 'where',
'?list=%s' % list_name
'?list=%s' % list_name,
'?dynamic=no'
]) ])
for code, dat in ips:
if dat != {}:
yield IpAddressListObj(dat['=address'], dat['=.id'])
def disable(self, user): def disable(self, user):
r = IpAddressListManager.find(self, user.ip, LIST_USERS_ALLOWED) r = IpAddressListManager.find(self, user.ip, LIST_USERS_ALLOWED)
@ -498,6 +507,15 @@ class MikrotikTransmitter(QueueManager, IpAddressListManager):
def read_users(self): def read_users(self):
# shapes is ShapeItem # shapes is ShapeItem
# allowed_ips = IpAddressListManager.read_ips_iter(self, LIST_USERS_ALLOWED)
queues = QueueManager.read_queue_iter(self)
allowed_ips = set(IpAddressListManager.read_ips_iter(self, LIST_USERS_ALLOWED))
queues = set(q for q in QueueManager.read_queue_iter(self) if q.ip in allowed_ips)
ips_from_queues = set([q.ip for q in queues])
allowed_ips = set(allowed_ips)
# удаляем ip адреса которые есть в firewall/address-list и нет соответствующих в queues
diff = list(allowed_ips - ips_from_queues)
if len(diff) > 0:
IpAddressListManager.remove_range(self, diff)
return queues return queues

4
clientsideapp/templates/clientsideapp/ext.html

@ -93,7 +93,9 @@
<div id="footer"> <div id="footer">
<div class="container"> <div class="container">
<p class="text-muted">&copy;DN</p>
<p class="text-muted">
Напишите разработчику <i>djing-developer@yandex.ru</i>.
</p>
</div> </div>
</div> </div>

30
cron.py

@ -10,43 +10,25 @@ from mydefs import LogicError
def main(): def main():
tm = None
users = Abon.objects.all() users = Abon.objects.all()
for user in users: for user in users:
try: try:
# бдим за услугами абонента # бдим за услугами абонента
user.bill_service(user) user.bill_service(user)
# если нет ip то и нет смысла лезть в NAS
if user.ip_address is None:
continue
# а есть-ли у абонента доступ к услуге
if not user.is_access():
continue
# строим структуру агента
ab = user.build_agent_struct()
if ab is None:
# если не построилась структура агента, значит нет ip
# а если нет ip то и синхронизировать абонента без ip нельзя
continue
# обновляем абонента если он статический. Иначе его обновит dhcp
if user.opt82 is None:
if tm is None:
tm = Transmitter()
tm.update_user(ab)
except (NasNetworkError, NasFailedResult) as er: except (NasNetworkError, NasFailedResult) as er:
print("Error:", er) print("Error:", er)
except LogicError as er: except LogicError as er:
print("Notice:", er) print("Notice:", er)
tm = Transmitter()
users = Abon.objects.filter(is_dynamic_ip=False, is_active=True).exclude(current_tariff=None)
tm.sync_nas(users)
if __name__ == "__main__": if __name__ == "__main__":
try: try:
main() main()
except (NasNetworkError, NasFailedResult) as e: except (NasNetworkError, NasFailedResult) as e:
print('NAS:', e)
print("Error while sync nas:", e)
except LogicError as e:
print("Notice while sync nas:", e)

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

@ -300,3 +300,12 @@ msgstr "Посмотреть устройство"
msgid "Eltex switch" msgid "Eltex switch"
msgstr "Элтекс свич" msgstr "Элтекс свич"
msgid "Can view device"
msgstr "Может видеть устройство"
msgid "Device"
msgstr "Устройство"
msgid "Can toggle ports"
msgstr "Может переключать порты"

51
devapp/migrations/0001_initial.py

@ -1,51 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2016-06-28 23:51
from django.db import migrations, models
import django.db.models.deletion
import mydefs
class Migration(migrations.Migration):
initial = True
dependencies = [
]
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.CreateModel(
name='PortStates',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('state_json_info', models.TextField()),
('port', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='devapp.Port')),
],
),
migrations.AlterUniqueTogether(
name='port',
unique_together={('device', 'num')},
),
]

90
devapp/migrations/0001_squashed_0007_auto_20170816_1109.py

@ -0,0 +1,90 @@
# -*- 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_auto_20160909_1018.py

@ -1,22 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2016-09-09 07:18
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('devapp', '0001_initial'),
]
operations = [
migrations.AlterModelTable(
name='device',
table='dev',
),
migrations.AlterModelTable(
name='port',
table='dev_port',
),
]

6
devapp/migrations/0004_device_user_group.py → devapp/migrations/0002_device_user_group.py

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-02-22 19:24
# Generated by Django 1.9 on 2017-09-04 16:16
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models
@ -9,8 +9,8 @@ import django.db.models.deletion
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('abonapp', '0011_auto_20170222_2224'),
('devapp', '0003_device_map_dot'),
('abonapp', '0001_squashed_0022_auto_20170816_1109'),
('devapp', '0001_squashed_0007_auto_20170816_1109'),
] ]
operations = [ operations = [

23
devapp/migrations/0003_auto_20170927_1838.py

@ -0,0 +1,23 @@
# -*- 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'},
),
]

20
devapp/migrations/0003_device_map_dot.py

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-01-28 22:03
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('mapapp', '0001_initial'),
('devapp', '0002_auto_20160909_1018'),
]
operations = [
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'),
),
]

20
devapp/migrations/0005_auto_20170502_2232.py

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-05-02 19:32
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('devapp', '0004_device_user_group'),
]
operations = [
migrations.AlterField(
model_name='device',
name='devtype',
field=models.CharField(choices=[('Dl', 'DLink switch'), ('Pn', 'PON OLT')], default='Dl', max_length=2),
),
]

48
devapp/migrations/0006_auto_20170705_1403.py

@ -1,48 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-07-05 14:03
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import djing.fields
class Migration(migrations.Migration):
dependencies = [
('devapp', '0005_auto_20170502_2232'),
]
operations = [
migrations.RemoveField(
model_name='portstates',
name='port',
),
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.DeleteModel(
name='PortStates',
),
]

20
devapp/migrations/0007_auto_20170816_1109.py

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-08-16 11:09
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('devapp', '0006_auto_20170705_1403'),
]
operations = [
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),
),
]

11
devapp/models.py

@ -8,6 +8,7 @@ from . import dev_types
from mapapp.models import Dot from mapapp.models import Dot
from subprocess import run from subprocess import run
from django.conf import settings from django.conf import settings
from django.utils.translation import ugettext_lazy as _
DEVICE_TYPES = ( DEVICE_TYPES = (
@ -34,6 +35,11 @@ class Device(models.Model):
class Meta: class Meta:
db_table = 'dev' db_table = 'dev'
permissions = (
('can_view_device', _('Can view device')),
)
verbose_name = _('Device')
verbose_name_plural = _('Devices')
def get_abons(self): def get_abons(self):
pass pass
@ -69,6 +75,11 @@ class Port(models.Model):
class Meta: class Meta:
db_table = 'dev_port' db_table = 'dev_port'
unique_together = (('device', 'num')) unique_together = (('device', 'num'))
permissions = (
('can_toggle_ports', _('Can toggle ports')),
)
verbose_name = _('Port')
verbose_name_plural = _('Ports')
def dev_post_save_signal(sender, instance, **kwargs): def dev_post_save_signal(sender, instance, **kwargs):

37
devapp/templates/devapp/custom_dev_page/onu.html

@ -14,25 +14,28 @@
</div> </div>
<div class="panel-body"> <div class="panel-body">
<ul class="list-group"> <ul class="list-group">
<li class="list-group-item">{% trans 'Ip address' %}: {{ dev.ip_address }}</li>
<li class="list-group-item">{% trans 'Mac' %}: {{ dev.mac_addr }}</li>
<li class="list-group-item">{% trans 'Description' %} {{ dev.comment }}</li>
<li class="list-group-item">{% trans 'Ip address' %}: {{ dev.ip_address }}</li>
<li class="list-group-item">{% trans 'Mac' %}: {{ dev.mac_addr }}</li>
<li class="list-group-item">{% trans 'Description' %} {{ dev.comment }}</li>
{% for da in dev_accs %} {% for da in dev_accs %}
<li class="list-group-item">{% trans 'Attached user' %}:
{% if da.group %}
<a href="{% url 'abonapp:abon_home' da.group.pk da.pk %}" target="_blank">{{ da.get_full_name }}</a>
{% else %}
{{ da.get_full_name }}
{% endif %}
</li>
<li class="list-group-item">{% trans 'Attached user' %}:
{% if da.group %}
<a href="{% url 'abonapp:abon_home' da.group.pk da.pk %}"
target="_blank">{{ da.get_full_name }}</a>
{% else %}
{{ da.get_full_name }}
{% endif %}
</li>
{% endfor %} {% endfor %}
{% if dev.parent_dev %}
<li class="list-group-item">
{% with pdev=dev.parent_dev pdgrp=dev.parent_dev.user_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>
{% endwith %}
</li>
{% endif %}
{% if dev.parent_dev %}
<li class="list-group-item">
{% with pdev=dev.parent_dev pdgrp=dev.parent_dev.user_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>
{% endwith %}
</li>
{% endif %}
</ul> </ul>
</div> </div>
</div> </div>

12
devapp/templates/devapp/devices_null_group.html

@ -38,19 +38,20 @@
</thead> </thead>
<tbody> <tbody>
{% with can_del_dev=perms.devapp.delete_device can_change_dev=perms.devapp.change_device %}
{% for dev in devices %} {% for dev in devices %}
<tr> <tr>
<td><a href="{% url 'devapp:view' dev.user_group.pk|default:0 dev.id %}">{{ dev.ip_address }}</a></td>
<td><a href="{% url 'devapp:view' dev.user_group.pk|default:0 dev.pk %}">{{ dev.ip_address }}</a></td>
<td>{{ dev.comment }}</td> <td>{{ dev.comment }}</td>
<td>{{ dev.get_devtype_display }}</td> <td>{{ dev.get_devtype_display }}</td>
<td class="btn-group btn-group-sm"> <td class="btn-group btn-group-sm">
{% if perms.devapp.delete_device %}
<a href="{% url 'devapp:del' dev.user_group.pk|default:0 dev.id %}" class="btn btn-danger btn-sm">
{% if can_del_dev %}
<a href="{% url 'devapp:del' dev.user_group.pk|default:0 dev.pk %}" class="btn btn-danger btn-sm">
<span class="glyphicon glyphicon-remove"></span> <span class="glyphicon glyphicon-remove"></span>
</a> </a>
{% endif %} {% endif %}
{% if perms.devapp.change_device %}
<a href="{% url 'devapp:edit' dev.user_group.pk|default:0 dev.id %}" class="btn btn-default btn-sm">
{% if can_change_dev %}
<a href="{% url 'devapp:edit' dev.user_group.pk|default:0 dev.pk %}" class="btn btn-default btn-sm">
<span class="glyphicon glyphicon-edit"></span> <span class="glyphicon glyphicon-edit"></span>
</a> </a>
{% endif %} {% endif %}
@ -61,6 +62,7 @@
<td colspan="4">{% trans 'Devices does not found' %}. <a href="{% url 'devapp:add' 0 %}">{% trans 'Create' %}</a></td> <td colspan="4">{% trans 'Devices does not found' %}. <a href="{% url 'devapp:add' 0 %}">{% trans 'Create' %}</a></td>
</tr> </tr>
{% endfor %} {% endfor %}
{% endwith %}
</tbody> </tbody>
<tfoot> <tfoot>

34
devapp/views.py

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.auth.decorators import login_required
from django.contrib.gis.shortcuts import render_to_text from django.contrib.gis.shortcuts import render_to_text
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.db.models import Q from django.db.models import Q
@ -15,13 +15,18 @@ from mydefs import pag_mn, res_success, res_error, only_admins, ping, order_help
from .forms import DeviceForm, PortForm from .forms import DeviceForm, PortForm
from abonapp.models import AbonGroup, Abon from abonapp.models import AbonGroup, Abon
from django.conf import settings from django.conf import settings
from guardian.decorators import permission_required_or_403 as permission_required
from guardian.shortcuts import get_objects_for_user
@login_required @login_required
@only_admins @only_admins
def devices(request, grp): def devices(request, grp):
group = get_object_or_404(AbonGroup, pk=grp) group = get_object_or_404(AbonGroup, pk=grp)
devs = Device.objects.filter(user_group=grp)
if not request.user.has_perm('abonapp.can_view_abongroup', group):
raise PermissionDenied
devs = Device.objects.filter(user_group=grp).only('comment', 'mac_addr', 'devtype', 'user_group', 'pk',
'ip_address')
# фильтр # фильтр
dr, field = order_helper(request) dr, field = order_helper(request)
@ -41,7 +46,7 @@ def devices(request, grp):
@login_required @login_required
@only_admins @only_admins
def devices_null_group(request): def devices_null_group(request):
devs = Device.objects.filter(user_group=None)
devs = Device.objects.filter(user_group=None).only('comment', 'devtype', 'user_group', 'pk', 'ip_address')
# фильтр # фильтр
dr, field = order_helper(request) dr, field = order_helper(request)
if field: if field:
@ -71,10 +76,12 @@ def devdel(request, did):
@login_required @login_required
@only_admins
@permission_required('devapp.can_view_device')
def dev(request, grp, devid=0): def dev(request, grp, devid=0):
devinst = get_object_or_404(Device, id=devid) if devid != 0 else None
user_group = get_object_or_404(AbonGroup, pk=grp) user_group = get_object_or_404(AbonGroup, pk=grp)
if not request.user.has_perm('abonapp.can_view_abongroup', user_group):
raise PermissionDenied
devinst = get_object_or_404(Device, id=devid) if devid != 0 else None
already_dev = None already_dev = None
if request.method == 'POST': if request.method == 'POST':
@ -294,7 +301,7 @@ def add_single_port(request, grp, did):
@login_required @login_required
@only_admins
@permission_required('devapp.can_view_device')
def devview(request, did): def devview(request, did):
ports = None ports = None
uptime = 0 uptime = 0
@ -318,7 +325,7 @@ def devview(request, did):
except DeviceDBException as e: except DeviceDBException as e:
messages.error(request, e) messages.error(request, e)
return render(request, 'devapp/custom_dev_page/'+template_name, {
return render(request, 'devapp/custom_dev_page/' + template_name, {
'dev': dev, 'dev': dev,
'ports': ports, 'ports': ports,
'uptime': uptime, 'uptime': uptime,
@ -327,7 +334,7 @@ def devview(request, did):
@login_required @login_required
@only_admins
@permission_required('devapp.can_toggle_ports')
def toggle_port(request, did, portid, status=0): def toggle_port(request, did, portid, status=0):
portid = int(portid) portid = int(portid)
status = int(status) status = int(status)
@ -338,9 +345,9 @@ def toggle_port(request, did, portid, status=0):
manager = dev.get_manager_klass()(dev.ip_address, dev.man_passw) manager = dev.get_manager_klass()(dev.ip_address, dev.man_passw)
ports = manager.get_ports() ports = manager.get_ports()
if status: if status:
ports[portid-1].enable()
ports[portid - 1].enable()
else: else:
ports[portid-1].disable()
ports[portid - 1].disable()
else: else:
messages.warning(request, _('Not Set snmp device password')) messages.warning(request, _('Not Set snmp device password'))
else: else:
@ -353,7 +360,8 @@ def toggle_port(request, did, portid, status=0):
@login_required @login_required
@only_admins @only_admins
def group_list(request): def group_list(request):
groups = AbonGroup.objects.all()
groups = AbonGroup.objects.all().order_by('title')
groups = get_objects_for_user(request.user, 'abonapp.can_view_abongroup', klass=groups, accept_global_perms=False)
return render(request, 'devapp/group_list.html', { return render(request, 'devapp/group_list.html', {
'groups': groups 'groups': groups
}) })
@ -365,6 +373,8 @@ def search_dev(request):
if word is None: if word is None:
results = [{'id': 0, 'text': ''}] results = [{'id': 0, 'text': ''}]
else: else:
results = Device.objects.filter(Q(comment__icontains=word) | Q(ip_address=word))[:16]
results = Device.objects.filter(
Q(comment__icontains=word) | Q(ip_address=word)
).only('pk', 'ip_address', 'comment')[:16]
results = [{'id': dev.pk, 'text': "%s: %s" % (dev.ip_address, dev.comment)} for dev in results] results = [{'id': dev.pk, 'text': "%s: %s" % (dev.ip_address, dev.comment)} for dev in results]
return HttpResponse(dumps(results, ensure_ascii=False)) return HttpResponse(dumps(results, ensure_ascii=False))

2
dialing_app/models.py

@ -1,6 +1,6 @@
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from djing import settings
from django.conf import settings
class AsteriskCDR(models.Model): class AsteriskCDR(models.Model):

14
dialing_app/templates/index.html

@ -21,22 +21,22 @@
<tbody> <tbody>
{% for log in logs %} {% for log in logs %}
<tr> <tr>
<td class="btn-group btn-group-sm btn-group-justify">
<td class="btn-group btn-group-xs btn-group-justify">
<button class="btn btn-default player-btn disabled"> <button class="btn btn-default player-btn disabled">
<span class="glyphicon glyphicon-play"></span> <span class="glyphicon glyphicon-play"></span>
<audio preload="metadata" src="{{ log.path_to_media }}/{{ log.calldate|date:"YmdHi" }}-{{ log.src }}-{{ log.dst }}.wav"></audio>
<audio preload="metadata" src="{{ log.path_to_media }}/{{ log.calldate|date:"Y/m/d/H_i" }}-{{ log.src }}-{{ log.dst }}.wav"></audio>
</button> </button>
<a href="{{ log.path_to_media }}/{{ log.calldate|date:"YmdHi" }}-{{ log.src }}-{{ log.dst }}.wav" class="btn btn-default disabled" target="_blank">
<a href="{{ log.path_to_media }}/{{ log.calldate|date:"Y/m/d/H_i" }}-{{ log.src }}-{{ log.dst }}.wav" class="btn btn-default disabled" target="_blank" title="{% trans 'Download' %}">
<span class="glyphicon glyphicon-download-alt"></span> <span class="glyphicon glyphicon-download-alt"></span>
</a> </a>
</td> </td>
<td>{{ log.calldate|date:'d E Y, H:i:s' }}</td>
<td>{{ log.calldate|date:'d M, H:i:s' }}</td>
<td>{{ log.src|abon_if_telephone|safe }}</td> <td>{{ log.src|abon_if_telephone|safe }}</td>
<td>{{ log.dst|abon_if_telephone|safe }}</td> <td>{{ log.dst|abon_if_telephone|safe }}</td>
<td>{{ log.duration }}</td> <td>{{ log.duration }}</td>
<td>{{ log.start|date:'d E Y, H:i:s' }}</td>
<td>{{ log.answer|date:'d E Y, H:i:s' }}</td>
<td>{{ log.end|date:'d E Y, H:i:s' }}</td>
<td>{{ log.start|date:'d M, H:i:s' }}</td>
<td>{{ log.answer|date:'d M, H:i:s' }}</td>
<td>{{ log.end|date:'d M, H:i:s' }}</td>
<td>{{ log.locate_disposition }}</td> <td>{{ log.locate_disposition }}</td>
</tr> </tr>
{% empty %} {% empty %}

2
dialing_app/views.py

@ -2,6 +2,7 @@ from django.contrib.auth.decorators import login_required
from django.contrib import messages from django.contrib import messages
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from guardian.decorators import permission_required_or_403 as permission_required
from abonapp.models import Abon from abonapp.models import Abon
from mydefs import only_admins, pag_mn from mydefs import only_admins, pag_mn
@ -9,6 +10,7 @@ from .models import AsteriskCDR
@login_required @login_required
@permission_required('dialing_app.change_asteriskcdr')
@only_admins @only_admins
def home(request): def home(request):
logs = AsteriskCDR.objects.exclude(userfield='request').order_by('-calldate') logs = AsteriskCDR.objects.exclude(userfield='request').order_by('-calldate')

3
django_messages/__init__.py

@ -1,3 +0,0 @@
VERSION = (0, 5, 3,)
__version__ = '.'.join(map(str, VERSION))
default_app_config = 'django_messages.apps.DjangoMessagesConfig'

112
django_messages/admin.py

@ -1,112 +0,0 @@
from django import forms
from django.conf import settings
from django.utils.translation import gettext_lazy as _
from django.contrib import admin
from django.contrib.auth.models import Group
from django_messages.utils import get_user_model
User = get_user_model()
if "notification" in settings.INSTALLED_APPS and getattr(settings, 'DJANGO_MESSAGES_NOTIFY', True):
from notification import models as notification
else:
notification = None
from django_messages.models import Message
class MessageAdminForm(forms.ModelForm):
"""
Custom AdminForm to enable messages to groups and all users.
"""
group = forms.ChoiceField(label=_('group'), required=False,
help_text=_('Creates the message optionally for all users or a group of users.'))
def __init__(self, *args, **kwargs):
super(MessageAdminForm, self).__init__(*args, **kwargs)
self.fields['group'].choices = self._get_group_choices()
self.fields['recipient'].required = True
def _get_group_choices(self):
return [('', u'---------'), ('all', _('All users'))] + \
[(group.pk, group.name) for group in Group.objects.all()]
class Meta:
model = Message
fields = ('sender', 'recipient', 'group', 'parent_msg', 'subject',
'body', 'sent_at', 'read_at', 'replied_at', 'sender_deleted_at',
'recipient_deleted_at')
class MessageAdmin(admin.ModelAdmin):
form = MessageAdminForm
fieldsets = (
(None, {
'fields': (
'sender',
('recipient', 'group'),
),
}),
(_('Message'), {
'fields': (
'parent_msg',
'subject', 'body',
),
'classes': ('monospace' ),
}),
(_('Date/time'), {
'fields': (
'sent_at', 'read_at', 'replied_at',
'sender_deleted_at', 'recipient_deleted_at',
),
'classes': ('collapse', 'wide'),
}),
)
list_display = ('subject', 'sender', 'recipient', 'sent_at', 'read_at')
list_filter = ('sent_at', 'sender', 'recipient')
search_fields = ('subject', 'body')
raw_id_fields = ('sender', 'recipient', 'parent_msg')
def save_model(self, request, obj, form, change):
"""
Saves the message for the recipient and looks in the form instance
for other possible recipients. Prevents duplication by excludin the
original recipient from the list of optional recipients.
When changing an existing message and choosing optional recipients,
the message is effectively resent to those users.
"""
obj.save()
if notification:
# Getting the appropriate notice labels for the sender and recipients.
if obj.parent_msg is None:
sender_label = 'messages_sent'
recipients_label = 'messages_received'
else:
sender_label = 'messages_replied'
recipients_label = 'messages_reply_received'
# Notification for the sender.
notification.send([obj.sender], sender_label, {'message': obj,})
if form.cleaned_data['group'] == 'all':
# send to all users
recipients = User.objects.exclude(pk=obj.recipient.pk)
else:
# send to a group of users
recipients = []
group = form.cleaned_data['group']
if group:
group = Group.objects.get(pk=group)
recipients.extend(
list(group.user_set.exclude(pk=obj.recipient.pk)))
# create messages for all found recipients
for user in recipients:
obj.pk = None
obj.recipient = user
obj.save()
if notification:
# Notification for the recipient.
notification.send([user], recipients_label, {'message' : obj,})
admin.site.register(Message, MessageAdmin)

6
django_messages/apps.py

@ -1,6 +0,0 @@
from django.apps import AppConfig
from django.utils.translation import ugettext_lazy as _
class DjangoMessagesConfig(AppConfig):
name = 'django_messages'
verbose_name = _('Messages')

7
django_messages/context_processors.py

@ -1,7 +0,0 @@
from django_messages.models import inbox_count_for
def inbox(request):
if request.user.is_authenticated():
return {'messages_inbox_count': inbox_count_for(request.user)}
else:
return {}

21
django_messages/fields.py

@ -1,21 +0,0 @@
"""
Based on http://www.djangosnippets.org/snippets/595/
by sopelkin
"""
from django.forms import widgets
from django_messages.utils import get_user_model, get_username_field
User = get_user_model()
class CommaSeparatedUserInput(widgets.Input):
input_type = 'text'
def render(self, name, value, attrs=None):
if value is None:
value = ''
elif isinstance(value, (list, tuple)):
value = (', '.join([getattr(user, get_username_field()) for user in value]))
return super(CommaSeparatedUserInput, self).render(name, value, attrs)

67
django_messages/forms.py

@ -1,67 +0,0 @@
from django import forms
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
if "notification" in settings.INSTALLED_APPS and getattr(settings, 'DJANGO_MESSAGES_NOTIFY', True):
from notification import models as notification
else:
notification = None
from django_messages.models import Message
from accounts_app.models import UserProfile
class ComposeForm(forms.Form):
"""
A simple default form for private messages.
"""
recipient = forms.ModelMultipleChoiceField(
label=_(u"Recipient"),
widget=forms.SelectMultiple(attrs={'class': 'form-control'}),
queryset=UserProfile.objects.filter(is_admin=True),
)
#recipient = CommaSeparatedUserField(label=_(u"Recipient"))
subject = forms.CharField(
label=_(u"Subject"),
max_length=140,
widget=forms.TextInput(attrs={'class': 'form-control'})
)
body = forms.CharField(label=_(u"Body"),
widget=forms.Textarea(attrs={'rows': '12', 'cols':'55', 'class': 'form-control'}))
def __init__(self, *args, **kwargs):
recipient_filter = kwargs.pop('recipient_filter', None)
super(ComposeForm, self).__init__(*args, **kwargs)
if recipient_filter is not None:
self.fields['recipient']._recipient_filter = recipient_filter
def save(self, sender, parent_msg=None):
recipients = self.cleaned_data['recipient']
subject = self.cleaned_data['subject']
body = self.cleaned_data['body']
message_list = []
for r in recipients:
msg = Message(
sender = sender,
recipient = r,
subject = subject,
body = body,
)
if parent_msg is not None:
msg.parent_msg = parent_msg
parent_msg.replied_at = timezone.now()
parent_msg.save()
msg.save()
message_list.append(msg)
if notification:
if parent_msg is not None:
notification.send([sender], "messages_replied", {'message': msg,})
notification.send([r], "messages_reply_received", {'message': msg,})
else:
notification.send([sender], "messages_sent", {'message': msg,})
notification.send([r], "messages_received", {'message': msg,})
return message_list

317
django_messages/locale/ar/LC_MESSAGES/django.po

@ -1,317 +0,0 @@
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
#
# Ossama M. Khayat <okhayat@yahoo.com>, 2009.
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-10-14 04:23+0300\n"
"PO-Revision-Date: 2009-11-02 00:41+0300\n"
"Last-Translator: Ossama M. Khayat <okhayat@yahoo.com>\n"
"Language-Team: Arabic <doc@arabeyes.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Lokalize 1.0\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
#: admin.py:13 forms.py:20 models.py:52 templates/messages/outbox.html:8
#: templates/messages/view.html:12
msgid "Recipient"
msgstr "المستلم"
#: admin.py:15
msgid "group"
msgstr "مجموعة"
#: admin.py:16
msgid "Creates the message optionally for all users or a group of users."
msgstr "ينشئ الرسالة اختياريا لجميع المستخدمين او لمجموعة من المستخدمين."
#: admin.py:23
msgid "All users"
msgstr "جميع المستخدمين"
#: admin.py:38 models.py:88
msgid "Message"
msgstr "الرسالة"
#: admin.py:45
msgid "Date/time"
msgstr "التاريخ/الوقت"
#: fields.py:53
#, python-format
msgid "The following usernames are incorrect: %(users)s"
msgstr "أسماء المستخدمين التالي ذكرهم غير صحيحة: %(users)s"
#: forms.py:21 models.py:49 templates/messages/inbox.html:8
#: templates/messages/outbox.html:8 templates/messages/trash.html:8
#: templates/messages/view.html:6
msgid "Subject"
msgstr "الموضوع"
#: forms.py:22 models.py:50
msgid "Body"
msgstr "المحتوى"
#: management.py:9
msgid "Message Received"
msgstr "تم استلام الرسالة"
#: management.py:9
msgid "you have received a message"
msgstr "وصلتك رسالة"
#: management.py:10
msgid "Message Sent"
msgstr "تم إرسال الرسالة"
#: management.py:10
msgid "you have sent a message"
msgstr "قمت بإرسال رسالة"
#: management.py:11
msgid "Message Replied"
msgstr "تم الرد على الرسالة"
#: management.py:11
msgid "you have replied to a message"
msgstr "قمت بالرد على الرسالة"
#: management.py:12
msgid "Reply Received"
msgstr "تم استلام الرد"
#: management.py:12
msgid "you have received a reply to a message"
msgstr "استملت رداً على رسالة"
#: management.py:13
msgid "Message Deleted"
msgstr "تم حذف الرسالة"
#: management.py:13
msgid "you have deleted a message"
msgstr "قمت بحذف رسالة"
#: management.py:14
msgid "Message Recovered"
msgstr "تم استرجاع الرسالة"
#: management.py:14
msgid "you have undeleted a message"
msgstr "قمت باسترجاع رسالة"
#: models.py:51 templates/messages/inbox.html:8
#: templates/messages/trash.html:8 templates/messages/view.html:8
msgid "Sender"
msgstr "المرسل"
#: models.py:53
msgid "Parent message"
msgstr "الرسالة الأساسية"
#: models.py:54
msgid "sent at"
msgstr "أرسلت في"
#: models.py:55
msgid "read at"
msgstr "قُرأت في"
#: models.py:56
msgid "replied at"
msgstr "رُدّ عليها في"
#: models.py:57
msgid "Sender deleted at"
msgstr "حذفها المُرسل في"
#: models.py:58
msgid "Recipient deleted at"
msgstr "حذفها المستلم في"
#: models.py:89
msgid "Messages"
msgstr "الرسائل"
#: utils.py:27
#, python-format
msgid "New Message: %(subject)s"
msgstr "رسالة جديدة: %(subject)s"
#: views.py:78 views.py:112
msgid "Message successfully sent."
msgstr "تم إرسال الرسالة بنجاح."
#: views.py:118
#, python-format
msgid ""
"%(sender)s wrote:\n"
"%(body)s"
msgstr ""
"كتب %(sender)s:\n"
"%(body)s"
#: views.py:122
#, python-format
msgid "Re: %(subject)s"
msgstr "رد: %(subject)s"
#: views.py:158
msgid "Message successfully deleted."
msgstr "تم حذف الرسالة بنجاح."
#: views.py:185
msgid "Message successfully recovered."
msgstr "تم استرجاع الرسالة بنجاح."
#: templates/messages/base.html:8 templates/messages/inbox.html:4
#: templates/messages/new_message.html:10
msgid "Inbox"
msgstr "الوارد"
#: templates/messages/base.html:9 templates/messages/outbox.html:4
msgid "Sent Messages"
msgstr "الرسائل المرسلة"
#: templates/messages/base.html:10
msgid "New Message"
msgstr "رسالة جديدة"
#: templates/messages/base.html:11
msgid "Trash"
msgstr "الحاوية"
#: templates/messages/compose.html:4
msgid "Compose Message"
msgstr "أكتب رسالة"
#: templates/messages/compose.html:9
msgid "Send"
msgstr "أرسل"
#: templates/messages/inbox.html:8
msgid "Received"
msgstr "استُلمت"
#: templates/messages/inbox.html:8 templates/messages/outbox.html:8
#: templates/messages/trash.html:8
msgid "Action"
msgstr "إجراء"
#: templates/messages/inbox.html:20 templates/messages/outbox.html:17
#: templates/messages/trash.html:17 templates/messages/view.html:11
msgid "DATETIME_FORMAT"
msgstr "DATETIME_FORMAT"
#: templates/messages/inbox.html:21 templates/messages/outbox.html:18
msgid "delete"
msgstr "حذف"
#: templates/messages/inbox.html:27 templates/messages/outbox.html:24
#: templates/messages/trash.html:24
msgid "No messages."
msgstr "لا توجد رسائل."
#: templates/messages/new_message.html:1
#, python-format
msgid ""
"Hello %(recipient)s,\n"
"\n"
"you received a private message from %(sender)s with\n"
"the following contents:"
msgstr ""
"مرحباً %(recipient)s،\n"
"\n"
"وصلتك رسالة خاصة من %(sender)s\n"
"تحتوي ما يلي:"
#: templates/messages/new_message.html:9
#, python-format
msgid "Sent from %(site_url)s"
msgstr "أرسلت من %(site_url)s"
#: templates/messages/new_message.html:11 templates/messages/view.html:18
msgid "Reply"
msgstr "رد"
#: templates/messages/outbox.html:8
msgid "Sent"
msgstr "أرسل"
#: templates/messages/trash.html:4
msgid "Deleted Messages"
msgstr "الرسائل المحذوفة"
#: templates/messages/trash.html:8 templates/messages/view.html:10
msgid "Date"
msgstr "التاريخ"
#: templates/messages/trash.html:18
msgid "undelete"
msgstr "استرجاع"
#: templates/messages/trash.html:27
msgid ""
"Deleted Messages are removed from the trash at unregular intervals, don't "
"rely on this feature for long-time storage."
msgstr ""
"تتم إزالة الرسائل المحذوفة من الحاوية على فترات زمنيّة متفاوتة، "
"فلا تعتمد على هذه الميزة للتخزين الطويل المدى."
#: templates/messages/view.html:4
msgid "View Message"
msgstr "مشاهدة الرسالة"
#: templates/messages/view.html:20
msgid "Delete"
msgstr "حذف"
#: templates/notification/messages_deleted/notice.html:1
#, python-format
msgid ""
"You have deleted the message <a href=\"%(message_url)s\">%(message)s</a>."
msgstr "قمت بحذف الرسالة <a href=\"%(message_url)s\">%(message)s</a>."
#: templates/notification/messages_received/notice.html:2
#, python-format
msgid ""
"You have received the message <a href=\"%(message_url)s\">%(message)s</a> "
"from %(message_sender)s."
msgstr ""
"وصلتك الرسالة <a href=\"%(message_url)s\">%(message)s</a> "
"من %(message_sender)s."
#: templates/notification/messages_recovered/notice.html:1
#, python-format
msgid ""
"You have recovered the message <a href=\"%(message_url)s\">%(message)s</a>."
msgstr "قمت باسترجاع الرسالة <a href=\"%(message_url)s\">%(message)s</a>."
#: templates/notification/messages_replied/notice.html:2
#, python-format
msgid ""
"You have replied to <a href=\"%(message_url)s\">%(message_parent_msg)s</a> "
"from %(message_recipient)s."
msgstr ""
"قمت بالرد الرسائل <a href=\"%(message_url)s\">%(message_parent_msg)s</a> "
"من %(message_recipient)s."
#: templates/notification/messages_reply_received/notice.html:2
#, python-format
msgid "%(message_sender)s has sent you a reply to %(message_parent_msg)s."
msgstr "أرسل لك %(message_sender)s رداً على %(message_parent_msg)s."
#: templates/notification/messages_sent/notice.html:2
#, python-format
msgid ""
"You have sent the message <a href=\"%(message_url)s\">%(message)s</a> to %"
"(message_recipient)s."
msgstr ""
"قمت بإرسالة الرسالة <a href=\"%(message_url)s\">%(message)s</a> إلى %"
"(message_recipient)s."

398
django_messages/locale/cs/LC_MESSAGES/django.po

@ -1,398 +0,0 @@
# Czech translation.
# Radim Sückr <radim.suckr@gmail.com>, 2016
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-01-01 12:29+0100\n"
"PO-Revision-Date: 2015-01-01 12:29+0100\n"
"Last-Translator: Radim Sückr <radim.suckr@gmail.com>\n"
"Language-Team: \n"
"Language: cs\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
#: admin.py:21
msgid "group"
msgstr "Skupina"
#: admin.py:22
msgid "Creates the message optionally for all users or a group of users."
msgstr "Volitelně vytváří zprávu pro všechny uživatele nebo skupinu uživatelů."
#: admin.py:30
msgid "All users"
msgstr "Všichni uživatelé"
#: admin.py:48 models.py:91
msgid "Message"
msgstr "Zpráva"
#: admin.py:55
msgid "Date/time"
msgstr "Datum/čas"
#: apps.py:6 models.py:92
msgid "Messages"
msgstr "Zprávy"
#: fields.py:56
#, python-format
msgid "The following usernames are incorrect: %(users)s"
msgstr "Následující uživatelská jména nejsou správně: %(users)s"
#: forms.py:18 models.py:55 templates/django_messages/outbox.html:10
#: templates/django_messages/view.html:14
msgid "Recipient"
msgstr "Příjemce"
#: forms.py:19 models.py:52 templates/django_messages/inbox.html:10
#: templates/django_messages/outbox.html:10
#: templates/django_messages/trash.html:10
#: templates/django_messages/view.html:8
msgid "Subject"
msgstr "Předmět"
#: forms.py:20 models.py:53
msgid "Body"
msgstr "Obsah"
#: management.py:9
msgid "Message Received"
msgstr "Zpráva přijata"
#: management.py:9
msgid "you have received a message"
msgstr "přišla vám zpráva"
#: management.py:10
msgid "Message Sent"
msgstr "Zpráva odeslána"
#: management.py:10
msgid "you have sent a message"
msgstr "odeslali jste zprávu"
#: management.py:11
msgid "Message Replied"
msgstr "Zpráva zodpovězena"
#: management.py:11
msgid "you have replied to a message"
msgstr "odpověděli jste na zprávu"
#: management.py:12
msgid "Reply Received"
msgstr "Odpověď přijata"
#: management.py:12
msgid "you have received a reply to a message"
msgstr "přišla vám odpověď na zprávu"
#: management.py:13
msgid "Message Deleted"
msgstr "Zpráva smazána"
#: management.py:13
msgid "you have deleted a message"
msgstr "smazali jste zprávu"
#: management.py:14
msgid "Message Recovered"
msgstr "Zpráva obnovena"
#: management.py:14
msgid "you have undeleted a message"
msgstr "obnovili jste smazanou zprávu"
#: models.py:54 templates/django_messages/inbox.html:10
#: templates/django_messages/trash.html:10
#: templates/django_messages/view.html:10
msgid "Sender"
msgstr "Odesílatel"
#: models.py:56
msgid "Parent message"
msgstr "Předchozí zpráva"
#: models.py:57
msgid "sent at"
msgstr "odesláno"
#: models.py:58
msgid "read at"
msgstr "přečteno"
#: models.py:59
msgid "replied at"
msgstr "zodpovězeno"
#: models.py:60
msgid "Sender deleted at"
msgstr "Odesílatel smazal zprávu"
#: models.py:61
msgid "Recipient deleted at"
msgstr "Příjemce smazal zprávu"
#: templates/django_messages/base.html:8 templates/django_messages/inbox.html:6
#: templates/django_messages/new_message.html:13
msgid "Inbox"
msgstr "Příchozí zprávy"
#: templates/django_messages/base.html:9
#: templates/django_messages/outbox.html:6
msgid "Sent Messages"
msgstr "Odchozí zprávy"
#: templates/django_messages/base.html:10
msgid "New Message"
msgstr "Nová zpráva"
#: templates/django_messages/base.html:11
msgid "Trash"
msgstr "Koš"
#: templates/django_messages/compose.html:4
msgid "Compose Message"
msgstr "Napsat zprávu"
#: templates/django_messages/compose.html:10
msgid "Send"
msgstr "Odeslat"
#: templates/django_messages/inbox.html:10
msgid "Received"
msgstr "Přijato"
#: templates/django_messages/inbox.html:10
#: templates/django_messages/outbox.html:10
#: templates/django_messages/trash.html:10
msgid "Action"
msgstr "Akce"
#: templates/django_messages/inbox.html:22
#: templates/django_messages/outbox.html:19
#: templates/django_messages/trash.html:19
#: templates/django_messages/view.html:13
msgid "DATETIME_FORMAT"
msgstr "j. E Y, H:i"
#: templates/django_messages/inbox.html:23
#: templates/django_messages/outbox.html:20
msgid "delete"
msgstr "smazat"
#: templates/django_messages/inbox.html:29
#: templates/django_messages/outbox.html:26
#: templates/django_messages/trash.html:26
msgid "No messages."
msgstr "Žádné zprávy."
#: templates/django_messages/new_message.html:4
#, python-format
msgid ""
"Hello %(recipient)s,\n"
"\n"
"you received a private message from %(sender)s with\n"
"the following contents:"
msgstr ""
"Dobrý den %(recipient)s,\n"
"\n"
"máte novou soukromou zprávu od %(sender)s\n"
"s následujícím obsahem:"
#: templates/django_messages/new_message.html:12
#, python-format
msgid "Sent from %(site_url)s"
msgstr "Odesláno z %(site_url)s"
#: templates/django_messages/new_message.html:14
#: templates/django_messages/view.html:20
msgid "Reply"
msgstr "Odpovědět"
#: templates/django_messages/outbox.html:10
msgid "Sent"
msgstr "Odesláno"
#: templates/django_messages/trash.html:6
msgid "Deleted Messages"
msgstr "Smazané zprávy"
#: templates/django_messages/trash.html:10
#: templates/django_messages/view.html:12
msgid "Date"
msgstr "Datum"
#: templates/django_messages/trash.html:20
msgid "undelete"
msgstr "obnovit"
#: templates/django_messages/trash.html:29
msgid ""
"Deleted Messages are removed from the trash at unregular intervals, don't "
"rely on this feature for long-time storage."
msgstr ""
"Smazané zprávy jsou z koše odstraňovány v nepravidelných intervalech, "
"nespoléhejte se na koš jako dlouhodobé úložiště."
#: templates/django_messages/view.html:6
msgid "View Message"
msgstr "Zobrazit zprávu"
#: templates/django_messages/view.html:22
msgid "Delete"
msgstr "Smazat"
#: templates/notification/messages_deleted/full.txt:1
#, python-format
msgid "You have deleted the message '%(message)s'."
msgstr "Smazali jste zprávu '%(message)s'."
#: templates/notification/messages_deleted/notice.html:1
#, python-format
msgid ""
"You have deleted the message <a href=\"%(message_url)s\">%(message)s</a>."
msgstr ""
"Smazali jste zprávu <a href=\"%(message_url)s\">%(message)s</a>."
#: templates/notification/messages_received/full.txt:1
#, python-format
msgid ""
"%(message_sender)s has sent you a message:\n"
"\n"
"%(message)s\n"
"\n"
"%(message_body)s\n"
"\n"
"http://%(current_site)s%(message_url)s"
msgstr ""
"%(message_sender)s vám napsal/a zprávu:\n"
"\n"
"%(message)s\n"
"\n"
"%(message_body)s\n"
"\n"
"http://%(current_site)s%(message_url)s"
#: templates/notification/messages_received/notice.html:2
#, python-format
msgid ""
"You have received the message <a href=\"%(message_url)s\">%(message)s</a> "
"from %(message_sender)s."
msgstr ""
"Přišla vám zpráva <a href=\"%(message_url)s\">%(message)s</a> "
"od %(message_sender)s."
#: templates/notification/messages_received/short.txt:1
#: templates/notification/messages_reply_received/short.txt:1
#, python-format
msgid "%(notice)s by %(message_sender)s"
msgstr "%(notice)s od %(message_sender)s"
#: templates/notification/messages_recovered/full.txt:1
#, python-format
msgid "You have recovered the message '%(message)s'."
msgstr "Obnovili jste zprávu '%(message)s'."
#: templates/notification/messages_recovered/notice.html:1
#, python-format
msgid ""
"You have recovered the message <a href=\"%(message_url)s\">%(message)s</a>."
msgstr ""
"Obnovili jste zprávu <a href=\"%(message_url)s\">%(message)s</a>."
#: templates/notification/messages_replied/full.txt:1
#, python-format
msgid ""
"You have replied to '%(message_parent_msg)s' from %(message_recipient)s."
msgstr ""
"Odpověděli jste na '%(message_parent_msg)s' od %(message_recipient)s."
#: templates/notification/messages_replied/notice.html:2
#, python-format
msgid ""
"You have replied to <a href=\"%(message_url)s\">%(message_parent_msg)s</a> "
"from %(message_recipient)s."
msgstr ""
"Odpověděli jste na <a href=\"%(message_url)s\">%(message_parent_msg)s</a> "
"od %(message_recipient)s."
#: templates/notification/messages_reply_received/full.txt:1
#, python-format
msgid ""
"%(message_sender)s replied to '%(message_parent_msg)s':\n"
"\n"
"%(message)s\n"
"\n"
"%(message_body)s\n"
"\n"
"http://%(current_site)s%(message_url)s"
msgstr ""
"%(message_sender)s odpověděl/a na '%(message_parent_msg)s':\n"
"\n"
"%(message)s\n"
"\n"
"%(message_body)s\n"
"\n"
"http://%(current_site)s%(message_url)s"
#: templates/notification/messages_reply_received/notice.html:2
#, python-format
msgid "%(message_sender)s has sent you a reply to %(message_parent_msg)s."
msgstr "%(message_sender)s vám poslal/a odpověď na %(message_parent_msg)s."
#: templates/notification/messages_sent/full.txt:1
#, python-format
msgid "You have sent the message '%(message)s' to %(message_recipient)s."
msgstr "Odeslali jste zprávu '%(message)s' uživateli %(message_recipient)s."
#: templates/notification/messages_sent/notice.html:2
#, python-format
msgid ""
"You have sent the message <a href=\"%(message_url)s\">%(message)s</a> to "
"%(message_recipient)s."
msgstr ""
"Odeslali jste zprávu <a href=\"%(message_url)s\">%(message)s</a> uživateli "
"%(message_recipient)s."
#: utils.py:26
#, python-format
msgid ""
"%(sender)s wrote:\n"
"%(body)s"
msgstr ""
"%(sender)s napsal:\n"
"%(body)s"
#: utils.py:54
#, python-format
msgid "Re%(prefix)s: %(subject)s"
msgstr "Re%(prefix)s: %(subject)s"
#: utils.py:60
#, python-format
msgid "New Message: %(subject)s"
msgstr "Nová zpráva: %(subject)s"
#: views.py:79 views.py:116
msgid "Message successfully sent."
msgstr "Zpráva úspěšně odeslána."
#: views.py:98 views.py:194
#, python-format
msgid "Re: %(subject)s"
msgstr "Re: %(subject)s"
#: views.py:159
msgid "Message successfully deleted."
msgstr "Zpráva úspěšně smazána."
#: views.py:186
msgid "Message successfully recovered."
msgstr "Zpráva úspěšně obnovena."

367
django_messages/locale/da/LC_MESSAGES/django.po

@ -1,367 +0,0 @@
# django-messages in Danish.
# django-messages på Dansk.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# Michael Lind Mortensen <illio@cs.au.dk>, 2009.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-09-11 12:31-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: admin.py:13 forms.py:20 models.py:52 templates/messages/outbox.html:7
#: templates/messages/view.html:12
msgid "Recipient"
msgstr "Modtager"
#: admin.py:15
msgid "group"
msgstr "gruppe"
#: admin.py:16
msgid "Creates the message optionally for all users or a group of users."
msgstr "Skaber beskeden for alle brugere eller en gruppe af brugere."
#: admin.py:23
msgid "All users"
msgstr "Alle brugere"
#: admin.py:38 models.py:88
msgid "Message"
msgstr "Beskeder"
#: admin.py:45
msgid "Date/time"
msgstr "Dato/tid"
#: fields.py:53
#, python-format
msgid "The following usernames are incorrect: %(users)s"
msgstr "De følgende brugernavne er forkerte: %(users)s"
#: forms.py:21 models.py:49 templates/messages/inbox.html:7
#: templates/messages/outbox.html:7 templates/messages/trash.html:7
#: templates/messages/view.html:6
msgid "Subject"
msgstr "Emne"
#: forms.py:22 models.py:50
msgid "Body"
msgstr "Indhold"
#: management.py:9
msgid "Message Received"
msgstr "Besked Modtaget"
#: management.py:9
msgid "you have received a message"
msgstr "du har modtaget en besked"
#: management.py:10
msgid "Message Sent"
msgstr "Besked Afsendt"
#: management.py:10
msgid "you have sent a message"
msgstr "du har sendt en besked"
#: management.py:11
msgid "Message Replied"
msgstr "Besked Besvaret"
#: management.py:11
msgid "you have replied to a message"
msgstr "du har besvaret en besked"
#: management.py:12
msgid "Reply Received"
msgstr "Svar Modtaget"
#: management.py:12
msgid "you have received a reply to a message"
msgstr "du har modtaget en besvarelse på en besked"
#: management.py:13
msgid "Message Deleted"
msgstr "Besked Slettet"
#: management.py:13
msgid "you have deleted a message"
msgstr "du har slettet en besked"
#: management.py:14
msgid "Message Recovered"
msgstr "Besked Genskabt"
#: management.py:14
msgid "you have undeleted a message"
msgstr "du har genskabt en besked"
#: models.py:51 templates/messages/inbox.html:7
#: templates/messages/trash.html:7 templates/messages/view.html:8
msgid "Sender"
msgstr "Afsender"
#: models.py:53
msgid "Parent message"
msgstr "Stambesked"
#: models.py:54
msgid "sent at"
msgstr "sendt"
#: models.py:55
msgid "read at"
msgstr "læst"
#: models.py:56
msgid "replied at"
msgstr "besvaret"
#: models.py:57
msgid "Sender deleted at"
msgstr "Afsender slettet"
#: models.py:58
msgid "Recipient deleted at"
msgstr "Modtager slettet"
#: models.py:89
msgid "Messages"
msgstr "Beskeder"
#: utils.py:27
#, python-format
msgid "New Message: %(subject)s"
msgstr "Ny besked: %(subject)s"
#: views.py:78 views.py:112
msgid "Message successfully sent."
msgstr "Besked sendt succesfuldt."
#: views.py:118
#, python-format
msgid ""
"%(sender)s wrote:\n"
"%(body)s"
msgstr ""
"%(sender)s skrev:\n"
"%(body)s"
#: views.py:122
#, python-format
msgid "Re: %(subject)s"
msgstr "SV: %(subject)s"
#: views.py:158
msgid "Message successfully deleted."
msgstr "Besked slettet succesfuldt."
#: views.py:185
msgid "Message successfully recovered."
msgstr "Besked genskabt succesfuldt."
#: templates/messages/base.html:8 templates/messages/inbox.html:4
#: templates/messages/new_message.html:10
msgid "Inbox"
msgstr "Indboks"
#: templates/messages/base.html:9 templates/messages/outbox.html:4
msgid "Sent Messages"
msgstr "Sendte Beskeder"
#: templates/messages/base.html:10
msgid "New Message"
msgstr "Ny Besked"
#: templates/messages/base.html:11
msgid "Trash"
msgstr "Papirkurv"
#: templates/messages/compose.html:4
msgid "Compose Message"
msgstr "Skriv Ny Besked"
#: templates/messages/compose.html:9
msgid "Send"
msgstr "Send"
#: templates/messages/inbox.html:7
msgid "Received"
msgstr "Modtaget"
#: templates/messages/inbox.html:7 templates/messages/outbox.html:7
#: templates/messages/trash.html:7
msgid "Action"
msgstr "Handling"
#: templates/messages/inbox.html:19 templates/messages/outbox.html:16
#: templates/messages/trash.html:16 templates/messages/view.html:11
msgid "DATETIME_FORMAT"
msgstr "DATETIME_FORMAT"
#: templates/messages/inbox.html:20 templates/messages/outbox.html:17
msgid "delete"
msgstr "slet"
#: templates/messages/new_message.html:1
#, python-format
msgid ""
"Hello %(recipient)s,\n"
"\n"
"you received a private message from %(sender)s with\n"
"the following contents:"
msgstr ""
"Goddag %(recipient)s,\n"
"\n"
"du har modtaget en privat besked fra %(sender)s med\n"
"følgende indhold:"
#: templates/messages/new_message.html:9
#, python-format
msgid "Sent from %(site_url)s"
msgstr "Sendt fra %(site_url)s"
#: templates/messages/new_message.html:11 templates/messages/view.html:18
msgid "Reply"
msgstr "Besvar"
#: templates/messages/outbox.html:7
msgid "Sent"
msgstr "Sendt"
#: templates/messages/trash.html:4
msgid "Deleted Messages"
msgstr "Slettede Beskeder"
#: templates/messages/trash.html:7 templates/messages/view.html:10
msgid "Date"
msgstr "Dato"
#: templates/messages/trash.html:17
msgid "undelete"
msgstr "genskab"
#: templates/messages/trash.html:23
msgid ""
"Deleted Messages are removed from the trash at unregular intervals, don't "
"rely on this feature for long-time storage."
msgstr ""
"Slettede beskeder fjernes fra papirkurven med jævne mellemrum. Lad være med "
"at regne med denne funktion til langtidslagring."
#: templates/messages/view.html:4
msgid "View Message"
msgstr "Læs Besked"
#: templates/messages/view.html:20
msgid "Delete"
msgstr "Slet"
#: templates/notification/messages_deleted/notice.html:1
#, python-format
msgid ""
"You have deleted the message <a href=\"%(message_url)s\">%(message)s</a>."
msgstr "Du har slettet beskeden <a href=\"%(message_url)s\">%(message)s</a>."
#: templates/notification/messages_received/notice.html:2
#, python-format
msgid ""
"You have received the message <a href=\"%(message_url)s\">%(message)s</a> "
"from %(message_sender)s."
msgstr ""
"Du har modtaget beskeden <a href=\"%(message_url)s\">%(message)s</a> fra %"
"(message_sender)s."
#: templates/notification/messages_recovered/notice.html:1
#, python-format
msgid ""
"You have recovered the message <a href=\"%(message_url)s\">%(message)s</a>."
msgstr "Du har genskabt beskeden <a href=\"%(message_url)s\">%(message)s</a>."
#: templates/notification/messages_replied/notice.html:2
#, python-format
msgid ""
"You have replied to <a href=\"%(message_url)s\">%(message_parent_msg)s</a> "
"from %(message_recipient)s."
msgstr ""
"Du har besvaret <a href=\"%(message_url)s\">%(message_parent_msg)s</a> fra %"
"(message_recipient)s."
#: templates/notification/messages_reply_received/notice.html:2
#, python-format
msgid "%(message_sender)s has sent you a reply to %(message_parent_msg)s."
msgstr ""
"%(message_sender)s har sendt dig en besvarelse på %(message_parent_msg)s."
#: templates/notification/messages_sent/notice.html:2
#, python-format
msgid ""
"You have sent the message <a href=\"%(message_url)s\">%(message)s</a> to %"
"(message_recipient)s."
msgstr ""
"Du har sendt beskeden <a href=\"%(message_url)s\">%(message)s</a> til %"
"(message_recipient)s."
#, fuzzy
#~ msgid "You have deleted the message '%(message)s'."
#~ msgstr "Du har slettet beskeden '%(message)s'."
#, fuzzy
#~ msgid ""
#~ "%(message_sender)s has sent you a message:\n"
#~ "\n"
#~ "%(message)s\n"
#~ "\n"
#~ "%(message_body)s\n"
#~ "\n"
#~ "http://%(current_site)s%(message_url)s"
#~ msgstr ""
#~ "%(message_sender)s har sendt dig en besked:\n"
#~ "\n"
#~ "%(message)s\n"
#~ "\n"
#~ "%(message_body)s\n"
#~ "\n"
#~ "http://%(current_site)s%(message_url)s"
#~ msgid "%(notice)s by %(message_sender)s"
#~ msgstr "%(notice)s af %(message_sender)s"
#, fuzzy
#~ msgid "You have recovered the message '%(message)s'."
#~ msgstr "Du har genskabt beskeden '%(message)s'."
#, fuzzy
#~ msgid ""
#~ "You have replied to '%(message_parent_msg)s' from %(message_recipient)s."
#~ msgstr "Du har besvaret '%(message_parent_msg)s' fra %(message_recipient)s."
#~ msgid ""
#~ "%(message_sender)s replied to '%(message_parent_msg)s':\n"
#~ "\n"
#~ "%(message)s\n"
#~ "\n"
#~ "%(message_body)s\n"
#~ "\n"
#~ "http://%(current_site)s%(message_url)s"
#~ msgstr ""
#~ "%(message_sender)s besvarede '%(message_parent_msg)s':\n"
#~ "\n"
#~ "%(message)s\n"
#~ "\n"
#~ "%(message_body)s\n"
#~ "\n"
#~ "http://%(current_site)s%(message_url)s"
#, fuzzy
#~ msgid "You have sent the message '%(message)s' to %(message_recipient)s."
#~ msgstr "Du har sendt beskeden '%(message)s' til %(message_recipient)s."

321
django_messages/locale/de/LC_MESSAGES/django.po

@ -1,321 +0,0 @@
# 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"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-09-11 12:31-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: admin.py:13 forms.py:20 models.py:52 templates/messages/outbox.html:7
#: templates/messages/view.html:12
msgid "Recipient"
msgstr "Empfänger"
#: admin.py:15
msgid "group"
msgstr "Gruppe"
#: admin.py:16
msgid "Creates the message optionally for all users or a group of users."
msgstr ""
"Fügt die Nachricht wahlweise für jeden Benutzer der ausgewählten Gruppe "
"hinzu."
#: admin.py:23
msgid "All users"
msgstr "Alle Benutzer"
#: admin.py:38 models.py:88
msgid "Message"
msgstr "Nachricht"
#: admin.py:45
msgid "Date/time"
msgstr "Datum/Zeit"
#: fields.py:53
#, python-format
msgid "The following usernames are incorrect: %(users)s"
msgstr "Die folgenden Benutzernamen sind nicht korrekt: %(users)s"
#: forms.py:21 models.py:49 templates/messages/inbox.html:7
#: templates/messages/outbox.html:7 templates/messages/trash.html:7
#: templates/messages/view.html:6
msgid "Subject"
msgstr "Betreff"
#: forms.py:22 models.py:50
msgid "Body"
msgstr "Inhalt"
#: management.py:9
msgid "Message Received"
msgstr "Nachricht erhalten"
#: management.py:9
msgid "you have received a message"
msgstr "Du hast eine Nachricht erhalten"
#: management.py:10
msgid "Message Sent"
msgstr "Nachricht gesendet"
#: management.py:10
msgid "you have sent a message"
msgstr "Du hast eine Nachricht gesendet"
#: management.py:11
msgid "Message Replied"
msgstr "Nachricht beantwortet"
#: management.py:11
msgid "you have replied to a message"
msgstr "Du hast eine Nachricht beantwortet"
#: management.py:12
msgid "Reply Received"
msgstr "Antwort erhalten"
#: management.py:12
msgid "you have received a reply to a message"
msgstr "Du hast eine Antwort auf eine Nachricht erhalten"
#: management.py:13
msgid "Message Deleted"
msgstr "Nachricht gelöscht"
#: management.py:13
msgid "you have deleted a message"
msgstr "Du hast eine Nachricht gelöscht"
#: management.py:14
msgid "Message Recovered"
msgstr "Nachricht wiederhergestellt"
#: management.py:14
msgid "you have undeleted a message"
msgstr "Du hast eine Nachricht wiederhergestellt"
#: models.py:51 templates/messages/inbox.html:7
#: templates/messages/trash.html:7 templates/messages/view.html:8
msgid "Sender"
msgstr "Absender"
#: models.py:53
msgid "Parent message"
msgstr "Übergeordnete Nachricht"
#: models.py:54
msgid "sent at"
msgstr "gesendet am"
#: models.py:55
msgid "read at"
msgstr "gelesen am"
#: models.py:56
msgid "replied at"
msgstr "beantwortet am"
#: models.py:57
msgid "Sender deleted at"
msgstr "Vom Absender gelöscht"
#: models.py:58
msgid "Recipient deleted at"
msgstr "Vom Empfänger gelöscht"
#: models.py:89
msgid "Messages"
msgstr "Nachrichten"
#: utils.py:27
#, python-format
msgid "New Message: %(subject)s"
msgstr "Neue Nachricht: %(subject)s"
#: views.py:78 views.py:112
msgid "Message successfully sent."
msgstr "Nachricht erfolgreich gesendet."
#: views.py:118
#, python-format
msgid ""
"%(sender)s wrote:\n"
"%(body)s"
msgstr ""
"%(sender)s schrieb:\n"
"%(body)s"
#: views.py:122
#, python-format
msgid "Re: %(subject)s"
msgstr "Re: %(subject)s"
#: views.py:158
msgid "Message successfully deleted."
msgstr "Nachricht erfolgreich gelöscht."
#: views.py:185
msgid "Message successfully recovered."
msgstr "Nachricht erfolgreich wiederhergestellt."
#: templates/messages/base.html:8 templates/messages/inbox.html:4
#: templates/messages/new_message.html:10
msgid "Inbox"
msgstr "Posteingang"
#: templates/messages/base.html:9 templates/messages/outbox.html:4
msgid "Sent Messages"
msgstr "Gesendete Nachrichten"
#: templates/messages/base.html:10
msgid "New Message"
msgstr "Neue Nachricht"
#: templates/messages/base.html:11
msgid "Trash"
msgstr "Papierkorb"
#: templates/messages/compose.html:4
msgid "Compose Message"
msgstr "Nachricht verfassen"
#: templates/messages/compose.html:9
msgid "Send"
msgstr "Senden"
#: templates/messages/inbox.html:7
msgid "Received"
msgstr "Erhalten"
#: templates/messages/inbox.html:7 templates/messages/outbox.html:7
#: templates/messages/trash.html:7
msgid "Action"
msgstr "Aktion"
#: templates/messages/inbox.html:19 templates/messages/outbox.html:16
#: templates/messages/trash.html:16 templates/messages/view.html:11
msgid "DATETIME_FORMAT"
msgstr "j. N Y, H:i"
#: templates/messages/inbox.html:20 templates/messages/outbox.html:17
msgid "delete"
msgstr "löschen"
#: templates/messages/inbox.html:27 templates/messages/outbox.html:24
#: templates/messages/trash.html:24
msgid "No messages."
msgstr "Keine Nachrichten."
#: templates/messages/new_message.html:1
#, python-format
msgid ""
"Hello %(recipient)s,\n"
"\n"
"you received a private message from %(sender)s with\n"
"the following contents:"
msgstr ""
"Hallo %(recipient)s,\n"
"\n"
"du hast eine private Nachricht von %(sender)s mit\n"
"dem folgenden Inhalt erhalten:"
#: templates/messages/new_message.html:9
#, python-format
msgid "Sent from %(site_url)s"
msgstr "Gesendet von %(site_url)s"
#: templates/messages/new_message.html:11 templates/messages/view.html:18
msgid "Reply"
msgstr "Antworten"
#: templates/messages/outbox.html:7
msgid "Sent"
msgstr "Gesendet"
#: templates/messages/trash.html:4
msgid "Deleted Messages"
msgstr "Gelöschte Nachrichten"
#: templates/messages/trash.html:7 templates/messages/view.html:10
msgid "Date"
msgstr "Datum"
#: templates/messages/trash.html:17
msgid "undelete"
msgstr "wiederherstellen"
#: templates/messages/trash.html:23
msgid ""
"Deleted Messages are removed from the trash at unregular intervals, don't "
"rely on this feature for long-time storage."
msgstr ""
"Gelöschte Nachrichten werden in unregelmäßigen Intervallen entfernt, verlass "
"dich nicht drauf, dass diese Nachrichten hier lange gespeichert werden."
#: templates/messages/view.html:4
msgid "View Message"
msgstr "Nachrichtendetails"
#: templates/messages/view.html:20
msgid "Delete"
msgstr "Löschen"
#: templates/notification/messages_deleted/notice.html:1
#, python-format
msgid ""
"You have deleted the message <a href=\"%(message_url)s\">%(message)s</a>."
msgstr ""
"Du hast die Nachricht <a href=\"%(message_url)s\">%(message)s</a> gelöscht."
#: templates/notification/messages_received/notice.html:2
#, python-format
msgid ""
"You have received the message <a href=\"%(message_url)s\">%(message)s</a> "
"from %(message_sender)s."
msgstr ""
"Du hast die Nachricht <a href=\"%(message_url)s\">%(message)s</a> von %"
"(message_sender)s erhalten."
#: templates/notification/messages_recovered/notice.html:1
#, python-format
msgid ""
"You have recovered the message <a href=\"%(message_url)s\">%(message)s</a>."
msgstr ""
"Du hast die Nachricht <a href=\"%(message_url)s\">%(message)s</a> "
"wiederhergestellt."
#: templates/notification/messages_replied/notice.html:2
#, python-format
msgid ""
"You have replied to <a href=\"%(message_url)s\">%(message_parent_msg)s</a> "
"from %(message_recipient)s."
msgstr ""
"Du hast auf die Nachricht <a href=\"%(message_url)s\">%(message_parent_msg)"
"s</a> von %(message_recipient)s geantwortet."
#: templates/notification/messages_reply_received/notice.html:2
#, python-format
msgid "%(message_sender)s has sent you a reply to %(message_parent_msg)s."
msgstr ""
"%(message_sender)s hat dir eine Antwort auf %(message_parent_msg)s gesendet."
#: templates/notification/messages_sent/notice.html:2
#, python-format
msgid ""
"You have sent the message <a href=\"%(message_url)s\">%(message)s</a> to %"
"(message_recipient)s."
msgstr ""
"Du hast die Nachricht <a href=\"%(message_url)s\">%(message)s</a> an %"
"(message_recipient)s gesendet."

291
django_messages/locale/el/LC_MESSAGES/django.po

@ -1,291 +0,0 @@
# 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.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-09-11 12:31-0700\n"
"PO-Revision-Date: 2009-09-08 15:50+0200\n"
"Last-Translator: markos <mgogoulos@gmail.com>\n"
"Language-Team: Markos Gogoulos <mgogoulos@gmail.com>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: admin.py:13 forms.py:20 models.py:52 templates/messages/outbox.html:7
#: templates/messages/view.html:12
msgid "Recipient"
msgstr "Αποδέκτης"
#: admin.py:15
msgid "group"
msgstr "ομάδα"
#: admin.py:16
msgid "Creates the message optionally for all users or a group of users."
msgstr "Δημιουργεί το μήνυμα προαιρετικά για όλους τους χρήστες ή για ομάδα χρηστών."
#: admin.py:23
msgid "All users"
msgstr "Όλοι οι χρήστες"
#: admin.py:38 models.py:88
msgid "Message"
msgstr "Μήνυμα"
#: admin.py:45
msgid "Date/time"
msgstr "Ημερομηνία/Ώρα"
#: fields.py:53
#, python-format
msgid "The following usernames are incorrect: %(users)s"
msgstr "Τα παρακάτω usernames δεν είναι σωστά: %(users)s"
#: forms.py:21 models.py:49 templates/messages/inbox.html:7
#: templates/messages/outbox.html:7 templates/messages/trash.html:7
#: templates/messages/view.html:6
msgid "Subject"
msgstr "Θέμα"
#: forms.py:22 models.py:50
msgid "Body"
msgstr "Κυρίως μέρος"
#: management.py:9
msgid "Message Received"
msgstr "Το μήνυμα ελήφθη "
#: management.py:9
msgid "you have received a message"
msgstr "έχετε λάβει ένα μήνυμα"
#: management.py:10
msgid "Message Sent"
msgstr "Το μήνυμα εστάλει"
#: management.py:10
msgid "you have sent a message"
msgstr "έχετε στείλει ένα μήνυμα"
#: management.py:11
msgid "Message Replied"
msgstr "Το μήνυμα έχει απαντηθεί"
#: management.py:11
msgid "you have replied to a message"
msgstr "έχετε απαντήσει σε ένα μήνυμα"
#: management.py:12
msgid "Reply Received"
msgstr "Η απάντηση ελήφθη"
#: management.py:12
msgid "you have received a reply to a message"
msgstr "έχετε λάβει μια απάντηση σε ένα μήνυμα"
#: management.py:13
msgid "Message Deleted"
msgstr "Το μήνυμα έχει διαγραφεί"
#: management.py:13
msgid "you have deleted a message"
msgstr "διαγράψατε ένα μήνυμα"
#: management.py:14
msgid "Message Recovered"
msgstr "Το μήνυμα έχει ανακληθεί"
#: management.py:14
msgid "you have undeleted a message"
msgstr "έχετε ανακτήσει ένα μήνυμα"
#: models.py:51 templates/messages/inbox.html:7
#: templates/messages/trash.html:7 templates/messages/view.html:8
msgid "Sender"
msgstr "Αποστολέας"
#: models.py:53
msgid "Parent message"
msgstr "Μήνυμα Γονέας"
#: models.py:54
msgid "sent at"
msgstr "εστάλει στις"
#: models.py:55
msgid "read at"
msgstr "αναγνώστηκε στις"
#: models.py:56
msgid "replied at"
msgstr "απαντήθηκε στις"
#: models.py:57
msgid "Sender deleted at"
msgstr "Ο αποστολέας το διέγραψε στις"
#: models.py:58
msgid "Recipient deleted at"
msgstr "Ο αποδέκτης το διέγραψε στις"
#: models.py:89
msgid "Messages"
msgstr "Μηνύματα"
#: utils.py:27
#, python-format
msgid "New Message: %(subject)s"
msgstr "καινούργιο μήνυμα: %(subject)s"
#: views.py:78 views.py:112
msgid "Message successfully sent."
msgstr "Το μήνυμα έχει αποσταλεί με επιτυχία."
#: views.py:118
#, python-format
msgid ""
"%(sender)s wrote:\n"
"%(body)s"
msgstr ""
"%(sender)s έγραψε:\n"
"%(body)s"
#: views.py:122
#, python-format
msgid "Re: %(subject)s"
msgstr "Re: %(subject)s"
#: views.py:158
msgid "Message successfully deleted."
msgstr "Το μήνυμα διεγράφει."
#: views.py:185
msgid "Message successfully recovered."
msgstr "Το μήνυμα έχει ανακληθεί επιτυχημένα"
#: templates/messages/base.html:8 templates/messages/inbox.html:4
#: templates/messages/new_message.html:10
msgid "Inbox"
msgstr "Εισερχόμενα"
#: templates/messages/base.html:9 templates/messages/outbox.html:4
msgid "Sent Messages"
msgstr "Σταλμένα μηνύματα"
#: templates/messages/base.html:10
msgid "New Message"
msgstr "Νέο μήνυμα"
#: templates/messages/base.html:11
msgid "Trash"
msgstr "Άχρηστα"
#: templates/messages/compose.html:4
msgid "Compose Message"
msgstr "Συντάξτε μήνυμα"
#: templates/messages/compose.html:9
msgid "Send"
msgstr "Στείλτε"
#: templates/messages/inbox.html:7
msgid "Received"
msgstr "Ελήφθη"
#: templates/messages/inbox.html:7 templates/messages/outbox.html:7
#: templates/messages/trash.html:7
msgid "Action"
msgstr "Ενέργεια"
#: templates/messages/inbox.html:19 templates/messages/outbox.html:16
#: templates/messages/trash.html:16 templates/messages/view.html:11
msgid "DATETIME_FORMAT"
msgstr "DATETIME_FORMAT"
#: templates/messages/inbox.html:20 templates/messages/outbox.html:17
msgid "delete"
msgstr "διαγράφω"
#: templates/messages/new_message.html:1
#, python-format
msgid ""
"Hello %(recipient)s,\n"
"\n"
"you received a private message from %(sender)s with\n"
"the following contents:"
msgstr ""
"Γειά χαρά %(recipient)s,\n"
"\n"
"έχετε λάβει ένα προσωπικό μήνυμα από τον/την %(sender)s με\n"
"το ακόλουθο περιεχόμενο:"
#: templates/messages/new_message.html:9
#, python-format
msgid "Sent from %(site_url)s"
msgstr "Εστάλει απο %(site_url)s"
#: templates/messages/new_message.html:11 templates/messages/view.html:18
msgid "Reply"
msgstr "Απαντήστε"
#: templates/messages/outbox.html:7
msgid "Sent"
msgstr "Απεσταλμένα"
#: templates/messages/trash.html:4
msgid "Deleted Messages"
msgstr "Διαγραμμένα μηνύματα"
#: templates/messages/trash.html:7 templates/messages/view.html:10
msgid "Date"
msgstr "Ημερομηνία"
#: templates/messages/trash.html:17
msgid "undelete"
msgstr "ξεδιαγράψτε"
#: templates/messages/trash.html:23
msgid "Deleted Messages are removed from the trash at unregular intervals, don't rely on this feature for long-time storage."
msgstr "Τα διαγραμμένα μηνύματα απομακρύνονται απο τα Άχρηστα σε μη τακτά διαστήματα, μη βασίζεστε σε αυτά για μακροχρόνια αποθήκευση."
#: templates/messages/view.html:4
msgid "View Message"
msgstr "Προβολή Μηνύματος"
#: templates/messages/view.html:20
msgid "Delete"
msgstr "Διαγραφή"
#: templates/notification/messages_deleted/notice.html:1
#, python-format
msgid "You have deleted the message <a href=\"%(message_url)s\">%(message)s</a>."
msgstr "Έχετε διαγράψει το μήνυμα <a href=\"%(message_url)s\">%(message)s</a>."
#: templates/notification/messages_received/notice.html:2
#, python-format
msgid "You have received the message <a href=\"%(message_url)s\">%(message)s</a> from %(message_sender)s."
msgstr "Έχετε λάβει το μήνυμα <a href=\"%(message_url)s\">%(message)s</a> από τον/την %(message_sender)s."
#: templates/notification/messages_recovered/notice.html:1
#, python-format
msgid "You have recovered the message <a href=\"%(message_url)s\">%(message)s</a>."
msgstr "Έχετε ανακτήσει το μήνυμα <a href=\"%(message_url)s\">%(message)s</a>."
#: templates/notification/messages_replied/notice.html:2
#, python-format
msgid "You have replied to <a href=\"%(message_url)s\">%(message_parent_msg)s</a> from %(message_recipient)s."
msgstr "Έχετε απαντήσει στο <a href=\"%(message_url)s\">%(message_parent_msg)s</a>από τον/την %(message_recipient)s."
#: templates/notification/messages_reply_received/notice.html:2
#, python-format
msgid "%(message_sender)s has sent you a reply to %(message_parent_msg)s."
msgstr "Ο/η %(message_sender)s σας έστειλε μια απάντηση στο %(message_parent_msg)s."
#: templates/notification/messages_sent/notice.html:2
#, python-format
msgid "You have sent the message <a href=\"%(message_url)s\">%(message)s</a> to %(message_recipient)s."
msgstr "Έχετε στείλει το μήνυμα <a href=\"%(message_url)s\">%(message)s</a> στον/στην %(message_recipient)s."

314
django_messages/locale/es/LC_MESSAGES/django.po

@ -1,314 +0,0 @@
# django-messages in Spanish.
# django-messages en Español.
# Copyright (C) 2008
# This file is distributed under the same license as the django-messages package.
# Maria Guadalupe Paz Urrea <paz.lupita@gmail.com>, 2008.
# Alfonso Bernardo Harita Rascón <alharita@gmail.com>, 2008.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-09-11 12:31-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: admin.py:13 forms.py:20 models.py:52 templates/messages/outbox.html:7
#: templates/messages/view.html:12
msgid "Recipient"
msgstr "Destinatario"
#: admin.py:15
msgid "group"
msgstr ""
#: admin.py:16
msgid "Creates the message optionally for all users or a group of users."
msgstr ""
#: admin.py:23
msgid "All users"
msgstr ""
#: admin.py:38 models.py:88
msgid "Message"
msgstr "Mensaje"
#: admin.py:45
#, fuzzy
msgid "Date/time"
msgstr "Fecha"
#: fields.py:53
#, python-format
msgid "The following usernames are incorrect: %(users)s"
msgstr "Los siguientes usuarios son incorrectos: %(users)s"
#: forms.py:21 models.py:49 templates/messages/inbox.html:7
#: templates/messages/outbox.html:7 templates/messages/trash.html:7
#: templates/messages/view.html:6
msgid "Subject"
msgstr "Asunto"
#: forms.py:22 models.py:50
msgid "Body"
msgstr "Cuerpo"
#: management.py:9
msgid "Message Received"
msgstr "Mensaje Recibido"
#: management.py:9
msgid "you have received a message"
msgstr "ha recibido un mensaje"
#: management.py:10
msgid "Message Sent"
msgstr "Mensaje Enviado"
#: management.py:10
msgid "you have sent a message"
msgstr "ha enviado un mensaje"
#: management.py:11
msgid "Message Replied"
msgstr "Mensaje Respondido"
#: management.py:11
msgid "you have replied to a message"
msgstr "ha respondido un mensaje"
#: management.py:12
msgid "Reply Received"
msgstr "Respuesta Recibida"
#: management.py:12
msgid "you have received a reply to a message"
msgstr "ha recibido una respuesta a un mensaje"
#: management.py:13
msgid "Message Deleted"
msgstr "Mensaje Eliminado"
#: management.py:13
msgid "you have deleted a message"
msgstr "ha eliminado un mensaje"
#: management.py:14
msgid "Message Recovered"
msgstr "Mensaje Recuperado"
#: management.py:14
msgid "you have undeleted a message"
msgstr "ha recuperado un mensaje"
#: models.py:51 templates/messages/inbox.html:7
#: templates/messages/trash.html:7 templates/messages/view.html:8
msgid "Sender"
msgstr "Emisor"
#: models.py:53
msgid "Parent message"
msgstr "Mensaje padre"
#: models.py:54
msgid "sent at"
msgstr "enviado"
#: models.py:55
msgid "read at"
msgstr "leído"
#: models.py:56
msgid "replied at"
msgstr "respondido"
#: models.py:57
msgid "Sender deleted at"
msgstr "Emisor borrado"
#: models.py:58
msgid "Recipient deleted at"
msgstr "Destinatario borrado"
#: models.py:89
msgid "Messages"
msgstr "Mensajes"
#: utils.py:27
#, python-format
msgid "New Message: %(subject)s"
msgstr "Nuevo Mensaje: %(subject)s"
#: views.py:78 views.py:112
msgid "Message successfully sent."
msgstr "Se envió con éxito el mensaje."
#: views.py:118
#, python-format
msgid ""
"%(sender)s wrote:\n"
"%(body)s"
msgstr ""
"%(sender)s escribió:\n"
"%(body)s"
#: views.py:122
#, python-format
msgid "Re: %(subject)s"
msgstr "Re: %(subject)s"
#: views.py:158
msgid "Message successfully deleted."
msgstr "Se eliminó con éxito el mensaje."
#: views.py:185
msgid "Message successfully recovered."
msgstr "Se recuperó con éxito el mensaje."
#: templates/messages/base.html:8 templates/messages/inbox.html:4
#: templates/messages/new_message.html:10
msgid "Inbox"
msgstr "Bandeja de entrada"
#: templates/messages/base.html:9 templates/messages/outbox.html:4
msgid "Sent Messages"
msgstr "Mensajes Enviados"
#: templates/messages/base.html:10
msgid "New Message"
msgstr "Nuevo Mensaje"
#: templates/messages/base.html:11
msgid "Trash"
msgstr "Papelera"
#: templates/messages/compose.html:4
msgid "Compose Message"
msgstr "Redactar Mensaje"
#: templates/messages/compose.html:9
msgid "Send"
msgstr "Enviar"
#: templates/messages/inbox.html:7
msgid "Received"
msgstr "Recibido"
#: templates/messages/inbox.html:7 templates/messages/outbox.html:7
#: templates/messages/trash.html:7
msgid "Action"
msgstr "Acción"
#: templates/messages/inbox.html:19 templates/messages/outbox.html:16
#: templates/messages/trash.html:16 templates/messages/view.html:11
msgid "DATETIME_FORMAT"
msgstr ""
#: templates/messages/inbox.html:20 templates/messages/outbox.html:17
msgid "delete"
msgstr "eliminar"
#: templates/messages/new_message.html:1
#, python-format
msgid ""
"Hello %(recipient)s,\n"
"\n"
"you received a private message from %(sender)s with\n"
"the following contents:"
msgstr ""
"Hola %(recipient)s,\n"
"\n"
"ha recibido un mensaje de %(sender)s con\n"
"el siguiente contenido:"
#: templates/messages/new_message.html:9
#, python-format
msgid "Sent from %(site_url)s"
msgstr "Enviado desde %(site_url)s"
#: templates/messages/new_message.html:11 templates/messages/view.html:18
msgid "Reply"
msgstr "Responder"
#: templates/messages/outbox.html:7
msgid "Sent"
msgstr "Enviado"
#: templates/messages/trash.html:4
msgid "Deleted Messages"
msgstr "Mensajes Eliminados"
#: templates/messages/trash.html:7 templates/messages/view.html:10
msgid "Date"
msgstr "Fecha"
#: templates/messages/trash.html:17
msgid "undelete"
msgstr "recuperar"
#: templates/messages/trash.html:23
msgid ""
"Deleted Messages are removed from the trash at unregular intervals, don't "
"rely on this feature for long-time storage."
msgstr ""
"Los Mensajes Eliminados son borrados de la Papelera a intérvalos irregulares,"
"no se confíe en esta característica para almacenamiento a largo plazo."
#: templates/messages/view.html:4
msgid "View Message"
msgstr "Ver Mensaje"
#: templates/messages/view.html:20
msgid "Delete"
msgstr "Eliminar"
#: templates/notification/messages_deleted/notice.html:1
#, python-format
msgid ""
"You have deleted the message <a href=\"%(message_url)s\">%(message)s</a>."
msgstr "ha borrado el mensaje <a href=\"%(message_url)s\">%(message)s</a>."
#: templates/notification/messages_received/notice.html:2
#, python-format
msgid ""
"You have received the message <a href=\"%(message_url)s\">%(message)s</a> "
"from %(message_sender)s."
msgstr ""
"ha recibido el mensaje <a href=\"%(message_url)s\">%(message)s</a> de %"
"(message_sender)s."
#: templates/notification/messages_recovered/notice.html:1
#, python-format
msgid ""
"You have recovered the message <a href=\"%(message_url)s\">%(message)s</a>."
msgstr "ha recuperado el mensaje <a href=\"%(message_url)s\">%(message)s</a>."
#: templates/notification/messages_replied/notice.html:2
#, python-format
msgid ""
"You have replied to <a href=\"%(message_url)s\">%(message_parent_msg)s</a> "
"from %(message_recipient)s."
msgstr ""
"ha respondido a <a href=\"%(message_url)s\">%(message_parent_msg)s</a> de %"
"(message_recipient)s."
#: templates/notification/messages_reply_received/notice.html:2
#, python-format
msgid "%(message_sender)s has sent you a reply to %(message_parent_msg)s."
msgstr ""
"%(message_sender)s le ha enviado una respuesta a %(message_parent_msg)s."
#: templates/notification/messages_sent/notice.html:2
#, python-format
msgid ""
"You have sent the message <a href=\"%(message_url)s\">%(message)s</a> to %"
"(message_recipient)s."
msgstr ""
"ha enviado el mensaje <a href=\"%(message_url)s\">%(message)s</a> a %"
"(message_recipient)s."

312
django_messages/locale/es_AR/LC_MESSAGES/django.po

@ -1,312 +0,0 @@
# django-messages in Spanish Argentina.
# django-messages en Español Argentina.
# Copyright (C) 2008
# This file is distributed under the same license as the django-messages package.
# Cecilia Lorena Puccinelli <ceciliapuccinelli@gmail.com>, 2008.
# Juan José Conti <jjconti@gnu.org>, 2008.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-09-11 12:31-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: admin.py:13 forms.py:20 models.py:52 templates/messages/outbox.html:7
#: templates/messages/view.html:12
msgid "Recipient"
msgstr "Destinatario"
#: admin.py:15
msgid "group"
msgstr ""
#: admin.py:16
msgid "Creates the message optionally for all users or a group of users."
msgstr ""
#: admin.py:23
msgid "All users"
msgstr ""
#: admin.py:38 models.py:88
msgid "Message"
msgstr "Mensaje"
#: admin.py:45
#, fuzzy
msgid "Date/time"
msgstr "Fecha"
#: fields.py:53
#, python-format
msgid "The following usernames are incorrect: %(users)s"
msgstr ""
#: forms.py:21 models.py:49 templates/messages/inbox.html:7
#: templates/messages/outbox.html:7 templates/messages/trash.html:7
#: templates/messages/view.html:6
msgid "Subject"
msgstr "Asunto"
#: forms.py:22 models.py:50
msgid "Body"
msgstr "Cuerpo"
#: management.py:9
msgid "Message Received"
msgstr "Mensaje Recibido"
#: management.py:9
msgid "you have received a message"
msgstr "ha recibido un mensaje"
#: management.py:10
msgid "Message Sent"
msgstr "Mensaje Enviado"
#: management.py:10
msgid "you have sent a message"
msgstr "ha enviado un mensaje"
#: management.py:11
msgid "Message Replied"
msgstr "Mensaje Respondido"
#: management.py:11
msgid "you have replied to a message"
msgstr "ha respondido un mensaje"
#: management.py:12
msgid "Reply Received"
msgstr "Respuesta Recibida"
#: management.py:12
msgid "you have received a reply to a message"
msgstr "ha recibido una respuesta a un mensaje"
#: management.py:13
msgid "Message Deleted"
msgstr "Mensaje Eliminado"
#: management.py:13
msgid "you have deleted a message"
msgstr "ha eliminado un mensaje"
#: management.py:14
msgid "Message Recovered"
msgstr "Mensaje Recuperado"
#: management.py:14
msgid "you have undeleted a message"
msgstr "ha recuperado un mensaje"
#: models.py:51 templates/messages/inbox.html:7
#: templates/messages/trash.html:7 templates/messages/view.html:8
msgid "Sender"
msgstr "Emisor"
#: models.py:53
msgid "Parent message"
msgstr "Mensaje padre"
#: models.py:54
msgid "sent at"
msgstr "enviado"
#: models.py:55
msgid "read at"
msgstr "leído"
#: models.py:56
msgid "replied at"
msgstr "respondido"
#: models.py:57
msgid "Sender deleted at"
msgstr "Emisor borrado"
#: models.py:58
msgid "Recipient deleted at"
msgstr "Destinatario borrado"
#: models.py:89
msgid "Messages"
msgstr "Mensajes"
#: utils.py:27
#, fuzzy, python-format
msgid "New Message: %(subject)s"
msgstr "Re: %(subject)s"
#: views.py:78 views.py:112
msgid "Message successfully sent."
msgstr "Se envió con éxito el mensaje."
#: views.py:118
#, python-format
msgid ""
"%(sender)s wrote:\n"
"%(body)s"
msgstr ""
"%(sender)s escribió:\n"
"%(body)s"
#: views.py:122
#, python-format
msgid "Re: %(subject)s"
msgstr "Re: %(subject)s"
#: views.py:158
msgid "Message successfully deleted."
msgstr "Se eliminó con éxito el mensaje."
#: views.py:185
msgid "Message successfully recovered."
msgstr "Se recuperó con éxito el mensaje."
#: templates/messages/base.html:8 templates/messages/inbox.html:4
#: templates/messages/new_message.html:10
msgid "Inbox"
msgstr "Bandeja de entrada"
#: templates/messages/base.html:9 templates/messages/outbox.html:4
msgid "Sent Messages"
msgstr "Mensajes Enviados"
#: templates/messages/base.html:10
msgid "New Message"
msgstr "Nuevo Mensaje"
#: templates/messages/base.html:11
msgid "Trash"
msgstr "Papelera"
#: templates/messages/compose.html:4
msgid "Compose Message"
msgstr "Redactar Mensaje"
#: templates/messages/compose.html:9
msgid "Send"
msgstr "Enviar"
#: templates/messages/inbox.html:7
msgid "Received"
msgstr "Recibido"
#: templates/messages/inbox.html:7 templates/messages/outbox.html:7
#: templates/messages/trash.html:7
msgid "Action"
msgstr "Acción"
#: templates/messages/inbox.html:19 templates/messages/outbox.html:16
#: templates/messages/trash.html:16 templates/messages/view.html:11
msgid "DATETIME_FORMAT"
msgstr ""
#: templates/messages/inbox.html:20 templates/messages/outbox.html:17
msgid "delete"
msgstr "eliminar"
#: templates/messages/new_message.html:1
#, python-format
msgid ""
"Hello %(recipient)s,\n"
"\n"
"you received a private message from %(sender)s with\n"
"the following contents:"
msgstr ""
#: templates/messages/new_message.html:9
#, python-format
msgid "Sent from %(site_url)s"
msgstr "Enviado desde %(site_url)s"
#: templates/messages/new_message.html:11 templates/messages/view.html:18
msgid "Reply"
msgstr "Responder"
#: templates/messages/outbox.html:7
msgid "Sent"
msgstr "Enviado"
#: templates/messages/trash.html:4
msgid "Deleted Messages"
msgstr "Mensajes Eliminados"
#: templates/messages/trash.html:7 templates/messages/view.html:10
msgid "Date"
msgstr "Fecha"
#: templates/messages/trash.html:17
msgid "undelete"
msgstr "recuperar"
#: templates/messages/trash.html:23
msgid ""
"Deleted Messages are removed from the trash at unregular intervals, don't "
"rely on this feature for long-time storage."
msgstr ""
"Los Mensajes Eliminados son borrados de la Papelera a intérvalos irregulares,"
"no se confíe en esta característica para almacenamiento a largo plazo."
#: templates/messages/view.html:4
msgid "View Message"
msgstr "Ver Mensaje"
#: templates/messages/view.html:20
msgid "Delete"
msgstr "Eliminar"
#: templates/notification/messages_deleted/notice.html:1
#, fuzzy, python-format
msgid ""
"You have deleted the message <a href=\"%(message_url)s\">%(message)s</a>."
msgstr "ha eliminado el mensaje %(message)s."
#: templates/notification/messages_received/notice.html:2
#, fuzzy, python-format
msgid ""
"You have received the message <a href=\"%(message_url)s\">%(message)s</a> "
"from %(message_sender)s."
msgstr "ha recibido un mensaje de %(sender)s."
#: templates/notification/messages_recovered/notice.html:1
#, fuzzy, python-format
msgid ""
"You have recovered the message <a href=\"%(message_url)s\">%(message)s</a>."
msgstr "ha recuperado el mensaje %(message)s."
#: templates/notification/messages_replied/notice.html:2
#, fuzzy, python-format
msgid ""
"You have replied to <a href=\"%(message_url)s\">%(message_parent_msg)s</a> "
"from %(message_recipient)s."
msgstr "ha respondido a %(message)s de %(recipient)s."
#: templates/notification/messages_reply_received/notice.html:2
#, fuzzy, python-format
msgid "%(message_sender)s has sent you a reply to %(message_parent_msg)s."
msgstr "%(sender)s le ha enviado una respuesta a %(message)s."
#: templates/notification/messages_sent/notice.html:2
#, python-format
msgid ""
"You have sent the message <a href=\"%(message_url)s\">%(message)s</a> to %"
"(message_recipient)s."
msgstr ""
#~ msgid "There is no user with this username."
#~ msgstr "No hay ningún usuario con ese nombre."
#~ msgid "you have sent a message to %(recipient)s."
#~ msgstr "ha enviado un mensaje a %(recipient)s."
#~ msgid "New Message:"
#~ msgstr "Mensaje Nuevo"

357
django_messages/locale/fa/LC_MESSAGES/django.po

@ -1,357 +0,0 @@
# django-messages fari translations
# Copyright (C) 2012 Hassan Zamani
# This file is distributed under the same license as the djagno-messages package.
# Hassan Zamani <hsn.zamani@gmail.com>, 2012.
#
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-27 12:44+0430\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"First-Translator: Mohammad Hamidi Esfahani"
"Last-Translator: Hassan Zamani <hsn.zamani@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: fa\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0\n"
#: admin.py:19 forms.py:20 models.py:52
#: templates/django_messages/outbox.html:8
#: templates/django_messages/view.html:12
msgid "Recipient"
msgstr "گیرنده"
#: admin.py:21
msgid "group"
msgstr "گروه"
#: admin.py:22
msgid "Creates the message optionally for all users or a group of users."
msgstr "ارسال پیام به همه کاربران یا گروهی از آن‌ها."
#: admin.py:29
msgid "All users"
msgstr "تمامی کاربران"
#: admin.py:44 models.py:88
msgid "Message"
msgstr "پیام"
#: admin.py:51
msgid "Date/time"
msgstr "تاریخ/ساعت"
#: fields.py:53
#, python-format
msgid "The following usernames are incorrect: %(users)s"
msgstr "این کاربرها صحیح نمی‌باشند: %(users)s"
#: forms.py:21 models.py:49 templates/django_messages/inbox.html:8
#: templates/django_messages/outbox.html:8
#: templates/django_messages/trash.html:8
#: templates/django_messages/view.html:6
msgid "Subject"
msgstr "موضوع"
#: forms.py:22 models.py:50
msgid "Body"
msgstr "متن"
#: management.py:9
msgid "Message Received"
msgstr "پیام دریافت‌شد"
#: management.py:9
msgid "you have received a message"
msgstr "شما یک پیام دریافت کرده‌اید"
#: management.py:10
msgid "Message Sent"
msgstr "پیام ارسال‌شد"
#: management.py:10
msgid "you have sent a message"
msgstr "شما یک پیام ارسال کرده‌اید"
#: management.py:11
msgid "Message Replied"
msgstr "پیام پاسخ داده‌شد"
#: management.py:11
msgid "you have replied to a message"
msgstr "شما به یک پیام پاسخ دادید"
#: management.py:12
msgid "Reply Received"
msgstr "پاسخ دریافت‌شد"
#: management.py:12
msgid "you have received a reply to a message"
msgstr "شما پاسخی به یک پیام دریافت کرده‌اید"
#: management.py:13
msgid "Message Deleted"
msgstr "پیام حذف گردید"
#: management.py:13
msgid "you have deleted a message"
msgstr "شما یک پیام حذف کردید"
#: management.py:14
msgid "Message Recovered"
msgstr "پیام بازیابی‌شد"
#: management.py:14
msgid "you have undeleted a message"
msgstr "شما یک پیام را بازیابی کردید"
#: models.py:51 templates/django_messages/inbox.html:8
#: templates/django_messages/trash.html:8
#: templates/django_messages/view.html:8
msgid "Sender"
msgstr "فرستنده"
#: models.py:53
msgid "Parent message"
msgstr "پیام مرجع"
#: models.py:54
msgid "sent at"
msgstr "ارسال شده در"
#: models.py:55
msgid "read at"
msgstr "خوانده شده در"
#: models.py:56
msgid "replied at"
msgstr "پاسخ داده شده در"
#: models.py:57
msgid "Sender deleted at"
msgstr "فرستنده حذف‌شده در"
#: models.py:58
msgid "Recipient deleted at"
msgstr "گیرنده خذف‌شده در"
#: models.py:89
msgid "Messages"
msgstr "پیام ها"
#: utils.py:26
#, python-format
msgid ""
"%(sender)s wrote:\n"
"%(body)s"
msgstr ""
"%(sender)s گفت:\n"
"%(body)s"
#: utils.py:54
#, python-format
msgid "Re%(prefix)s: %(subject)s"
msgstr "پاسخ%(prefix)s: %(subject)s"
#: utils.py:60
#, python-format
msgid "New Message: %(subject)s"
msgstr "پیام جدید: %(subject)s"
#: views.py:78 views.py:114
msgid "Message successfully sent."
msgstr "پیام با موفقیت ارسال‌شد."
#: views.py:121
#, python-format
msgid "Re: %(subject)s"
msgstr "پاسخ: %(subject)s"
#: views.py:157
msgid "Message successfully deleted."
msgstr "پیام با موفقیت حذف‌شد."
#: views.py:184
msgid "Message successfully recovered."
msgstr "پیام با موفقیت بازیابی‌شد."
#: templates/django_messages/base.html:8
#: templates/django_messages/inbox.html:4
#: templates/django_messages/new_message.html:10
msgid "Inbox"
msgstr "صندوق دریافتی"
#: templates/django_messages/base.html:9
#: templates/django_messages/outbox.html:4
msgid "Sent Messages"
msgstr "پیام‌های ارسال‌شده"
#: templates/django_messages/base.html:10
msgid "New Message"
msgstr "پیام جدید"
#: templates/django_messages/base.html:11
msgid "Trash"
msgstr "پیام‌های حذف‌شده"
#: templates/django_messages/compose.html:4
msgid "Compose Message"
msgstr "ایجاد پیام جدید"
#: templates/django_messages/compose.html:10
msgid "Send"
msgstr "بفرست"
#: templates/django_messages/inbox.html:8
msgid "Received"
msgstr "دریافت‌شد"
#: templates/django_messages/inbox.html:8
#: templates/django_messages/outbox.html:8
#: templates/django_messages/trash.html:8
msgid "Action"
msgstr "عمل"
#: templates/django_messages/inbox.html:20
#: templates/django_messages/outbox.html:17
#: templates/django_messages/trash.html:17
#: templates/django_messages/view.html:11
msgid "DATETIME_FORMAT"
msgstr ""
#: templates/django_messages/inbox.html:21
#: templates/django_messages/outbox.html:18
msgid "delete"
msgstr "حذف"
#: templates/django_messages/inbox.html:27
#: templates/django_messages/outbox.html:24
#: templates/django_messages/trash.html:24
msgid "No messages."
msgstr "پیامی وجود ندارد."
#: templates/django_messages/new_message.html:1
#, python-format
msgid ""
"Hello %(recipient)s,\n"
"\n"
"you received a private message from %(sender)s with\n"
"the following contents:"
msgstr "سلام %(recipient)s,\n"
"\n"
"شما یک پیام خصوصی از %(sender)s دریافت کرده‌اید:"
#: templates/django_messages/new_message.html:9
#, python-format
msgid "Sent from %(site_url)s"
msgstr "ارسال شده از %(site_url)s"
#: templates/django_messages/new_message.html:11
#: templates/django_messages/view.html:18
msgid "Reply"
msgstr "پاسخ"
#: templates/django_messages/outbox.html:8
msgid "Sent"
msgstr "ارسال‌شد"
#: templates/django_messages/trash.html:4
msgid "Deleted Messages"
msgstr "پیام های حذف‌شده"
#: templates/django_messages/trash.html:8
#: templates/django_messages/view.html:10
msgid "Date"
msgstr "تاریخ"
#: templates/django_messages/trash.html:18
msgid "undelete"
msgstr "بازیابی"
#: templates/django_messages/trash.html:27
msgid ""
"Deleted Messages are removed from the trash at unregular intervals, don't "
"rely on this feature for long-time storage."
msgstr ""
"پیام‌های حذف‌شده در بازه‌های زمانی مشخصی از اینجا حذف می‌شوند، بنابراین برای نگهداری طولانی مدت از این‌جا استفاده نکنید."
#: templates/django_messages/view.html:4
msgid "View Message"
msgstr "نمایش پیام"
#: templates/django_messages/view.html:20
msgid "Delete"
msgstr "حذف"
#: templates/notification/messages_deleted/notice.html:1
#, python-format
msgid ""
"You have deleted the message <a href=\"%(message_url)s\">%(message)s</a>."
msgstr "شما پیام <a href=\"%(message_url)s\">%(message)s</a> را حذف کردید."
#: templates/notification/messages_received/notice.html:2
#, python-format
msgid ""
"You have received the message <a href=\"%(message_url)s\">%(message)s</a> "
"from %(message_sender)s."
msgstr "شما پیام جدید <a href=\"%(message_url)s\">%(message)s</a> را از %(message_sender)s دریافت کردید."
#: templates/notification/messages_recovered/notice.html:1
#, python-format
msgid ""
"You have recovered the message <a href=\"%(message_url)s\">%(message)s</a>."
msgstr "شما پیام <a href=\"%(message_url)s\">%(message)s</a> را بازیابی کردید."
#: templates/notification/messages_replied/notice.html:2
#, python-format
msgid ""
"You have replied to <a href=\"%(message_url)s\">%(message_parent_msg)s</a> "
"from %(message_recipient)s."
msgstr "شما به پیام <a href=\"%(message_url)s\">%(message_parent_msg)s</a> از %(message_recipient)s پاسخ‌دادید."
#: templates/notification/messages_reply_received/notice.html:2
#, python-format
msgid "%(message_sender)s has sent you a reply to %(message_parent_msg)s."
msgstr "%(message_sender)s پاسخی به %(message_parent_msg)s برای شما ارسال کرده."
#: templates/notification/messages_sent/notice.html:2
#, python-format
msgid ""
"You have sent the message <a href=\"%(message_url)s\">%(message)s</a> to "
"%(message_recipient)s."
msgstr "شما پیام <a href=\"%(message_url)s\">%(message)s</a> را به %(message_recipient)s ارسال‌کردید."
#~ msgid "context"
#~ msgstr "متن پیام"
#~ msgid "received at"
#~ msgstr "دریافت شده در"
#~ msgid "deleted by sender at"
#~ msgstr "حذف شده توسط فرستنده در"
#~ msgid "deleted by receiver at"
#~ msgstr "حذف شده توسط گیرنده در"
#~ msgid "Message revert successfully"
#~ msgstr "پیام با موفقیت بازگردانی شد"
#~ msgid "send message"
#~ msgstr "ارسال پیام"
#~ msgid "date"
#~ msgstr "تاریخ"
#~ msgid "revert"
#~ msgstr "بازگردانی"
#~ msgid "deleted Messages will remove from trash step by step"
#~ msgstr "پیام های حذف شده در فواصل نامنظم از سطل زباله حذف می گردند"
#~ msgid "not replied yet"
#~ msgstr "هنوز پاسخ داده نشده است"

408
django_messages/locale/fr/LC_MESSAGES/django.po

@ -1,408 +0,0 @@
# 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.
#
msgid ""
msgstr ""
"Project-Id-Version: messages\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-03-18 17:46+0100\n"
"PO-Revision-Date: 2008-08-09 21:58+0100\n"
"Last-Translator: Roland Frédéric <frederic.roland@creativeconvergence.be>\n"
"Language-Team: Frédéric Roland <frederic.roland@creativeconvergence.be>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-Language: French\n"
#: admin.py:21
msgid "group"
msgstr "groupe"
#: admin.py:22
msgid "Creates the message optionally for all users or a group of users."
msgstr ""
"Créé le message en option pour tous les utilisateurs ou un groupe "
"d'utilisateurs."
#: admin.py:30
msgid "All users"
msgstr "Tous les utilisateurs"
#: admin.py:48 models.py:91
msgid "Message"
msgstr "Message"
#: admin.py:55
msgid "Date/time"
msgstr "Date/heure"
#: apps.py:6 models.py:92
msgid "Messages"
msgstr "Messages"
#: fields.py:56
#, python-format
msgid "The following usernames are incorrect: %(users)s"
msgstr "Les noms d'utilisateurs suivants sont incorrects : %(users)s"
#: forms.py:18 models.py:55 templates/django_messages/outbox.html:10
#: templates/django_messages/view.html:14
msgid "Recipient"
msgstr "Destinataire"
#: forms.py:19 models.py:52 templates/django_messages/inbox.html:10
#: templates/django_messages/outbox.html:10
#: templates/django_messages/trash.html:10
#: templates/django_messages/view.html:8
msgid "Subject"
msgstr "Sujet"
#: forms.py:20 models.py:53
msgid "Body"
msgstr "Message"
#: management.py:9
msgid "Message Received"
msgstr "Message Reçu"
#: management.py:9
msgid "you have received a message"
msgstr "vous avez reçu un message"
#: management.py:10
msgid "Message Sent"
msgstr "Message Envoyé"
#: management.py:10
msgid "you have sent a message"
msgstr "vous avez envoyé un message"
#: management.py:11
msgid "Message Replied"
msgstr "Message Répondu"
#: management.py:11
msgid "you have replied to a message"
msgstr "vous avez répondu à un message"
#: management.py:12
msgid "Reply Received"
msgstr "Réponse Reçue"
#: management.py:12
msgid "you have received a reply to a message"
msgstr "vous avez reçu une réponse à un message"
#: management.py:13
msgid "Message Deleted"
msgstr "Message Effacé"
#: management.py:13
msgid "you have deleted a message"
msgstr "vous avez effacé un message"
#: management.py:14
msgid "Message Recovered"
msgstr "Message Récupéré"
#: management.py:14
msgid "you have undeleted a message"
msgstr "vous avez récupéré un message"
#: models.py:54 templates/django_messages/inbox.html:10
#: templates/django_messages/trash.html:10
#: templates/django_messages/view.html:10
msgid "Sender"
msgstr "Expéditeur"
#: models.py:56
msgid "Parent message"
msgstr "Message parent"
#: models.py:57
msgid "sent at"
msgstr "envoyé à"
#: models.py:58
msgid "read at"
msgstr "lu à"
#: models.py:59
msgid "replied at"
msgstr "répondu à"
#: models.py:60
msgid "Sender deleted at"
msgstr "Expéditeur effacé à"
#: models.py:61
msgid "Recipient deleted at"
msgstr "Destinataire effacé à"
#: templates/django_messages/base.html:8
#: templates/django_messages/inbox.html:6
#: templates/django_messages/new_message.html:13
msgid "Inbox"
msgstr "Boîte de réception"
#: templates/django_messages/base.html:9
#: templates/django_messages/outbox.html:6
msgid "Sent Messages"
msgstr "Messages envoyés"
#: templates/django_messages/base.html:10
msgid "New Message"
msgstr "Nouveau Message"
#: templates/django_messages/base.html:11
msgid "Trash"
msgstr "Poubelle"
#: templates/django_messages/compose.html:4
msgid "Compose Message"
msgstr "Composer Message"
#: templates/django_messages/compose.html:10
msgid "Send"
msgstr "Envoyer"
#: templates/django_messages/inbox.html:10
msgid "Received"
msgstr "Reçu"
#: templates/django_messages/inbox.html:10
#: templates/django_messages/outbox.html:10
#: templates/django_messages/trash.html:10
msgid "Action"
msgstr "Action"
#: templates/django_messages/inbox.html:22
#: templates/django_messages/outbox.html:19
#: templates/django_messages/trash.html:19
#: templates/django_messages/view.html:13
msgid "DATETIME_FORMAT"
msgstr "j F Y, G:i"
#: templates/django_messages/inbox.html:23
#: templates/django_messages/outbox.html:20
msgid "delete"
msgstr "effacer"
#: templates/django_messages/inbox.html:29
#: templates/django_messages/outbox.html:26
#: templates/django_messages/trash.html:26
msgid "No messages."
msgstr "Aucun message."
#: templates/django_messages/new_message.html:4
#, python-format
msgid ""
"Hello %(recipient)s,\n"
"\n"
"you received a private message from %(sender)s with\n"
"the following contents:"
msgstr ""
"Bonjour %(recipient)s,\n"
"\n"
"vous avez reçu un message privé de %(sender)s avec\n"
"le contenu suivant :"
#: templates/django_messages/new_message.html:12
#, python-format
msgid "Sent from %(site_url)s"
msgstr "Envoyé depuis %(site_url)s"
#: templates/django_messages/new_message.html:14
#: templates/django_messages/view.html:20
msgid "Reply"
msgstr "Répondre"
#: templates/django_messages/outbox.html:10
msgid "Sent"
msgstr "Envoyé"
#: templates/django_messages/trash.html:6
msgid "Deleted Messages"
msgstr "Messages Effacés"
#: templates/django_messages/trash.html:10
#: templates/django_messages/view.html:12
msgid "Date"
msgstr "Date"
#: templates/django_messages/trash.html:20
msgid "undelete"
msgstr "restaurer"
#: templates/django_messages/trash.html:29
msgid ""
"Deleted Messages are removed from the trash at unregular intervals, don't "
"rely on this feature for long-time storage."
msgstr ""
"Les Messages Effacés sont enlevé de la poubelle a intervalles irréguliers, "
"ne comptez pas sur cette fonctionnalité pour du stockage à long terme."
#: templates/django_messages/view.html:6
msgid "View Message"
msgstr "Voir Message"
#: templates/django_messages/view.html:22
msgid "Delete"
msgstr "Effacer"
#: templates/notification/messages_deleted/full.txt:1
#, python-format
msgid "You have deleted the message '%(message)s'."
msgstr "Vous avez effacé le message '%(message)s'."
#: templates/notification/messages_deleted/notice.html:1
#, python-format
msgid ""
"You have deleted the message <a href=\"%(message_url)s\">%(message)s</a>."
msgstr ""
"Vous avez effacé le message <a href=\"%(message_url)s\">%(message)s</a>."
#: templates/notification/messages_received/full.txt:1
#, fuzzy, python-format
#| msgid "%(message_sender)s has sent you a reply to %(message_parent_msg)s."
msgid ""
"%(message_sender)s has sent you a message:\n"
"\n"
"%(message)s\n"
"\n"
"%(message_body)s\n"
"\n"
"http://%(current_site)s%(message_url)s"
msgstr ""
"%(message_sender)s vous a envoyé une réponse à %(message_parent_msg)s."
#: templates/notification/messages_received/notice.html:2
#, python-format
msgid ""
"You have received the message <a href=\"%(message_url)s\">%(message)s</a> "
"from %(message_sender)s."
msgstr ""
"Vous avez reçu le message <a href=\"%(message_url)s\">%(message)s</a> de "
"%(message_sender)s."
#: templates/notification/messages_received/short.txt:1
#: templates/notification/messages_reply_received/short.txt:1
#, python-format
msgid "%(notice)s by %(message_sender)s"
msgstr ""
#: templates/notification/messages_recovered/full.txt:1
#, python-format
msgid "You have recovered the message '%(message)s'."
msgstr "vous avez récupéré le message '%(message)s'."
#: templates/notification/messages_recovered/notice.html:1
#, python-format
msgid ""
"You have recovered the message <a href=\"%(message_url)s\">%(message)s</a>."
msgstr ""
"Vous avez récupéré le message <a href=\"%(message_url)s\">%(message)s</a>."
#: templates/notification/messages_replied/full.txt:1
#, python-format
msgid ""
"You have replied to '%(message_parent_msg)s' from %(message_recipient)s."
msgstr ""
"Vous avez répondu à '%(message_parent_msg)s' de %(message_recipient)s."
#: templates/notification/messages_replied/notice.html:2
#, python-format
msgid ""
"You have replied to <a href=\"%(message_url)s\">%(message_parent_msg)s</a> "
"from %(message_recipient)s."
msgstr ""
"Vous avez répondu à <a href=\"%(message_url)s\">%(message_parent_msg)s</a> "
"de %(message_recipient)s."
#: templates/notification/messages_reply_received/full.txt:1
#, python-format
msgid ""
"%(message_sender)s replied to '%(message_parent_msg)s':\n"
"\n"
"%(message)s\n"
"\n"
"%(message_body)s\n"
"\n"
"http://%(current_site)s%(message_url)s"
msgstr ""
#: templates/notification/messages_reply_received/notice.html:2
#, python-format
msgid "%(message_sender)s has sent you a reply to %(message_parent_msg)s."
msgstr ""
"%(message_sender)s vous a envoyé une réponse à %(message_parent_msg)s."
#: templates/notification/messages_sent/full.txt:1
#, python-format
msgid "You have sent the message '%(message)s' to %(message_recipient)s."
msgstr "Vous avez envoyé le message '%(message)s' à %(message_recipient)s."
#: templates/notification/messages_sent/notice.html:2
#, python-format
msgid ""
"You have sent the message <a href=\"%(message_url)s\">%(message)s</a> to "
"%(message_recipient)s."
msgstr ""
"Vous avez envoyé le message <a href=\"%(message_url)s\">%(message)s</a> à "
"%(message_recipient)s."
#: utils.py:26
#, python-format
msgid ""
"%(sender)s wrote:\n"
"%(body)s"
msgstr ""
"%(sender)s a écrit:\n"
"%(body)s"
#: utils.py:54
#, fuzzy, python-format
#| msgid "Re: %(subject)s"
msgid "Re%(prefix)s: %(subject)s"
msgstr "Re: %(subject)s"
#: utils.py:60
#, python-format
msgid "New Message: %(subject)s"
msgstr "Nouveau message: %(subject)s"
#: views.py:79 views.py:116
msgid "Message successfully sent."
msgstr "Message envoyé avec succès."
#: views.py:98 views.py:194
#, python-format
msgid "Re: %(subject)s"
msgstr "Re: %(subject)s"
#: views.py:159
msgid "Message successfully deleted."
msgstr "Message effacé avec succès."
#: views.py:186
msgid "Message successfully recovered."
msgstr "Message récupéré avec succès."
#~ msgid "There is no user with this username."
#~ msgstr "Il n'y a pas d'utilisateur avec ce nom d'utilisateur."
#~ msgid "New Message:"
#~ msgstr "Nouveau Message:"
#~ msgid "You have received a message from %(message_sender)s."
#~ msgstr "Vous avez reçu un message de %(message_sender)s."
#~ msgid ""
#~ "<a href=\"%(sender_url)s\">%(message_sender)s</a> has sent you a reply to "
#~ "'<a href=\"%(message_url)s\">%(message_parent_msg)s</a>'."
#~ msgstr ""
#~ "<a href=\"%(sender_url)s\">%(message_sender)s</a> vous a envoyé une "
#~ "réponse à '<a href=\"%(message_url)s\">%(message_parent_msg)s</a>'."

317
django_messages/locale/it/LC_MESSAGES/django.po

@ -1,317 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# Sergio Morstabilini <sergiomorstabilini@gmail.com>, 2010.
#
msgid ""
msgstr ""
"Project-Id-Version: messages\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-03-03 12:31-0700\n"
"PO-Revision-Date: 2010-03-03 21:58+0100\n"
"Last-Translator: Sergio Morstabilini <sergiomorstabilini@gmail.com>\n"
"Language-Team: Sergio Morstabilini <sergiomorstabilini@gmail.com>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-Language: Italian\n"
#: admin.py:13 forms.py:20 models.py:52 templates/messages/outbox.html:7
#: templates/messages/view.html:12
msgid "Recipient"
msgstr "Destinatario"
#: admin.py:38 models.py:88
msgid "Message"
msgstr "Messaggio"
#: forms.py:21 models.py:49 templates/messages/inbox.html:7
#: templates/messages/outbox.html:7 templates/messages/trash.html:7
#: templates/messages/view.html:6
msgid "Subject"
msgstr "Oggetto"
#: forms.py:22 models.py:50
msgid "Body"
msgstr "Messaggio"
#: management.py:9
msgid "Message Received"
msgstr "Messaggio Ricevuto"
#: management.py:9
msgid "you have received a message"
msgstr "hai ricevuto un messaggio"
#: management.py:10
msgid "Message Sent"
msgstr "Messaggio Inviato"
#: management.py:10
msgid "you have sent a message"
msgstr "hai inviato un messaggio"
#: management.py:11
msgid "Message Replied"
msgstr "Risposta Inviata"
#: management.py:11
msgid "you have replied to a message"
msgstr "hai risposto ad un messaggio"
#: management.py:12
msgid "Reply Received"
msgstr "Risposta Ricevuta"
#: management.py:12
msgid "you have received a reply to a message"
msgstr "hai ricevuto una risposta ad un messaggio"
#: management.py:13
msgid "Message Deleted"
msgstr "Messaggio Cancellato"
#: management.py:13
msgid "you have deleted a message"
msgstr "hai cancellato un messaggio"
#: management.py:14
msgid "Message Recovered"
msgstr "Messaggio Ripristinato"
#: management.py:14
msgid "you have undeleted a message"
msgstr "hai ripristinato un messaggio"
#: models.py:51 templates/messages/inbox.html:7
#: templates/messages/trash.html:7 templates/messages/view.html:8
msgid "Sender"
msgstr "Mittente"
#: models.py:53
msgid "Parent message"
msgstr "In risposta a"
#: models.py:54
msgid "sent at"
msgstr "inviato il"
#: models.py:55
msgid "read at"
msgstr "letto il"
#: models.py:56
msgid "replied at"
msgstr "risposto il"
#: models.py:57
msgid "Sender deleted at"
msgstr "Mittente cancellato il"
#: models.py:58
msgid "Recipient deleted at"
msgstr "Destinatario cancellato il"
#: models.py:89
msgid "Messages"
msgstr "Messaggi"
#: views.py:78 views.py:112
msgid "Message successfully sent."
msgstr "Messaggio inviato con successo."
#: views.py:118
#, python-format
msgid ""
"%(sender)s wrote:\n"
"%(body)s"
msgstr ""
"%(sender)s ha scritto:\n"
"%(body)s"
#: views.py:122
#, python-format
msgid "Re: %(subject)s"
msgstr "Re: %(subject)s"
#: views.py:158
msgid "Message successfully deleted."
msgstr "Messaggio cancellato con successo."
#: views.py:185
msgid "Message successfully recovered."
msgstr "Messaggio recuperato con successo."
#: templates/messages/base.html:8 templates/messages/inbox.html:4
#: templates/messages/new_message.html:10
msgid "Inbox"
msgstr "Messaggi Ricevuti"
#: templates/messages/base.html:9 templates/messages/outbox.html:4
msgid "Sent Messages"
msgstr "Messaggi Inviati"
#: templates/messages/base.html:10
msgid "New Message"
msgstr "Nuovo Messaggio"
#: templates/messages/base.html:11
msgid "Trash"
msgstr "Cestino"
#: templates/messages/compose.html:4
msgid "Compose Message"
msgstr "Scrivi Messaggio"
#: templates/messages/compose.html:9
msgid "Send"
msgstr "Invia"
#: templates/messages/inbox.html:7
msgid "Received"
msgstr "Ricevuto"
#: templates/messages/inbox.html:7 templates/messages/outbox.html:7
#: templates/messages/trash.html:7
msgid "Action"
msgstr "Azione"
#: templates/messages/inbox.html:19 templates/messages/outbox.html:16
#: templates/messages/trash.html:16 templates/messages/view.html:11
msgid "DATETIME_FORMAT"
msgstr "j F Y, G:i"
#: templates/messages/inbox.html:20 templates/messages/outbox.html:17
msgid "delete"
msgstr "cancella"
#: templates/messages/new_message.html:9
#, python-format
msgid "Sent from %(site_url)s"
msgstr "Spedito da %(site_url)s"
#: templates/messages/new_message.html:11 templates/messages/view.html:18
msgid "Reply"
msgstr "Rispondi"
#: templates/messages/outbox.html:7
msgid "Sent"
msgstr "Spedito"
#: templates/messages/trash.html:4
msgid "Deleted Messages"
msgstr "Messaggi Cancellati"
#: templates/messages/trash.html:7 templates/messages/view.html:10
msgid "Date"
msgstr "Data"
#: templates/messages/trash.html:17
msgid "undelete"
msgstr "ripristina"
#: templates/messages/trash.html:23
msgid "Deleted Messages are removed from the trash at unregular intervals, don't rely on this feature for long-time storage."
msgstr "I messaggi cancellati sono rimossi dal cestino ad intervalli irregolari, non affidatevi a questa cartella per salvare messaggi a lungo termine."
#: templates/messages/view.html:4
msgid "View Message"
msgstr "Vedi Messaggio"
#: templates/messages/view.html:20
msgid "Delete"
msgstr "Cancella"
#: templates/notification/messages_deleted/notice.html:1
#, python-format
msgid "You have deleted the message <a href=\"%(message_url)s\">%(message)s</a>."
msgstr "Hai cancellato il messaggio <a href=\"%(message_url)s\">%(message)s</a>."
#: templates/notification/messages_recovered/notice.html:1
#, python-format
msgid "You have recovered the message <a href=\"%(message_url)s\">%(message)s</a>."
msgstr "Hai ripristinato il messaggio <a href=\"%(message_url)s\">%(message)s</a>."
#: templates/notification/messages_received/notice.html:2
#, python-format
msgid "You have received the message <a href=\"%(message_url)s\">%(message)s</a> from %(message_sender)s."
msgstr "Hai ricevuto il messaggio <a href=\"%(message_url)s\">%(message)s</a> da %(message_sender)s."
#: templates/notification/messages_reply_received/notice.html:2
#, python-format
msgid "%(message_sender)s has sent you a reply to %(message_parent_msg)s."
msgstr "%(message_sender)s ha mandato una risposta a %(message_parent_msg)s."
#: templates/notification/messages_sent/notice.html:2
#, python-format
msgid "You have sent the message <a href=\"%(message_url)s\">%(message)s</a> to %(message_recipient)s."
msgstr "Hai inviato il messaggio <a href=\"%(message_url)s\">%(message)s</a> a %(message_recipient)s."
#: templates/notification/messages_replied/notice.html:2
#, python-format
msgid "You have replied to <a href=\"%(message_url)s\">%(message_parent_msg)s</a> from %(message_recipient)s."
msgstr "Hai risposto a <a href=\"%(message_url)s\">%(message_parent_msg)s</a> ricevuto da %(message_recipient)s."
#: templates/messages/new_message.html:1
#, python-format
msgid ""
"Hello %(recipient)s,\n"
"\n"
"you received a private message from %(sender)s with\n"
"the following contents:"
msgstr ""
"Ciao %(recipient)s,\n"
"\n"
"hai ricevuto un messaggio privato da %(sender)s con\n"
"il seguente contenuto:"
#: admin.py:16
msgid "Creates the message optionally for all users or a group of users."
msgstr "Crea il messaggio facoltativamente per tutti gli utenti o per un gruppo di utenti."
#: admin.py:15
msgid "group"
msgstr "gruppo"
#: admin.py:23
msgid "All users"
msgstr "Tutti gli utenti"
#: fields.py:53
#, python-format
msgid "The following usernames are incorrect: %(users)s"
msgstr "I seguenti nomi utente sono incorretti: %(users)s"
#: admin.py:45
msgid "Date/time"
msgstr "Data/ora"
#: utils.py:27
#, python-format
msgid "New Message: %(subject)s"
msgstr "Nuovo Messaggio: %(subject)s"
#~ msgid "There is no user with this username."
#~ msgstr "Non esiste un utente con questo nome."
#~ msgid "New Message:"
#~ msgstr "Nuovo Messaggio:"
#~ msgid "You have deleted the message '%(message)s'."
#~ msgstr "Hai cancellato il messaggio '%(message)s'."
#~ msgid "You have received a message from %(message_sender)s."
#~ msgstr "Hai ricevuto un messaggio da %(message_sender)s."
#~ msgid "You have recovered the message '%(message)s'."
#~ msgstr "Hai ripristinato il messaggio '%(message)s'."
#~ msgid "You have replied to '%(message_parent_msg)s' from %(message_recipient)s."
#~ msgstr "Hai risposto a '%(message_parent_msg)s' ricevuto da %(message_recipient)s."
#~ msgid "<a href=\"%(sender_url)s\">%(message_sender)s</a> has sent you a reply to '<a href=\"%(message_url)s\">%(message_parent_msg)s</a>'."
#~ msgstr "<a href=\"%(sender_url)s\">%(message_sender)s</a> ha risposto a '<a href=\"%(message_url)s\">%(message_parent_msg)s</a>'."
#~ msgid "You have sent the message '%(message)s' to %(message_recipient)s."
#~ msgstr "Hai spedito il messaggio '%(message)s' a %(message_recipient)s."

292
django_messages/locale/ko/LC_MESSAGES/django.po

@ -1,292 +0,0 @@
# django-messages translation for Korean.
# Copyright (C) 2012 Jeong YunWon
# This file is distributed under the same license as the django-messages package.
# Jeong YunWon <jeong@youknowone.org>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: messages\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-09-11 12:31-0700\n"
"PO-Revision-Date: 2012-02-04 10:58+0900\n"
"Last-Translator: Jeong YunWon <jeong@youknowone.org>\n"
"Language-Team: Jeong YunWon <jeong@youknowone.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-Language: Korean\n"
#: admin.py:13 forms.py:20 models.py:52 templates/messages/outbox.html:7
#: templates/messages/view.html:12
msgid "Recipient"
msgstr "받는이"
#: admin.py:38 models.py:88
msgid "Message"
msgstr "쪽지"
#: forms.py:21 models.py:49 templates/messages/inbox.html:7
#: templates/messages/outbox.html:7 templates/messages/trash.html:7
#: templates/messages/view.html:6
msgid "Subject"
msgstr "제목"
#: forms.py:22 models.py:50
msgid "Body"
msgstr "내용"
#: management.py:9
msgid "Message Received"
msgstr "받은 시각"
#: management.py:9
msgid "you have received a message"
msgstr "쪽지를 받았습니다"
#: management.py:10
msgid "Message Sent"
msgstr "쪽지 보냄"
#: management.py:10
msgid "you have sent a message"
msgstr "쪽지를 보냈습니다"
#: management.py:11
msgid "Message Replied"
msgstr "쪽지 답장"
#: management.py:11
msgid "you have replied to a message"
msgstr "쪽지에 답장하였습니다"
#: management.py:12
msgid "Reply Received"
msgstr "답장 받음"
#: management.py:12
msgid "you have received a reply to a message"
msgstr "쪽지에 답장을 받았습니다"
#: management.py:13
msgid "Message Deleted"
msgstr "쪽지 지움"
#: management.py:13
msgid "you have deleted a message"
msgstr "쪽지를 지웠습니다"
#: management.py:14
msgid "Message Recovered"
msgstr "쪽지 되살림"
#: management.py:14
msgid "you have undeleted a message"
msgstr "쪽지를 되살렸습니다"
#: models.py:51 templates/messages/inbox.html:7
#: templates/messages/trash.html:7 templates/messages/view.html:8
msgid "Sender"
msgstr "보낸이"
#: models.py:53
msgid "Parent message"
msgstr "이전 쪽지"
#: models.py:54
msgid "sent at"
msgstr "보낸 시각:"
#: models.py:55
msgid "read at"
msgstr "읽은 시각:"
#: models.py:56
msgid "replied at"
msgstr "답장 시각:"
#: models.py:57
msgid "Sender deleted at"
msgstr "보낸이가 지운 시각:"
#: models.py:58
msgid "Recipient deleted at"
msgstr "받는이가 지운 시각:"
#: models.py:89
msgid "Messages"
msgstr "쪽지"
#: views.py:78 views.py:112
msgid "Message successfully sent."
msgstr "쪽지를 보냈습니다."
#: views.py:118
#, python-format
msgid ""
"%(sender)s wrote:\n"
"%(body)s"
msgstr ""
"%(sender)s 님의 글:\n"
"%(body)s"
#: views.py:122
#, python-format
msgid "Re: %(subject)s"
msgstr "Re: %(subject)s"
#: views.py:158
msgid "Message successfully deleted."
msgstr "쪽지를 지웠습니다."
#: views.py:185
msgid "Message successfully recovered."
msgstr "쪽지를 되살렸습니다."
#: templates/messages/base.html:8 templates/messages/inbox.html:4
#: templates/messages/new_message.html:10
msgid "Inbox"
msgstr "받은 편지함"
#: templates/messages/base.html:9 templates/messages/outbox.html:4
msgid "Sent Messages"
msgstr "보낸 편지함"
#: templates/messages/base.html:10
msgid "New Message"
msgstr "새 쪽지"
#: templates/messages/base.html:11
msgid "Trash"
msgstr "휴지통"
#: templates/messages/compose.html:4
msgid "Compose Message"
msgstr "새 쪽지 쓰기"
#: templates/messages/compose.html:9
msgid "Send"
msgstr "보내기"
#: templates/messages/inbox.html:7
msgid "Received"
msgstr "받은 시각"
#: templates/messages/inbox.html:7 templates/messages/outbox.html:7
#: templates/messages/trash.html:7
msgid "Action"
msgstr "할일"
#: templates/messages/inbox.html:19 templates/messages/outbox.html:16
#: templates/messages/trash.html:16 templates/messages/view.html:11
msgid "DATETIME_FORMAT"
msgstr "Y-m-d G:i"
#: templates/messages/inbox.html:20 templates/messages/outbox.html:17
msgid "delete"
msgstr "지우기"
#: templates/messages/new_message.html:9
#, python-format
msgid "Sent from %(site_url)s"
msgstr "%(site_url)s 에서 보냄"
#: templates/messages/new_message.html:11 templates/messages/view.html:18
msgid "Reply"
msgstr "답장"
#: templates/messages/outbox.html:7
msgid "Sent"
msgstr "보낸 시각"
#: templates/messages/trash.html:4
msgid "Deleted Messages"
msgstr "지운 쪽지"
#: templates/messages/trash.html:7 templates/messages/view.html:10
msgid "Date"
msgstr "날짜"
#: templates/messages/trash.html:17
msgid "undelete"
msgstr "되살리기"
#: templates/messages/trash.html:23
msgid "Deleted Messages are removed from the trash at unregular intervals, don't rely on this feature for long-time storage."
msgstr "지운 쪽지는 비정기적으로 휴지통에서 완전히 삭제됩니다. 오래 보관해야 하는 쪽지에 이 기능을 사용하지 마세요."
#: templates/messages/view.html:4
msgid "View Message"
msgstr "쪽지 보기"
#: templates/messages/view.html:20
msgid "Delete"
msgstr "지우기"
#: templates/notification/messages_deleted/notice.html:1
#, python-format
msgid "You have deleted the message <a href=\"%(message_url)s\">%(message)s</a>."
msgstr "<a href=\"%(message_url)s\">%(message)s</a> 지윘습니다."
#: templates/notification/messages_recovered/notice.html:1
#, python-format
msgid "You have recovered the message <a href=\"%(message_url)s\">%(message)s</a>."
msgstr "<a href=\"%(message_url)s\">%(message)s</a> 되살렸습니다."
#: templates/notification/messages_received/notice.html:2
#, python-format
msgid "You have received the message <a href=\"%(message_url)s\">%(message)s</a> from %(message_sender)s."
msgstr "%(message_sender)s 님에게 <a href=\"%(message_url)s\">%(message)s</a> 받았습니다."
#: templates/notification/messages_reply_received/notice.html:2
#, python-format
msgid "%(message_sender)s has sent you a reply to %(message_parent_msg)s."
msgstr "%(message_sender)s 님이 %(message_parent_msg)s 에 답장을 보냈습니다."
#: templates/notification/messages_sent/notice.html:2
#, python-format
msgid "You have sent the message <a href=\"%(message_url)s\">%(message)s</a> to %(message_recipient)s."
msgstr "%(message_recipient)s 님에게 <a href=\"%(message_url)s\">%(message)s</a> 보냈습니다."
#: templates/notification/messages_replied/notice.html:2
#, python-format
msgid "You have replied to <a href=\"%(message_url)s\">%(message_parent_msg)s</a> from %(message_recipient)s."
msgstr "%(message_recipient)s 님의 <a href=\"%(message_url)s\">%(message_parent_msg)s</a> 에 답장하였습니다."
#: templates/messages/new_message.html:1
#, python-format
msgid ""
"Hello %(recipient)s,\n"
"\n"
"you received a private message from %(sender)s with\n"
"the following contents:"
msgstr ""
"%(recipient)s 님\n"
"\n"
"%(sender)s 님께 다음 내용으로 쪽지를 받았습니다:"
#: admin.py:16
msgid "Creates the message optionally for all users or a group of users."
msgstr "Creates the message optionally for all users or a group of users."
#: admin.py:15
msgid "group"
msgstr "그룹"
#: admin.py:23
msgid "All users"
msgstr "모든 사용자"
#: fields.py:53
#, python-format
msgid "The following usernames are incorrect: %(users)s"
msgstr "올바르지 않은 사용자 이름을 입력하였습니다: %(users)s"
#: admin.py:45
msgid "Date/time"
msgstr "날짜/시각"
#: utils.py:27
#, python-format
msgid "New Message: %(subject)s"
msgstr "새 쪽지: %(subject)s"

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

Loading…
Cancel
Save