Browse Source

Merge branch 'devel' of https://github.com/bashmak/djing into tariffs

devel
Dmitry 9 years ago
parent
commit
b9b5889ca2
  1. 33
      abonapp/tests.py
  2. 8
      agent/mod_mikrotik.py
  3. 16
      agent/settings.py
  4. 25
      clientsideapp/views.py
  5. 69
      djing/utils/load_from_nodeny.py
  6. 182
      djing/utils/save_from_nodeny.py
  7. 15
      taskapp/handle.py
  8. 362
      taskapp/locale/ru/LC_MESSAGES/django.po
  9. 15
      taskapp/models.py
  10. 13
      taskapp/views.py

33
abonapp/tests.py

@ -1,3 +1,4 @@
from django.shortcuts import resolve_url
from django.test import TestCase from django.test import TestCase
from django.test.client import Client from django.test.client import Client
from agent import NasNetworkError from agent import NasNetworkError
@ -86,11 +87,12 @@ class AbonTestCase(TestCase):
c = Client() c = Client()
# login # login
c.post('/accounts/login/', {'login': '1234567', 'password': 'ps'})
resp = c.get('/abons/1/1/complete_service1')
c.post(resolve_url('acc_app:login'), {'login': '1234567', 'password': 'ps'})
url = resolve_url('abonapp:compl_srv', gid=1, uid=1, srvid=1)
resp = c.get(url)
print('RESP:', resp) print('RESP:', resp)
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
resp = c.post('/abons/1/1/complete_service1', data={
resp = c.post(url, data={
'finish_confirm': 'yes' 'finish_confirm': 'yes'
}) })
print('RESP:', resp) print('RESP:', resp)
@ -108,13 +110,16 @@ class AbonTestCase(TestCase):
from hashlib import md5 from hashlib import md5
from djing.settings import pay_SECRET, pay_SERV_ID from djing.settings import pay_SECRET, pay_SERV_ID
import xmltodict import xmltodict
def sig(act, pay_account, pay_id): def sig(act, pay_account, pay_id):
md = md5() md = md5()
s = '_'.join((str(act), str(pay_account), pay_SERV_ID, str(pay_id), pay_SECRET)) s = '_'.join((str(act), str(pay_account), pay_SERV_ID, str(pay_id), pay_SECRET))
md.update(bytes(s, 'utf-8')) md.update(bytes(s, 'utf-8'))
return md.hexdigest() return md.hexdigest()
c = Client() c = Client()
r = c.get('/abons/pay', {
url = resolve_url('abonapp:terminal_pay')
r = c.get(url, {
'ACT': 1, 'PAY_ACCOUNT': '1234567', 'ACT': 1, 'PAY_ACCOUNT': '1234567',
'SERVICE_ID': pay_SERV_ID, 'SERVICE_ID': pay_SERV_ID,
'PAY_ID': 3561234, 'PAY_ID': 3561234,
@ -123,7 +128,7 @@ class AbonTestCase(TestCase):
}) })
xobj = xmltodict.parse(r.content) xobj = xmltodict.parse(r.content)
self.assertEqual(int(xobj['pay-response']['status_code']), 21) self.assertEqual(int(xobj['pay-response']['status_code']), 21)
r = c.get('/abons/pay', {
r = c.get(url, {
'ACT': 4, 'PAY_ACCOUNT': '1234567', 'ACT': 4, 'PAY_ACCOUNT': '1234567',
'SERVICE_ID': pay_SERV_ID, 'SERVICE_ID': pay_SERV_ID,
'PAY_ID': 3561234, 'PAY_ID': 3561234,
@ -133,7 +138,7 @@ class AbonTestCase(TestCase):
}) })
xobj = xmltodict.parse(r.content) xobj = xmltodict.parse(r.content)
self.assertEqual(int(xobj['pay-response']['status_code']), 22) self.assertEqual(int(xobj['pay-response']['status_code']), 22)
r = c.get('/abons/pay', {
r = c.get(url, {
'ACT': 4, 'PAY_ACCOUNT': '1234567', 'ACT': 4, 'PAY_ACCOUNT': '1234567',
'SERVICE_ID': pay_SERV_ID, 'SERVICE_ID': pay_SERV_ID,
'PAY_ID': 3561234, 'PAY_ID': 3561234,
@ -143,7 +148,7 @@ class AbonTestCase(TestCase):
}) })
xobj = xmltodict.parse(r.content) xobj = xmltodict.parse(r.content)
self.assertEqual(int(xobj['pay-response']['status_code']), -100) self.assertEqual(int(xobj['pay-response']['status_code']), -100)
r = c.get('/abons/pay', {
r = c.get(url, {
'ACT': 7, 'PAY_ACCOUNT': '1234567', 'ACT': 7, 'PAY_ACCOUNT': '1234567',
'SERVICE_ID': pay_SERV_ID, 'SERVICE_ID': pay_SERV_ID,
'PAY_ID': 3561234, 'PAY_ID': 3561234,
@ -166,10 +171,11 @@ class AbonTestCase(TestCase):
def test_add_abon(self): def test_add_abon(self):
c = Client() c = Client()
c.login(username='1234567', password='ps') c.login(username='1234567', password='ps')
r = c.get('/abons/1/addabon')
url = resolve_url('abonapp:add_abon', gid=1)
r = c.get(url)
# поглядим на страницу добавления абонента # поглядим на страницу добавления абонента
self.assertEqual(r.status_code, 200) self.assertEqual(r.status_code, 200)
r = c.post('/abons/1/addabon', {
r = c.post(url, {
'username': '123', 'username': '123',
'password': 'ps', 'password': 'ps',
'fio': 'Abon Fio', 'fio': 'Abon Fio',
@ -177,7 +183,7 @@ class AbonTestCase(TestCase):
'is_active': True 'is_active': True
}) })
self.assertEqual(r.status_code, 302) self.assertEqual(r.status_code, 302)
r = c.get('/abons/324/addabon')
r = c.get(resolve_url('abonapp:add_abon', gid=324))
self.assertEqual(r.status_code, 404) self.assertEqual(r.status_code, 404)
try: try:
abn = Abon.objects.get(username='123') abn = Abon.objects.get(username='123')
@ -191,6 +197,13 @@ class AbonTestCase(TestCase):
# должен быть пароль абонента простым текстом # должен быть пароль абонента простым текстом
self.assertTrue(False) self.assertTrue(False)
# пробуем удалить абонента
def test_view_delentity(self):
c = Client()
c.login(username='1234567', password='ps')
url = resolve_url('abonapp:del_abon') + '?t=a&id=1'
r = c.get('/abons/1/addabon')
class AbonTariffTestCase(TestCase): class AbonTariffTestCase(TestCase):
def setUp(self): def setUp(self):

8
agent/mod_mikrotik.py

@ -226,7 +226,9 @@ class QueueManager(TransmitterManager):
'=name=uid%d' % user.uid, '=name=uid%d' % user.uid,
#FIXME: тут в разных микротиках или =target-addresses или =target #FIXME: тут в разных микротиках или =target-addresses или =target
'=target=%s' % user.ip.get_str(), '=target=%s' % user.ip.get_str(),
'=max-limit=%.3fM/%.3fM' % (user.tariff.speedOut, user.tariff.speedIn)
'=max-limit=%.3fM/%.3fM' % (user.tariff.speedOut, user.tariff.speedIn),
'=queue=MikroBILL_SFQ/MikroBILL_SFQ',
'=burst-time=1/1'
]) ])
def remove(self, user): def remove(self, user):
@ -251,7 +253,9 @@ class QueueManager(TransmitterManager):
'=name=uid%d' % user.uid, '=name=uid%d' % user.uid,
'=max-limit=%.3fM/%.3fM' % (user.tariff.speedOut, user.tariff.speedIn), '=max-limit=%.3fM/%.3fM' % (user.tariff.speedOut, user.tariff.speedIn),
#FIXME: тут в разных микротиках или =target-addresses или =target #FIXME: тут в разных микротиках или =target-addresses или =target
'=target=%s' % user.ip.get_str()
'=target=%s' % user.ip.get_str(),
'=queue=MikroBILL_SFQ/MikroBILL_SFQ',
'=burst-time=1/1'
]) ])
# читаем шейпер, возващаем записи о шейпере # читаем шейпер, возващаем записи о шейпере

16
agent/settings.py

@ -1,16 +0,0 @@
# -*- coding: utf-8 -*-
# Для установки модуля NAS смотрите в __init__
# Certificates
CERTFILE = "/etc/ssl/server.crt"
KEYFILE = "/etc/ssl/server.key"
# Использовать-ли при передаче инфы между NAS и основным сервером SSL
IS_USE_SSL = False
NAS_IP = '10.12.1.11'
NAS_LOGIN = 'admin'
NAS_PASSW = '2ekc3'
NAS_PORT = 8728

25
clientsideapp/views.py

@ -43,18 +43,23 @@ def services(request):
def buy_service(request, srv_id): def buy_service(request, srv_id):
abon = get_object_or_404(Abon, id=request.user.pk) abon = get_object_or_404(Abon, id=request.user.pk)
service = get_object_or_404(Tariff, id=srv_id) service = get_object_or_404(Tariff, id=srv_id)
try:
current_service = abon.active_tariff() current_service = abon.active_tariff()
if request.method == 'POST': if request.method == 'POST':
abon.pick_tariff(service, request.user, 'Покупка тарифного плана через личный кабинет, тариф "%s"' abon.pick_tariff(service, request.user, 'Покупка тарифного плана через личный кабинет, тариф "%s"'
% service) % service)
messages.success(request, 'Вы подписались на новую услугу. Она встала на очередь подключений. ' messages.success(request, 'Вы подписались на новую услугу. Она встала на очередь подключений. '
'Когда закончится ваша текущая услуга, то включится эта') 'Когда закончится ваша текущая услуга, то включится эта')
return redirect('client_side:services')
else:
return render_to_text('clientsideapp/modal_service_buy.html', { return render_to_text('clientsideapp/modal_service_buy.html', {
'service': service, 'service': service,
'current_service': current_service 'current_service': current_service
}, request=request) }, request=request)
except LogicError as e:
messages.error(request, e)
except NasFailedResult as e:
messages.error(request, e)
return redirect('client_side:services')
@login_required @login_required
@ -62,6 +67,7 @@ def complete_service(request, srv_id):
abtar = get_object_or_404(AbonTariff, id=srv_id) abtar = get_object_or_404(AbonTariff, id=srv_id)
service = abtar.tariff service = abtar.tariff
try:
if request.method == 'POST': if request.method == 'POST':
# досрочно завершаем услугу # досрочно завершаем услугу
finish_confirm = request.POST.get('finish_confirm') finish_confirm = request.POST.get('finish_confirm')
@ -77,15 +83,20 @@ def complete_service(request, srv_id):
) )
else: else:
messages.error(request, 'Действие не подтверждено') messages.error(request, 'Действие не подтверждено')
return redirect('client_side:services')
else:
time_use = RuTimedelta(timezone.now() - abtar.time_start) time_use = RuTimedelta(timezone.now() - abtar.time_start)
return render_to_text('clientsideapp/modal_complete_service.html', { return render_to_text('clientsideapp/modal_complete_service.html', {
'service': service, 'service': service,
'abtar': abtar, 'abtar': abtar,
'time_use': time_use 'time_use': time_use
}, request=request) }, request=request)
except LogicError as e:
messages.error(request, e)
except NasFailedResult as e:
messages.error(request, e)
except NasNetworkError:
messages.error(request, 'Временные неполадки')
return redirect('client_side:services')
@login_required @login_required
@ -107,6 +118,10 @@ def unsubscribe_service(request, srv_id):
}, request=request) }, request=request)
except AbonTariff.DoesNotExist: except AbonTariff.DoesNotExist:
messages.error(request, 'Указанная подписка на услугу не найдена') messages.error(request, 'Указанная подписка на услугу не найдена')
except NasFailedResult as e:
messages.error(request, e)
except NasNetworkError:
messages.error(request, 'Временные неполадки')
return redirect('client_side:services') return redirect('client_side:services')

69
djing/utils/load_from_nodeny.py

@ -1,48 +1,55 @@
#!/bin/env python2
#!/bin/env python3
# coding=utf-8 # coding=utf-8
import os
import MySQLdb import MySQLdb
from json import dumps from json import dumps
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djing.settings")
db = MySQLdb.connect(host="localhost", user="root", passwd="PASSWORD", db="nodeny", charset='utf8')
cursor = db.cursor()
result = dict()
def load_users(cursor, grp_id):
# выбираем абонентов # выбираем абонентов
sql = r"SELECT users.name, users.fio, data0._adr_telefon, dictionary.v, data0._adr_house, data0._birthday, users.grp FROM users LEFT JOIN data0 ON (data0.uid=users.id) LEFT JOIN dictionary ON (dictionary.k=data0._adr_street AND dictionary.type='street') WHERE users.grp=23"
sql = r"SELECT users.name, users.fio, data0._adr_telefon, dictionary.v AS street, data0._adr_house, data0._birthday, users.grp, INET_NTOA(ip_pool.ip) AS ip, users.balance, AES_DECRYPT(users.passwd, 'Vu6saiZa') as decr_passwd FROM users LEFT JOIN data0 ON (data0.uid = users.id) LEFT JOIN dictionary ON (dictionary.k = data0._adr_street AND dictionary.type = 'street') LEFT JOIN ip_pool ON (ip_pool.uid = users.id) WHERE users.grp = %d" % grp_id
cursor.execute(sql) cursor.execute(sql)
result['users'] = list()
res = cursor.fetchone()
while res:
result['users'].append({
'name': res[0],
'fio': res[1],
'tel': res[2],
'addr': u"ул. %s д. %s" % (res[3], res[4]),
'birth': int(res[5]),
'grp': int(res[6])
})
res = cursor.fetchone()
users = [{
'name': str(res[0]),
'fio': str(res[1]),
'tel': str(res[2]),
'street': str(res[3] or ''),
'house': str(res[4]),
'birth': res[5],
'grp': int(res[6]),
'ip': str(res[7] or ''),
'balance': float(res[8]),
'passw': res[9].decode("utf-8") if res[9] is not None else ''
} for res in cursor.fetchall()]
return users
def load_groups(cursor):
# выбираем группы # выбираем группы
sql = r'SELECT grp_id, grp_name FROM user_grp' sql = r'SELECT grp_id, grp_name FROM user_grp'
cursor.execute(sql) cursor.execute(sql)
result['groups'] = list()
res = cursor.fetchone()
while res:
result['groups'].append({
groups = list()
for res in cursor.fetchall():
users = load_users(cursor=cursor, grp_id=int(res[0]))
groups.append({
'gid': int(res[0]), 'gid': int(res[0]),
'gname': res[1]
'gname': res[1],
'users': users
}) })
res = cursor.fetchone()
return groups
if __name__ == "__main__":
db = MySQLdb.connect(host="127.0.0.1", user="<username>", passwd="<password>", db="db", charset='utf8')
cursor = db.cursor()
result = dict()
result['groups'] = load_groups(cursor=cursor)
db.close() db.close()
f = open('dump_chkal.json', 'w')
f.write(dumps(result, ensure_ascii=False).encode('utf8'))
f = open('dump.json', 'w')
f.write(dumps(result, ensure_ascii=False))
f.close() f.close()

182
djing/utils/save_from_nodeny.py

@ -4,67 +4,143 @@
import os import os
from json import load from json import load
import django import django
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djing.settings") os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djing.settings")
django.setup() django.setup()
from abonapp.models import Abon, AbonGroup, AbonTariff, AbonRawPassword
from abonapp.models import Abon, AbonGroup, AbonRawPassword, AbonStreet
from ip_pool.models import IpPoolItem from ip_pool.models import IpPoolItem
from tariff_app.models import Tariff
from accounts_app.models import UserProfile
with open('dump_pshen.json', 'r') as f:
dat = load(f)
#for dt in dat['groups']:
# try:
# grp = AbonGroup.objects.get(title=dt['gname'])
# except AbonGroup.DoesNotExist:
# grp = AbonGroup(title=dt['gname'])
# grp.save()
# dt['obj'] = grp
grp = AbonGroup.objects.get(id=43)
pshen_trf = Tariff.objects.get(id=3)
print(pshen_trf)
iam = UserProfile.objects.get(id=1)
for dt in dat['users']:
#grp = [gr for gr in dat['groups'] if dt['grp']==gr['gid']]
#grp = grp[0]['obj'] if len(grp)>0 else None
class DumpAbon(object):
def __init__(self, obj=None):
if obj is None: return
self.name = obj['name']
self.fio = obj['fio']
self.tel = obj['tel']
self.street = obj['street']
self.house = obj['house']
self.birth = obj['birth']
self.grp = obj['grp']
self.ip = obj['ip']
self.balance = obj['balance']
self.passw = obj['passw']
@staticmethod
def build_from_django(obj):
assert isinstance(obj, Abon)
self = DumpAbon()
self.name = obj.username
self.fio = obj.fio
self.tel = obj.telephone
self.street = obj.street
self.house = obj.house
self.birth = obj.birth_day
self.grp = obj.group.pk
self.ip = obj.ip_address
self.balance = obj.ballance
try: try:
abon = Abon.objects.get(username=dt['name'])
raw_passw = AbonRawPassword.objects.get(account=obj)
except AbonRawPassword.DoesNotExist:
raw_passw = ''
self.passw = raw_passw
return self
def __eq__(self, other):
assert isinstance(other, DumpAbon)
r = self.name == other.name
r = r and self.name == other.name
r = r and self.fio == other.fio
r = r and self.tel == other.tel
r = r and self.street == other.street
r = r and self.house == other.house
r = r and self.birth == other.birth
r = r and self.grp == other.grp
r = r and self.ip == other.ip
r = r and self.balance == other.ballance
return r
def __ne__(self, other):
return not self.__eq__(other)
def load_users(obj, group):
for usr in obj:
# абонент из дампа
dump_abon = DumpAbon(usr)
# абонент из биллинга
print('\t', dump_abon.name, dump_abon.fio, dump_abon.ip)
try:
abon = Abon.objects.get(username=dump_abon.name)
bl_abon = DumpAbon.build_from_django(abon)
if bl_abon != dump_abon:
update_user(abon, dump_abon, group)
except Abon.DoesNotExist: except Abon.DoesNotExist:
abon = Abon(username=dt['name'])
# добавляем абонента
add_user(dump_abon, group)
def add_user(obj, user_group):
assert isinstance(obj, DumpAbon)
street = None
ip = None
try: try:
ip_addr = IpPoolItem.objects.get(ip=dt['ip'])
ip = IpPoolItem.objects.get(ip=obj.ip)
street = AbonStreet.objects.get(name=obj.street)
except IpPoolItem.DoesNotExist: except IpPoolItem.DoesNotExist:
ip_addr = None
abon.fio = dt['fio']
abon.telephone=dt['tel']
abon.house=dt['addr']
abon.group=grp
abon.ballance=dt['balance']
abon.ip_address=ip_addr
abon.set_password(dt['passw'])
abon.save()
try:
abon_raw_passw = AbonRawPassword.objects.get(account=abon)
abon_raw_passw.passw_text = dt['passw']
abon_raw_passw.save(update_fields=['passw_text'])
except AbonRawPassword.DoesNotExist:
AbonRawPassword.objects.create(
account=abon,
passw_text=dt['passw']
ip = IpPoolItem.objects.create(ip=obj.ip)
except AbonStreet.DoesNotExist:
street = AbonStreet.objects.create(name=obj.street, group=user_group)
Abon.objects.create(
username=obj.name,
fio=obj.fio,
telephone=obj.tel,
street=street,
house=obj.house,
birth_day=obj.birth,
group = user_group,
ip_address=ip,
ballance=obj.balance
) )
abtrfs = AbonTariff.objects.filter(abon=abon)
if abtrfs.count() > 0:
abtrf = abtrfs[0]
else:
abtrf = AbonTariff()
abtrf.abon = abon
abtrf.tariff = pshen_trf
abtrf.save()
abtrf.activate(iam)
print(abon.username, abon.fio, abon.group, ip_addr)
def update_user(db_abon, obj, user_group):
assert isinstance(obj, DumpAbon)
assert isinstance(db_abon, Abon)
street = None
ip = None
try:
ip = IpPoolItem.objects.get(ip=obj.ip)
street = AbonStreet.objects.get(name=obj.street, group=user_group)
except IpPoolItem.DoesNotExist:
if obj.ip:
ip = IpPoolItem.objects.create(ip=obj.ip)
except AbonStreet.DoesNotExist:
street = AbonStreet.objects.create(name=obj.street, group=user_group)
db_abon.fio = obj.fio
db_abon.telephone = obj.tel
db_abon.street = street
db_abon.house = obj.house
#db_abon.birth_day = datetime(obj.birth)
db_abon.group = user_group
db_abon.ip_address = ip
db_abon.ballance = obj.balance
db_abon.save()
if __name__ == "__main__":
with open('dump.json', 'r') as f:
dat = load(f)
for grp in dat['groups']:
try:
abgrp=AbonGroup.objects.get(title=grp['gname'])
except AbonGroup.DoesNotExist:
abgrp = AbonGroup.objects.create(
title=grp['gname']
)
print(grp['gname'])
load_users(grp['users'], abgrp)

15
taskapp/handle.py

@ -21,16 +21,19 @@ def handle(task, author, recipient, abon_group):
# Если задача завершена # Если задача завершена
elif task.state == 'F': elif task.state == 'F':
text = _('Task completed') text = _('Task completed')
# Меняем телефон назначения на телефон автора, т.к. при завершении
# Меняем цель назначения на автора, т.к. при завершении
# идёт оповещение автору о выполнении # идёт оповещение автору о выполнении
dst_account = author dst_account = author
fulltext="%s: %s. " % (text, task.abon.get_full_name())
fulltext="%s:\n%s\n" % (text, task.abon.get_full_name())
fulltext += _('locality %s.\n') % abon_group.title
if task.abon: if task.abon:
fulltext += _('address %(task.abon.address)s. telephone %(task.abon.telephone)s. ') % (
task.abon.address, task.abon.telephone
fulltext += _('address %s %s.\ntelephone %s\n') % (
task.abon.street.name if task.abon.street is not None else '<'+_('not chosen')+'>',
task.abon.house,
task.abon.telephone
) )
fulltext += _('locality %(abon_group.title)s. Task type - %(task.get_mode_display)s. ') % (abon_group.title, task.get_mode_display())
fulltext += task.descr if task.descr else _('Not assigned')
fulltext += _('Task type - %s.\n') % task.get_mode_display()
fulltext += task.descr if task.descr else ''
send_notify(fulltext, dst_account) send_notify(fulltext, dst_account)
except ChatException as e: except ChatException as e:
raise TaskException(e) raise TaskException(e)

362
taskapp/locale/ru/LC_MESSAGES/django.po

@ -1,362 +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.
# Dmitry Novikov nerosketch@gmail.com, 2017.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-27 12:27+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Dmitry Novikov nerosketch@gmail.com\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
"%100>=11 && n%100<=14)? 2 : 3);\n"
#: taskapp/forms.py:16
msgid "Short description"
msgstr "Краткое описание"
#: taskapp/handle.py:14
msgid "Task"
msgstr "Задача"
#: taskapp/handle.py:23
msgid "Task completed"
msgstr "Задача завершена"
#: taskapp/handle.py:29
#, python-format
msgid "address %s. telephone %s. "
msgstr "по адресу %s тел. %s. "
#: taskapp/handle.py:32
#, python-format
msgid "locality %s. Task type - %s. "
msgstr "с. %s. Тип задачи - %s. "
#: taskapp/handle.py:33 taskapp/templates/taskapp/view.html.py:34
msgid "Not assigned"
msgstr "&lt;Не назначено&gt;"
#: taskapp/models.py:13
msgid "Higher"
msgstr "Высший"
#: taskapp/models.py:14
msgid "Average"
msgstr "Средний"
#: taskapp/models.py:15
msgid "Low"
msgstr "Низкий"
#: taskapp/models.py:19
msgid "New"
msgstr "Новая"
#: taskapp/models.py:20
msgid "In fulfilling"
msgstr "На выполнении"
#: taskapp/models.py:21
msgid "Completed"
msgstr "Выполнена"
#: taskapp/models.py:25
msgid "not chosen"
msgstr "не выбрано"
#: taskapp/models.py:26
msgid "yellow triangle"
msgstr "жёлтый треугольник"
#: taskapp/models.py:27
msgid "red cross"
msgstr "красный крестик"
#: taskapp/models.py:28
msgid "weak speed"
msgstr "слабая скорость"
#: taskapp/models.py:29
msgid "cable break"
msgstr "обрыв кабеля"
#: taskapp/models.py:30
msgid "connection"
msgstr "подключение"
#: taskapp/models.py:31
msgid "periodic disappearance"
msgstr "переодическое пропадание"
#: taskapp/models.py:32
msgid "router setup"
msgstr "настройка роутера"
#: taskapp/models.py:33
msgid "configure onu"
msgstr "настроить onu"
#: taskapp/models.py:34
msgid "crimp cable"
msgstr "обжать кабель"
#: taskapp/models.py:35
msgid "other"
msgstr "другое"
#: taskapp/models.py:42
msgid "Change task"
msgstr "Изменение задачи"
#: taskapp/models.py:43
msgid "Create task"
msgstr "Создание задачи"
#: taskapp/models.py:44
msgid "Delete task"
msgstr "Удаление задачи"
#: taskapp/models.py:45
msgid "Completing tasks"
msgstr "Завершение задачи"
#: taskapp/models.py:46
msgid "The task started"
msgstr "Задача начата"
#: taskapp/models.py:77
msgid "Access to all tasks"
msgstr "Доступ ко всем задачам"
#: taskapp/models.py:78
msgid "Reminders of tasks"
msgstr "Напоминания о задачах"
#: taskapp/templates/taskapp/add_edit_task.html:7
#: taskapp/templates/taskapp/tasklist_all.html:7
#: taskapp/templates/taskapp/view.html:7
msgid "Tasks"
msgstr "Задачи"
#: taskapp/templates/taskapp/add_edit_task.html:8
#: taskapp/templates/taskapp/tasklist.html:48
#: taskapp/templates/taskapp/tasklist_active.html:46
#: taskapp/templates/taskapp/tasklist_all.html:54
#: taskapp/templates/taskapp/tasklist_finish.html:43
#: taskapp/templates/taskapp/tasklist_own.html:40
msgid "Edit"
msgstr "Редактировать"
#: taskapp/templates/taskapp/add_edit_task.html:8
msgid "Create"
msgstr "Создать"
#: taskapp/templates/taskapp/add_edit_task.html:15
#: taskapp/templates/taskapp/footer_btns.html:3
#: taskapp/templates/taskapp/footer_btns.html:4
#: taskapp/templates/taskapp/tasklist_all.html:75
#: taskapp/templates/taskapp/tasklist_all.html:76
msgid "Add new task"
msgstr "Добавьте новую задачу"
#: taskapp/templates/taskapp/add_edit_task.html:27
#: taskapp/templates/taskapp/tasklist.html:10
#: taskapp/templates/taskapp/tasklist_active.html:10
#: taskapp/templates/taskapp/tasklist_all.html:22
#: taskapp/templates/taskapp/tasklist_finish.html:10
#: taskapp/templates/taskapp/tasklist_own.html:10
#: taskapp/templates/taskapp/view.html:19
msgid "Description"
msgstr "Описание"
#: taskapp/templates/taskapp/add_edit_task.html:35
#: taskapp/templates/taskapp/tasklist.html:12
#: taskapp/templates/taskapp/tasklist_active.html:12
#: taskapp/templates/taskapp/tasklist_all.html:24
#: taskapp/templates/taskapp/tasklist_finish.html:12
#: taskapp/templates/taskapp/tasklist_own.html:11
msgid "The nature of the damage"
msgstr "Характер поломки"
#: taskapp/templates/taskapp/add_edit_task.html:43
#: taskapp/templates/taskapp/tasklist.html:14
#: taskapp/templates/taskapp/tasklist_active.html:14
#: taskapp/templates/taskapp/tasklist_all.html:26
#: taskapp/templates/taskapp/tasklist_finish.html:14
#: taskapp/templates/taskapp/tasklist_own.html:13
msgid "A priority"
msgstr "Приоритет"
#: taskapp/templates/taskapp/add_edit_task.html:51
#: taskapp/templates/taskapp/tasklist.html:13
#: taskapp/templates/taskapp/tasklist_active.html:13
#: taskapp/templates/taskapp/tasklist_all.html:25
#: taskapp/templates/taskapp/tasklist_finish.html:13
#: taskapp/templates/taskapp/tasklist_own.html:12
msgid "Condition"
msgstr "Состояние"
#: taskapp/templates/taskapp/add_edit_task.html:59
#: taskapp/templates/taskapp/view.html:30
msgid "Subscriber"
msgstr "Абонент"
#: taskapp/templates/taskapp/add_edit_task.html:75
msgid "Reality (the date by which you must complete the task)"
msgstr "Актуальность (дата, до которой нужно завершить задачу)"
#: taskapp/templates/taskapp/add_edit_task.html:91
msgid "Attached image"
msgstr "Прикреплённое изображение"
#: taskapp/templates/taskapp/add_edit_task.html:99
msgid "Save"
msgstr "Сохранить"
#: taskapp/templates/taskapp/add_edit_task.html:102
msgid "Reset"
msgstr "Сбросить"
#: taskapp/templates/taskapp/footer_btns.html:9
msgid "View all tasks"
msgstr "Просмотреть все задачи"
#: taskapp/templates/taskapp/tasklist.html:11
#: taskapp/templates/taskapp/tasklist_active.html:11
#: taskapp/templates/taskapp/tasklist_all.html:23
#: taskapp/templates/taskapp/tasklist_finish.html:11
msgid "Task author"
msgstr "Кто назначил"
#: taskapp/templates/taskapp/tasklist.html:15
#: taskapp/templates/taskapp/tasklist_active.html:15
#: taskapp/templates/taskapp/tasklist_all.html:27
#: taskapp/templates/taskapp/tasklist_finish.html:15
#: taskapp/templates/taskapp/tasklist_own.html:14
#: taskapp/templates/taskapp/view.html:27
msgid "Date of create"
msgstr "Дата создания"
#: taskapp/templates/taskapp/tasklist.html:16
#: taskapp/templates/taskapp/tasklist_active.html:16
#: taskapp/templates/taskapp/tasklist_all.html:28
#: taskapp/templates/taskapp/tasklist_finish.html:16
#: taskapp/templates/taskapp/tasklist_own.html:15
#: taskapp/templates/taskapp/view.html:37
msgid "Attachment"
msgstr "Приложение"
#: taskapp/templates/taskapp/tasklist.html:17
#: taskapp/templates/taskapp/tasklist_active.html:17
#: taskapp/templates/taskapp/tasklist_all.html:29
#: taskapp/templates/taskapp/tasklist_finish.html:17
#: taskapp/templates/taskapp/tasklist_own.html:16
msgid "Actions"
msgstr "Действия"
#: taskapp/templates/taskapp/tasklist.html:41
msgid "Begin"
msgstr "Начать"
#: taskapp/templates/taskapp/tasklist.html:44
#: taskapp/templates/taskapp/tasklist_active.html:42
msgid "Complete"
msgstr "Завершить"
#: taskapp/templates/taskapp/tasklist.html:56
#: taskapp/templates/taskapp/tasklist_active.html:54
#: taskapp/templates/taskapp/tasklist_all.html:67
#: taskapp/templates/taskapp/tasklist_finish.html:56
msgid "The list is empty"
msgstr "Список пуст"
#: taskapp/templates/taskapp/tasklist_all.html:8
msgid "All tasks"
msgstr "Все задачи"
#: taskapp/templates/taskapp/tasklist_all.html:14
msgid "Records of all the tasks in the system"
msgstr "Лог всех задач в системе"
#: taskapp/templates/taskapp/tasklist_all.html:59
#: taskapp/templates/taskapp/tasklist_own.html:45
msgid "Remind"
msgstr "Напомнить"
#: taskapp/templates/taskapp/tasklist_finish.html:48
#: taskapp/templates/taskapp/tasklist_own.html:50
msgid "Delete"
msgstr "Удалить"
#: taskapp/templates/taskapp/tasklist_own.html:58
msgid "All your tasks has been performed"
msgstr "Все ваши задачи выполнены"
#: taskapp/templates/taskapp/view.html:15
msgid "Task description"
msgstr "Описание задачи"
#: taskapp/templates/taskapp/view.html:20
msgid "Implementers"
msgstr "Исполнители"
#: taskapp/templates/taskapp/view.html:26
msgid "The task is valid until"
msgstr "Задача действительна до"
#: taskapp/templates/taskapp/view.html:28
#, fuzzy
#| msgid "Time left"
msgid "time left"
msgstr "Времени осталось"
#: taskapp/templates/taskapp/view.html:29
msgid "Task type"
msgstr "Тип задачи"
#: taskapp/views.py:84
msgid "You cannot delete task that assigned to you"
msgstr "Вы не можете удалять назначенные на вас задачи"
#: taskapp/views.py:148
msgid "No responsible employee for the users group"
msgstr "Нет ответственных за группу, в которой находится выбранный абонент"
#: taskapp/views.py:150
msgid "You must select the subscriber"
msgstr "Нужно выбрать абонента"
#: taskapp/views.py:152
msgid "Error in the form fields"
msgstr "Ошибка в полях формы"
#: taskapp/views.py:154
msgid "Employee has not yet signed up for notifications"
msgstr "Исполнитель ещё не подписался на оповещения"
msgid "Tasks to be performed"
msgstr "Задачи, которые необходимо выполнить"
msgid "New tasks"
msgstr "Новые задачи"
msgid "Active tasks"
msgstr "Активные задачи"
msgid "Completed tasks"
msgstr "Выполненные задачи"
msgid "Scheduled tasks me"
msgstr "Назначенные мной задачи"
msgid "All my tasks"
msgstr "Все мои задачи"

15
taskapp/models.py

@ -124,13 +124,14 @@ def task_handler(sender, instance, **kwargs):
) )
def task_delete(sender, instance, **kwargs):
ChangeLog.objects.create(
task=instance,
act_type='d',
who=instance.author
)
#def task_delete(sender, instance, **kwargs):
# ChangeLog.objects.create(
# task=instance,
# act_type='d',
# who=instance.author
# )
models.signals.post_save.connect(task_handler, sender=Task) models.signals.post_save.connect(task_handler, sender=Task)
models.signals.post_delete.connect(task_delete, sender=Task)
#models.signals.post_delete.connect(task_delete, sender=Task)

13
taskapp/views.py

@ -101,7 +101,7 @@ def view(request, task_id):
@only_admins @only_admins
def task_add_edit(request, task_id=0): def task_add_edit(request, task_id=0):
task_id = safe_int(task_id) task_id = safe_int(task_id)
uid = request.GET.get('uid')
uid = request.GET.get('uid', 0)
selected_abon = None selected_abon = None
frm = TaskFrm() frm = TaskFrm()
@ -119,11 +119,8 @@ def task_add_edit(request, task_id=0):
frm = TaskFrm(instance=tsk) frm = TaskFrm(instance=tsk)
selected_abon = tsk.abon selected_abon = tsk.abon
if uid:
selected_abon = get_object_or_404(Abon, username=str(uid))
if request.method == 'POST':
try: try:
if request.method == 'POST':
tsk.author = request.user tsk.author = request.user
frm = TaskFrm(request.POST, request.FILES, instance=tsk) frm = TaskFrm(request.POST, request.FILES, instance=tsk)
@ -150,8 +147,14 @@ def task_add_edit(request, task_id=0):
messages.error(request, _('You must select the subscriber')) messages.error(request, _('You must select the subscriber'))
else: else:
messages.error(request, _('Error in the form fields')) messages.error(request, _('Error in the form fields'))
elif uid:
selected_abon = Abon.objects.get(username=str(uid))
except TelegramBot.DoesNotExist: except TelegramBot.DoesNotExist:
messages.error(request, _('Employee has not yet signed up for notifications')) messages.error(request, _('Employee has not yet signed up for notifications'))
except Abon.DoesNotExist:
messages.warning(request, _("User '%s' does not exist") % str(uid))
except TaskException as e:
messages.error(request, e)
return render(request, 'taskapp/add_edit_task.html', { return render(request, 'taskapp/add_edit_task.html', {
'form': frm, 'form': frm,

Loading…
Cancel
Save