From 9daac6254971b5110546ec013fc85f87eb4e8b91 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Wed, 26 Jul 2017 02:23:16 +0300 Subject: [PATCH 1/3] =?UTF-8?q?=D0=9D=D0=B0=20=D1=81=D1=82=D0=B0=D0=B4?= =?UTF-8?q?=D0=B8=D0=B8=20=D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D0=B8..?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- abonapp/locale/ru/LC_MESSAGES/django.po | 30 +-- abonapp/models.py | 241 ++++++---------------- abonapp/templates/abonapp/buy_tariff.html | 2 +- abonapp/templates/abonapp/peoples.html | 26 +-- abonapp/templates/abonapp/service.html | 54 +++++ abonapp/templates/abonapp/services.html | 101 --------- abonapp/tests.py | 225 -------------------- abonapp/urls_abon.py | 2 - abonapp/views.py | 67 +----- bugs.txt | 3 + clientsideapp/views.py | 2 +- cron.py | 2 +- djing/utils/save_from_nodeny.py | 2 +- 13 files changed, 143 insertions(+), 614 deletions(-) create mode 100644 abonapp/templates/abonapp/service.html delete mode 100644 abonapp/templates/abonapp/services.html delete mode 100644 abonapp/tests.py diff --git a/abonapp/locale/ru/LC_MESSAGES/django.po b/abonapp/locale/ru/LC_MESSAGES/django.po index 5be7d30..8ee31a6 100644 --- a/abonapp/locale/ru/LC_MESSAGES/django.po +++ b/abonapp/locale/ru/LC_MESSAGES/django.po @@ -57,10 +57,6 @@ msgstr "Не хватает денег на счету" msgid "finish service perm" msgstr "Снятие со счёта средств" -#: abonapp/models.py:145 -msgid "activate service perm" -msgstr "Активация услуги абонента" - #: abonapp/models.py:162 msgid "Digital field" msgstr "Цифровое поле" @@ -94,10 +90,6 @@ msgstr "Может просматривать паспортные данные" msgid "Buy service default log" msgstr "Покупка тарифного плана через админку" -#: abonapp/models.py:303 -msgid "service overdue log" -msgstr "Услуга просрочена, отключаем, и подключаем новую" - #: abonapp/models.py:346 msgid "Ip address already exist" msgstr "Такой ip уже у кого-то есть" @@ -598,10 +590,6 @@ msgstr "Не найдены улицы для группы" msgid "Services of subscriber" msgstr "Купленные абонентом услуги (назначенные тарифные планы)" -#: abonapp/templates/abonapp/services.html:9 -msgid "Priority" -msgstr "Приоритет" - #: abonapp/templates/abonapp/services.html:12 msgid "Input speed" msgstr "Входящая скорость" @@ -614,18 +602,6 @@ msgstr "Исходящая скорость" msgid "Works until" msgstr "Действует до" -#: abonapp/templates/abonapp/services.html:15 -msgid "Do" -msgstr "Действия" - -#: abonapp/templates/abonapp/services.html:52 -msgid "Priority up" -msgstr "Повысить приоритет" - -#: abonapp/templates/abonapp/services.html:58 -msgid "Priority down" -msgstr "Понизить приоритет" - #: abonapp/templates/abonapp/services.html:64 msgid "Delete service" msgstr "Удалить услугу" @@ -902,3 +878,9 @@ msgstr "Звонки не найдены" msgid "Dialing" msgstr "Звонки" + +msgid "That service already activated" +msgstr "Эта услуга уже подключена" + +msgid "Service already activated" +msgstr "Услуга уже подключена" diff --git a/abonapp/models.py b/abonapp/models.py index 3e0fb45..f291155 100644 --- a/abonapp/models.py +++ b/abonapp/models.py @@ -41,107 +41,42 @@ class AbonLog(models.Model): class AbonTariff(models.Model): - abon = models.ForeignKey('Abon') + + def __init__(self, deadline=None, *args, **kwargs): + super(AbonTariff, self).__init__(*args, **kwargs) + calc_obj = self.tariff.get_calc_type()(self) + self.time_start = timezone.now() + if deadline is None: + self.deadline = calc_obj.calc_deadline() + else: + self.deadline = deadline + tariff = models.ForeignKey(Tariff, related_name='linkto_tariff') - tariff_priority = models.PositiveSmallIntegerField(default=0) - # время начала действия, остальные что не начали действие - NULL + # время начала действия услуги time_start = models.DateTimeField(null=True, blank=True, default=None) # время завершения услуги deadline = models.DateTimeField(null=True, blank=True, default=None) - def priority_up(self): - # ищем услугу с большим приоритетом(число приоритета меньше) - target_abtar = AbonTariff.objects.filter( - abon=self.abon, - tariff_priority__lt=self.tariff_priority - ).order_by('-tariff_priority')[:1] - if target_abtar.count() > 0: - target_abtar = target_abtar[0] - else: - return - - # Ищем текущий тариф абонента - active_abtar = AbonTariff.objects.filter( - abon=self.abon - )[:1] - if active_abtar.count() > 0: - active_abtar = active_abtar[0] - else: - return - - # Если услуга с которой хотим поменяться приоритетом является текущей то нельзя меняться - if active_abtar == target_abtar: - return - - # Swap приоритетов у текущего и найденного с меньшим tariff_priority (большим приоритетом) - tmp_prior = target_abtar.tariff_priority - target_abtar.tariff_priority = self.tariff_priority - target_abtar.save(update_fields=['tariff_priority']) - self.tariff_priority = tmp_prior - self.save(update_fields=['tariff_priority']) - - def priority_down(self): - # ищем услугу с меньшим приоритетом - target_abtar = AbonTariff.objects.filter( - abon=self.abon, - tariff_priority__gt=self.tariff_priority - )[:1] - if target_abtar.count() > 0: - target_abtar = target_abtar[0] - else: - # меньше нет, это самая последняя услуга - return - - # Swap приоритетов у текущего и найденного с большим tariff_priority (меньшим приоритетом) - tmp_pr = self.tariff_priority - self.tariff_priority = target_abtar.tariff_priority - target_abtar.tariff_priority = tmp_pr - target_abtar.save(update_fields=['tariff_priority']) - self.save(update_fields=['tariff_priority']) - - # Считает текущую стоимость услуг согласно выбранной для тарифа логики оплаты (см. в документации) def calc_amount_service(self): amount = self.tariff.amount return round(amount, 2) - # Активируем тариф - def activate(self, current_user, deadline=None): - calc_obj = self.tariff.get_calc_type()(self) - amnt = self.tariff.amount - # если не хватает денег - if self.abon.ballance < amnt: - raise LogicError(_('not enough money')) - # считаем дату активации услуги - self.time_start = timezone.now() - # считаем дату завершения услуги - if deadline is None: - self.deadline = calc_obj.calc_deadline() - else: - self.deadline = deadline - # снимаем деньги за услугу - self.abon.make_pay(current_user, amnt) - self.save() - # Используется-ли услуга сейчас, если время старта есть то он активирован def is_started(self): - return True if self.time_start is not None else False + return False if self.time_start is None else True def __str__(self): - return "%d: '%s' - '%s'" % ( - self.tariff_priority, + return "'%s' - '%s'" % ( self.tariff.title, self.abon.get_short_name() ) class Meta: - ordering = ('tariff_priority',) db_table = 'abonent_tariff' - unique_together = (('abon', 'tariff', 'tariff_priority'),) permissions = ( - ('can_complete_service', _('finish service perm')), - ('can_activate_service', _('activate service perm')) + ('can_complete_service', _('finish service perm')) ) @@ -211,7 +146,7 @@ class Opt82(models.Model): class Abon(UserProfile): - current_tariffs = models.ManyToManyField(Tariff, through=AbonTariff) + 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) ballance = models.FloatField(default=0.0) ip_address = MyGenericIPAddressField(blank=True, null=True) @@ -221,20 +156,9 @@ class Abon(UserProfile): extra_fields = models.ManyToManyField(ExtraFieldsModel, blank=True) opt82 = models.ForeignKey(Opt82, null=True, blank=True, on_delete=models.SET_NULL) - _act_tar_cache = None - - # возвращает текущий тариф для абонента - def active_tariff(self, use_cache=True): - if self._act_tar_cache and use_cache: - return self._act_tar_cache - - ats = AbonTariff.objects.filter(abon=self).exclude(time_start=None) - - if ats.count() > 0: - self._act_tar_cache = ats[0].tariff - return ats[0].tariff - else: - self._act_tar_cache = None + # возвращает связь с текущим тарифом для абонента + def active_tariff(self): + return self.current_tariff class Meta: db_table = 'abonent' @@ -262,23 +186,28 @@ class Abon(UserProfile): def pick_tariff(self, tariff, author, comment=None, deadline=None): assert isinstance(tariff, Tariff) - # выбераем связь ТарифАбонент с самым низким приоритетом - abtrf = AbonTariff.objects.filter(abon=self).order_by('-tariff_priority')[:1] - abtrf = abtrf[0] if abtrf.count() > 0 else None + amount = round(tariff.amount, 2) - # создаём новую связь с приоритетом ещё ниже - new_abtar = AbonTariff( - abon=self, - tariff=tariff, - tariff_priority=abtrf.tariff_priority + 1 if abtrf else -1 - ) + if self.current_tariff is not None: + if self.current_tariff.tariff == tariff: + # Эта услуга уже подключена + raise LogicError(_('That service already activated')) + else: + # Не надо молча заменять услугу если какая-то уже есть + raise LogicError(_('Service already activated')) - # Если это первая услуга в списке (фильтр по приоритету ничего не вернул) - if not abtrf: - # значит пробуем её активировать - new_abtar.activate(author, deadline) - else: - new_abtar.save() + # если не хватает денег + if self.ballance < amount: + raise LogicError(_('not enough money')) + + new_abtar = AbonTariff(deadline=deadline, tariff=tariff) + new_abtar.save() + self.current_tariff = new_abtar + + # снимаем деньги за услугу + self.ballance -= amount + + self.save() # Запись об этом в лог AbonLog.objects.create( @@ -287,43 +216,23 @@ class Abon(UserProfile): comment=comment or _('Buy service default log') ) - # Пробует подключить новую услугу если пришло время - def activate_next_tariff(self, author): - ats = AbonTariff.objects.filter(abon=self).order_by('tariff_priority') - + # Производим расчёт услуги абонента, т.е. завершаем если пришло время + def bill_service(self, author): + abon_tariff = self.active_tariff() nw = timezone.now() - - for at in ats: - # услуга не активна, продолжаем - if at.deadline is None: - continue - # если услуга просрочена - if nw > at.deadline: - print(_('service overdue log')) - # выберем следующую по приоритету - # next_tarifs = AbonTariff.objects.filter(tariff_priority__gt = self.tariff_priority, abon=self.abon) - next_tarifs = [tr for tr in ats if tr.tariff_priority > at.tariff_priority][:2] - #next_tarifs = filter(lambda tr: tr.tariff_priority > at.tariff_priority, ats)[:2] - - # и если что-нибудь из списка следующих услуг вернулось - то активируем - if len(next_tarifs) > 0: - next_tarifs[0].activate(author) - - # удаляем запись о текущей услугу. - at.delete() - return + # если услуга просрочена + if nw > abon_tariff.deadline: + print("Service %s for user %s is overdued, end service" % (abon_tariff.tariff, self)) + abon_tariff.delete() # есть-ли доступ у абонента к услуге, смотрим в tariff_app.custom_tariffs..manage_access() def is_access(self): - ats = AbonTariff.objects.filter(abon=self).exclude(time_start=None) - if not ats or ats.count() < 1: - return False - trf = ats[0].tariff - ct = trf.get_calc_type()(ats[0]) - if ct.manage_access(self): - return True - else: + abon_tariff = self.active_tariff() + if abon_tariff is None: return False + trf = abon_tariff.tariff + ct = trf.get_calc_type()(abon_tariff) + return ct.manage_access(self) # создаём абонента из структуры агента def build_agent_struct(self): @@ -331,16 +240,17 @@ class Abon(UserProfile): user_ip = ip2int(self.ip_address) else: return - inst_tariff = self.active_tariff() - if inst_tariff: - agent_trf = TariffStruct(inst_tariff.id, inst_tariff.speedIn, inst_tariff.speedOut) - else: + abon_tariff = self.active_tariff() + if abon_tariff is None: agent_trf = TariffStruct() + else: + trf = abon_tariff.tariff + agent_trf = TariffStruct(trf.id, trf.speedIn, trf.speedOut) return AbonStruct(self.pk, user_ip, agent_trf, bool(self.is_active)) def save(self, *args, **kwargs): # проверяем не-ли у кого такого-же ip - if Abon.objects.filter(ip_address=self.ip_address).exclude(pk=self.pk).count() > 0: + if self.ip_address is not None and Abon.objects.filter(ip_address=self.ip_address).exclude(pk=self.pk).count() > 0: self.is_bad_ip = True raise LogicError(_('Ip address already exist')) super(Abon, self).save(*args, **kwargs) @@ -467,40 +377,5 @@ def abon_del_signal(sender, instance, **kwargs): return True -def abontariff_post_save(sender, instance, **kwargs): - # Тут или подключение абону услуги, или изменение приоритета - if not kwargs['created']: - # если изменение приоритета то не говорим об этом NAS'у - return - if instance.abon.ip_address is None: - return - try: - agent_abon = instance.abon.build_agent_struct() - if agent_abon is None: - return True - tm = Transmitter() - tm.update_user(agent_abon) - except (NasFailedResult, NasNetworkError): - return True - - -def abontariff_del_signal(sender, instance, **kwargs): - if not instance.is_started(): - # если удаляем не активную услугу то говорить об этом NAS'у не обязательно - return - if instance.abon.ip_address is None: - # если у абонента нет ip то и создавать правило не на кого - return - try: - agent_abon = instance.abon.build_agent_struct() - tm = Transmitter() - tm.pause_user(agent_abon) - except (NasFailedResult, NasNetworkError): - return True - - -models.signals.post_save.connect(abon_post_save, sender=Abon) -models.signals.post_delete.connect(abon_del_signal, sender=Abon) - -models.signals.post_save.connect(abontariff_post_save, sender=AbonTariff) -models.signals.post_delete.connect(abontariff_del_signal, sender=AbonTariff) +#models.signals.post_save.connect(abon_post_save, sender=Abon) +#models.signals.post_delete.connect(abon_del_signal, sender=Abon) diff --git a/abonapp/templates/abonapp/buy_tariff.html b/abonapp/templates/abonapp/buy_tariff.html index ab4aad9..3b968e7 100644 --- a/abonapp/templates/abonapp/buy_tariff.html +++ b/abonapp/templates/abonapp/buy_tariff.html @@ -22,7 +22,7 @@
{% csrf_token %}
- +
diff --git a/abonapp/templates/abonapp/peoples.html b/abonapp/templates/abonapp/peoples.html index ad334f7..079a32e 100644 --- a/abonapp/templates/abonapp/peoples.html +++ b/abonapp/templates/abonapp/peoples.html @@ -50,7 +50,7 @@ {% if order_by == 'house' %}{% endif %} {% trans 'Telephone' %} - + {% trans 'Service' %} {% trans 'Ballance' %} @@ -83,16 +83,16 @@ {{ human.street|default:_('Not assigned') }} {{ human.house|default:_('Not assigned') }} {{ human.telephone }} - + + {% if human.active_tariff %} + {% if perms.tariff_app.change_tariff %} + {{ human.active_tariff.tariff.title }} + {% else %} + {{ human.active_tariff.tariff.title }} + {% endif %} + {% else %}——— + {% endif %} + {{ human.ballance }} {% if perms.abonapp.delete_abon %} @@ -104,7 +104,7 @@ {% empty %} - + {% trans 'Subscribers not found' %}. {% if perms.abonapp.add_abon %} {% trans 'Add abon' %} @@ -115,7 +115,7 @@ - + {% if perms.abonapp.add_abon %} {% trans 'Add abon' %} diff --git a/abonapp/templates/abonapp/service.html b/abonapp/templates/abonapp/service.html new file mode 100644 index 0000000..17f81c0 --- /dev/null +++ b/abonapp/templates/abonapp/service.html @@ -0,0 +1,54 @@ +{% extends request.is_ajax|yesno:'nullcont.htm,abonapp/ext.htm' %} +{% load i18n %} +{% block content %} + +
+
+ +
+
+

{% trans 'Services of subscriber' %}

+
+
+ {% if abon_tariff %} +

+ {% trans 'Service' %}: + {% if perms.tariff_app.change_tariff %} + + {{ abon_tariff.tariff.title }} + + {% else %} + {{ abon_tariff.tariff.title }} + {% endif %} +

+ {% trans 'Sum' %}: {{ abon_tariff.tarif.amount }} руб. +

{% trans 'Input speed' %}: {{ abon_tariff.tariff.speedIn }}

+

{% trans 'Output speed' %}: {{ abon_tariff.tariff.speedOut }}

+

{% trans 'Works until' %}: {{ abon_tariff.deadline|date:"d E Y, l" }}

+

{{ abon_tariff.tarif.descr }}

+ {% else %} + No service, + {% trans 'Buy service' %} + + {% endif %} + +
+
+
+
+
+
+

Услуги для заказа

+
+
+
+
+
+
+
+ + + + + +{% endblock %} diff --git a/abonapp/templates/abonapp/services.html b/abonapp/templates/abonapp/services.html deleted file mode 100644 index 47b67a9..0000000 --- a/abonapp/templates/abonapp/services.html +++ /dev/null @@ -1,101 +0,0 @@ -{% extends request.is_ajax|yesno:'nullcont.htm,abonapp/ext.htm' %} -{% load i18n %} -{% block content %} - - {% trans 'Services of subscriber' %} - - - - - - - - - - - - - - - {% for trf in abon_tarifs %} - - - - - - - - {% if trf.id != active_abontariff_id %} - - {% else %} - - {% endif %} - - {% empty %} - - - - {% endfor %} - - {% if perms.abonapp.can_buy_tariff %} - - - - - - {% endif %} -
{% trans 'Priority' %}{% trans 'Service' %}{% trans 'Sum' %}{% trans 'Input speed' %}{% trans 'Output speed' %}{% trans 'Works until' %}{% trans 'Do' %}
{{ trf.tariff_priority }} - - {% if perms.tariff_app.change_tariff %} - - {{ trf.tariff.title }} - - {% else %} - {{ trf.tariff.title }} - {% endif %} - - {{ trf.tariff.amount }}{{ trf.tariff.speedIn }}{{ trf.tariff.speedOut }}{{ trf.deadline|date:"d E Y, l" }} - - {% if perms.abonapp.can_activate_service %} - {% if not active_abontariff_id %} - - - - {% endif %} - {% endif %} - - - - - - - - - - - - {% if perms.abonapp.delete_abontariff %} - - - - {% endif %} - - - {% trans 'Finish service' %} - -
{% trans 'Services of subscribers not found' %}. - {% if perms.abonapp.can_buy_tariff %} - {% trans 'Buy' %} - {% endif %} -
- - {% trans 'Buy service' %} - -
- - -{% endblock %} \ No newline at end of file diff --git a/abonapp/tests.py b/abonapp/tests.py deleted file mode 100644 index b66baf8..0000000 --- a/abonapp/tests.py +++ /dev/null @@ -1,225 +0,0 @@ -from django.shortcuts import resolve_url -from django.test import TestCase -from django.test.client import Client -from agent import NasNetworkError -from .models import AbonTariff, Abon, AbonGroup, AbonRawPassword -from tariff_app.models import Tariff -from mydefs import LogicError - - -class AbonTestCase(TestCase): - def setUp(self): - try: - Tariff.objects.create( - title='test_tariff', - descr='taroff descr', - speedIn=1.2, - speedOut=3.0, - amount=3 - ) - abon = Abon() - abon.username = '1234567' - abon.fio = 'mainuser' - abon.telephone = '+79788328884' - abon.set_password('ps') - abon.is_superuser = True - abon.save() - abon_group = AbonGroup.objects.create(title='abon_group') - abon_group.profiles.add(abon) - except NasNetworkError: - pass - - # проверка на пополнение счёта - def test_add_ballance(self): - try: - abon = Abon.objects.get(username='1234567') - ballance = abon.ballance - abon.add_ballance(abon, 13, 'test pay') - abon.save(update_fields=['ballance']) - self.assertEqual(abon.ballance, ballance+13) - ballance = abon.ballance - abon.add_ballance(abon, 5.34, 'test float pay') - abon.save(update_fields=['ballance']) - self.assertEqual(abon.ballance, ballance+5.34) - except NasNetworkError: - pass - - # пробуем выбрать услугу - def test_pick_tariff(self): - try: - tariff = Tariff.objects.get(title='test_tariff') - abon = Abon.objects.get(username='1234567') - try: - abon.pick_tariff(tariff, abon) - # нет денег, должно всплыть исключение и сюда дойти мы не должны - self.assertFalse(True) - except LogicError: - pass - act_tar = abon.active_tariff() - # если недостаточно денег на счету - assert abon.ballance <= tariff.amount - # У абонента на счету 0, не должна быть куплена услуга - self.assertEqual(act_tar, None) - # Раз услуги нет то и доступа быть не должно - self.assertTrue(not abon.is_access()) - - # с деньгами - abon.add_ballance(abon, 7.34, 'add pay for test pick tariff') - abon.pick_tariff(tariff, abon) - act_tar = abon.active_tariff() - # должны получить указанную услугу - self.assertEqual(act_tar, tariff) - # и получить доступ - self.assertTrue(abon.is_access()) - except NasNetworkError: - pass - - # тестим очередь услуг - def test_services_queue(self): - abon = Abon.objects.get(username='1234567') - tariff = Tariff.objects.get(title='test_tariff') - abon.add_ballance(abon, 9, 'add pay for test services queue') - abon.save() - abon.pick_tariff(tariff, abon) - abon.pick_tariff(tariff, abon) - abon.pick_tariff(tariff, abon) - # снять деньги должно было только за первый выбор, остальные стают в очередь услуг - self.assertEqual(abon.ballance, 6) - - c = Client() - # login - 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) - self.assertEqual(resp.status_code, 200) - resp = c.post(url, data={ - 'finish_confirm': 'yes' - }) - print('RESP:', resp) - # при успешной остановке услуги идёт редирект на др страницу - self.assertEqual(resp.status_code, 302) - # текущей услуги быть не должно - act_tar = abon.active_tariff() - self.assertIsNone(act_tar) - # не активных услуг останется 2 - noact_count = AbonTariff.objects.filter(abon=abon).filter(time_start=None).count() - self.assertEqual(noact_count, 2) - - # проверяем платёжку alltime - def test_allpay(self): - from hashlib import md5 - from djing.settings import pay_SECRET, pay_SERV_ID - import xmltodict - - def sig(act, pay_account, pay_id): - md = md5() - s = '_'.join((str(act), str(pay_account), pay_SERV_ID, str(pay_id), pay_SECRET)) - md.update(bytes(s, 'utf-8')) - return md.hexdigest() - - c = Client() - url = resolve_url('abonapp:terminal_pay') - r = c.get(url, { - 'ACT': 1, 'PAY_ACCOUNT': '1234567', - 'SERVICE_ID': pay_SERV_ID, - 'PAY_ID': 3561234, - 'TRADE_POINT': 377, - 'SIGN': sig(1, 1234567, 3561234) - }) - xobj = xmltodict.parse(r.content) - self.assertEqual(int(xobj['pay-response']['status_code']), 21) - r = c.get(url, { - 'ACT': 4, 'PAY_ACCOUNT': '1234567', - 'SERVICE_ID': pay_SERV_ID, - 'PAY_ID': 3561234, - 'PAY_AMOUNT': 1.0, - 'TRADE_POINT': 377, - 'SIGN': sig(4, 1234567, 3561234) - }) - xobj = xmltodict.parse(r.content) - self.assertEqual(int(xobj['pay-response']['status_code']), 22) - r = c.get(url, { - 'ACT': 4, 'PAY_ACCOUNT': '1234567', - 'SERVICE_ID': pay_SERV_ID, - 'PAY_ID': 3561234, - 'PAY_AMOUNT': 1.0, - 'TRADE_POINT': 377, - 'SIGN': sig(4, 1234567, 3561234) - }) - xobj = xmltodict.parse(r.content) - self.assertEqual(int(xobj['pay-response']['status_code']), -100) - r = c.get(url, { - 'ACT': 7, 'PAY_ACCOUNT': '1234567', - 'SERVICE_ID': pay_SERV_ID, - 'PAY_ID': 3561234, - 'PAY_AMOUNT': 1.0, - 'TRADE_POINT': 377, - 'SIGN': sig(7, 1234567, 3561234) - }) - xobj = xmltodict.parse(r.content) - self.assertEqual(int(xobj['pay-response']['status_code']), 11) - abon = Abon.objects.get(username='1234567') - self.assertEqual(abon.ballance, 1) - - # пробуем добавить группу абонентов - def test_add_abongroup(self): - abon = Abon.objects.get(username='1234567') - ag = AbonGroup.objects.create(title='%&34%$&*(') - ag.profiles.add(abon) - - # пробуем добавить абонента - def test_add_abon(self): - c = Client() - c.login(username='1234567', password='ps') - url = resolve_url('abonapp:add_abon', gid=1) - r = c.get(url) - # поглядим на страницу добавления абонента - self.assertEqual(r.status_code, 200) - r = c.post(url, { - 'username': '123', - 'password': 'ps', - 'fio': 'Abon Fio', - 'telephone': '+79783753914', - 'is_active': True - }) - self.assertEqual(r.status_code, 302) - r = c.get(resolve_url('abonapp:add_abon', gid=324)) - self.assertEqual(r.status_code, 404) - try: - abn = Abon.objects.get(username='123') - self.assertIsNotNone(abn) - psw = AbonRawPassword.objects.get(account=abn, passw_text='ps') - self.assertIsNotNone(psw) - except Abon.DoesNotExist: - # абонент должен был создаться - self.assertTrue(False) - except AbonRawPassword.DoesNotExist: - # должен быть пароль абонента простым текстом - 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): - def setUp(self): - abon = Abon.objects.create( - username='1234567', - telephone='+79788328884' - ) - tariff = Tariff.objects.create( - title='test_tariff', - descr='taroff descr', - speedIn=1.2, - speedOut=3.0, - amount=3 - ) - AbonTariff.objects.create( - abon=abon, - tariff=tariff - ) diff --git a/abonapp/urls_abon.py b/abonapp/urls_abon.py index 1de99da..9636922 100644 --- a/abonapp/urls_abon.py +++ b/abonapp/urls_abon.py @@ -15,10 +15,8 @@ urlpatterns = [ url(r'^(?P\d+)/addinvoice$', views.add_invoice, name='add_invoice'), url(r'^(?P\d+)/pick$', views.pick_tariff, name='pick_tariff'), - url(r'^(?P\d+)/chpriority$', views.chpriority, name='chpriority_tariff'), url(r'^(?P\d+)/passport_view$', views.passport_view, name='passport_view'), url(r'^(?P\d+)/complete_service(?P\d+)$', views.complete_service, name='compl_srv'), - url(r'^(?P\d+)/activate_service(?P\d+)$', views.activate_service, name='activate_service'), url(r'^(?P\d+)/opt82$', views.opt82, name='opt82'), url(r'^(?P\d+)/chart$', views.charts, name='charts'), url(r'^(?P\d+)/dials$', views.dials, name='dials'), diff --git a/abonapp/views.py b/abonapp/views.py index db135c9..5fd3f9b 100644 --- a/abonapp/views.py +++ b/abonapp/views.py @@ -245,14 +245,10 @@ def pay_history(request, gid, uid): @mydefs.only_admins def abon_services(request, gid, uid): abon = get_object_or_404(models.Abon, pk=uid) - abon_tarifs = models.AbonTariff.objects.filter(abon=uid) - active_abontariff = abon_tarifs.exclude(time_start=None) - - return render(request, 'abonapp/services.html', { + return render(request, 'abonapp/service.html', { 'abon': abon, - 'abon_tarifs': abon_tarifs, - 'active_abontariff_id': active_abontariff[0].id if active_abontariff.count() > 0 else None, + 'abon_tariff': abon.current_tariff, 'abon_group': abon.group }) @@ -434,28 +430,6 @@ def pick_tariff(request, gid, uid): }) -@login_required -@mydefs.only_admins -def chpriority(request, gid, uid): - t = request.GET.get('t') - act = request.GET.get('a') - - current_abon_tariff = get_object_or_404(models.AbonTariff, pk=t) - - try: - if act == 'up': - current_abon_tariff.priority_up() - elif act == 'down': - current_abon_tariff.priority_down() - except (NasFailedResult, NasNetworkError) as e: - messages.error(request, e) - except mydefs.MultipleException as errs: - for err in errs.err_list: - messages.add_message(request, messages.constants.ERROR, err) - - return redirect('abonapp:abon_home', gid=gid, uid=uid) - - @login_required @permission_required('abonapp.can_complete_service') def complete_service(request, gid, uid, srvid): @@ -515,38 +489,6 @@ def complete_service(request, gid, uid, srvid): }) -@login_required -@permission_required('abonapp.can_activate_service') -def activate_service(request, gid, uid, srvid): - abtar = get_object_or_404(models.AbonTariff, pk=srvid) - amount = abtar.calc_amount_service() - - try: - if request.method == 'POST': - if request.POST.get('finish_confirm') != 'yes': - return HttpResponse(_('Not confirmed')) - - abtar.activate(request.user) - messages.success(request, _('Service has been activated successfully')) - return redirect('abonapp:abon_services', gid, uid) - - except (NasFailedResult, mydefs.LogicError) 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) - calc_obj = abtar.tariff.get_calc_type()(abtar) - return render(request, 'abonapp/activate_service.html', { - 'abon': abtar.abon, - 'abon_group': abtar.abon.group, - 'abtar': abtar, - 'amount': amount, - 'diff': abtar.abon.ballance - amount, - 'deadline': calc_obj.calc_deadline() - }) - @login_required @permission_required('abonapp.delete_abontariff') @@ -743,7 +685,8 @@ def charts(request, gid, uid): abontariff = abon.active_tariff() if abontariff is not None: - high = abontariff.speedIn + abontariff.speedOut + trf = abontariff.tariff + high = trf.speedIn + trf.speedOut if high > 100: high = 100 @@ -888,7 +831,7 @@ def dials(request, gid, uid): def abons(request): ablist = [{ 'id': abn.pk, - 'tarif_id': abn.active_tariff().pk if abn.active_tariff() else 0, + '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()] diff --git a/bugs.txt b/bugs.txt index fa0bb2e..ba9cf41 100644 --- a/bugs.txt +++ b/bugs.txt @@ -8,3 +8,6 @@ - Не надо коннектиться к микротику когда не собираемся ничего изменять. А то при сохранении залогинились и вышли без действий - Не удаляет просроченные услуги если не пингуется NAS - Надо отменить учёт временной зоны +!!! Обязательно проверить как отрабатывает на NAS удаление и изменение AbonTariff +!!! Удалить всё что связано с активацией услуги +!!! Убрать досрочное завершение услуги diff --git a/clientsideapp/views.py b/clientsideapp/views.py index fb3d785..b40f628 100644 --- a/clientsideapp/views.py +++ b/clientsideapp/views.py @@ -54,7 +54,7 @@ def buy_service(request, srv_id): else: return render_to_text('clientsideapp/modal_service_buy.html', { 'service': service, - 'current_service': current_service + 'current_service': current_service.tariff if current_service is not None else None }, request=request) except LogicError as e: messages.error(request, e) diff --git a/cron.py b/cron.py index e42d2d8..1369392 100755 --- a/cron.py +++ b/cron.py @@ -16,7 +16,7 @@ def main(): for user in users: try: # бдим за услугами абонента: просроченные отключить, заказанные подключить - user.activate_next_tariff(user) + user.bill_service(user) # если нет ip то и нет смысла лезть в NAS if user.ip_address is None: diff --git a/djing/utils/save_from_nodeny.py b/djing/utils/save_from_nodeny.py index ab5cc4b..c8dfc76 100755 --- a/djing/utils/save_from_nodeny.py +++ b/djing/utils/save_from_nodeny.py @@ -102,7 +102,7 @@ class DumpAbon(object): self.passw = raw_passw srv = obj.active_tariff() if srv is not None: - self.service = DumpService.build_from_db(srv) + self.service = DumpService.build_from_db(srv.tariff) else: self.service = None if obj.opt82 is not None and obj.opt82.mac is not None and obj.opt82.port is not None: From 3bc35540a070bd988e449685b5328b7c42ae49c7 Mon Sep 17 00:00:00 2001 From: bashmak Date: Mon, 14 Aug 2017 13:04:58 +0300 Subject: [PATCH 2/3] =?UTF-8?q?FIXBUG:=20=D0=BE=D0=BF=D0=BE=D0=B2=D0=B5?= =?UTF-8?q?=D1=89=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BE=20=D0=B2=D1=8B=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D0=B5=D0=BD=D0=B8=D0=B8=20=D0=B8=D0=BB=D0=B8=20?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D0=B2=D0=B0=D0=BB=D0=B5=D0=BD=D0=BD=D0=BE?= =?UTF-8?q?=D0=BC=20=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B8=20=D0=B4?= =?UTF-8?q?=D1=83=D0=B1=D0=BB=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BB=D0=BE?= =?UTF-8?q?=D1=81=D1=8C=20=D0=B0=D0=B2=D1=82=D0=BE=D1=80=D1=83=20=D1=81?= =?UTF-8?q?=D1=82=D0=BE=D0=BB=D1=8C=D0=BA=D0=BE=20=D1=80=D0=B0=D0=B7=20?= =?UTF-8?q?=D1=81=D0=BA=D0=BE=D0=BB=D1=8C=D0=BA=D0=BE=20=D0=B1=D1=8B=D0=BB?= =?UTF-8?q?=D0=BE=20=D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5?= =?UTF-8?q?=D0=BB=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- taskapp/handle.py | 73 ++++++++++++++++++++++++++--------------------- taskapp/handle.sh | 2 +- taskapp/models.py | 18 ++++-------- taskapp/views.py | 8 ++++++ 4 files changed, 55 insertions(+), 46 deletions(-) diff --git a/taskapp/handle.py b/taskapp/handle.py index be59da7..e31303f 100644 --- a/taskapp/handle.py +++ b/taskapp/handle.py @@ -2,41 +2,50 @@ from django.utils.translation import ugettext as _ from chatbot.telebot import send_notify from chatbot.models import ChatException +from mydefs import MultipleException class TaskException(Exception): pass -def handle(task, author, recipient, abon_group): - try: - dst_account = recipient - text = _('Task') - # Если сигнал самому себе то молчим - if author == recipient: - return - # Если задача 'На выполнении' то молчим - if task.state == 'C': - return - # Если задача завершена - elif task.state == 'F': - text = _('Task completed') - # Меняем цель назначения на автора, т.к. при завершении - # идёт оповещение автору о выполнении - dst_account = author - if task.abon is not None: - fulltext="%s:\n%s\n" % (text, task.abon.get_full_name()) - else: - fulltext="%s\n" % text - fulltext += _('locality %s.\n') % abon_group.title - if task.abon: - 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 += _('Task type - %s.') % task.get_mode_display() + '\n' - fulltext += task.descr if task.descr else '' - send_notify(fulltext, dst_account) - except ChatException as e: - raise TaskException(e) +def handle(task, author, recipients, abon_group): + errors = [] + for recipient in recipients: + try: + dst_account = recipient + text = _('Task') + # Если сигнал самому себе то молчим + if author == recipient: + return + # Если задача завершена или провалена + elif task.state == 'F' or task.state == 'C': + text = _('Task completed') + if task.abon is not None: + fulltext = "%s:\n%s\n" % (text, task.abon.get_full_name()) + else: + fulltext = "%s\n" % text + fulltext += _('locality %s.\n') % abon_group.title + if task.abon: + 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 += _('Task type - %s.') % task.get_mode_display() + '\n' + fulltext += task.descr if task.descr else '' + + print('task.state:', task.state) + + if task.state == 'F' or task.state == 'C': + # Если задача завершена или провалена то отправляем одно оповещение автору + try: + send_notify(fulltext, author) + except ChatException as e: + raise TaskException(e) + else: + send_notify(fulltext, dst_account) + except ChatException as e: + errors.append(e) + if len(errors) > 0: + raise MultipleException(errors) diff --git a/taskapp/handle.sh b/taskapp/handle.sh index e08b533..8ac380f 100755 --- a/taskapp/handle.sh +++ b/taskapp/handle.sh @@ -44,6 +44,6 @@ fi FULLTEXT="$text: $ABON_FIO. $ABON_ADDR $ABON_TEL. $ABON_GRP. $FAIL_MODE. $DESCR" -echo "TO $RECIPIENT_TEL: $FULLTEXT" >> /tmp/task_sms.log +echo "TO $RECIPIENT_TEL: $FULLTEXT" /usr/bin/gammu-smsd-inject EMS $RECIPIENT_TEL -text "$FULLTEXT" -unicode diff --git a/taskapp/models.py b/taskapp/models.py index f4db733..37e30f6 100644 --- a/taskapp/models.py +++ b/taskapp/models.py @@ -6,8 +6,7 @@ from django.conf import settings from django.utils import timezone from django.utils.translation import ugettext as _ from abonapp.models import Abon -from .handle import handle as task_handle, TaskException -from mydefs import MultipleException +from .handle import handle as task_handle TASK_PRIORITIES = ( @@ -121,17 +120,10 @@ def task_handler(sender, instance, **kwargs): act_type='e', who=instance.author ) - errors = [] - for recipient in instance.recipients.all(): - try: - task_handle( - instance, instance.author, - recipient, group - ) - except TaskException as e: - errors.append(e) - if len(errors) > 0: - raise MultipleException(errors) + task_handle( + instance, instance.author, + instance.recipients.all(), group + ) #def task_delete(sender, instance, **kwargs): diff --git a/taskapp/views.py b/taskapp/views.py index c4e1966..d8ec471 100644 --- a/taskapp/views.py +++ b/taskapp/views.py @@ -6,6 +6,8 @@ from django.contrib import messages from abonapp.models import Abon from django.utils.translation import ugettext as _ from datetime import date + +from .handle import TaskException from .models import Task from mydefs import pag_mn, only_admins, safe_int, MultipleException, RuTimedelta from .forms import TaskFrm @@ -152,6 +154,8 @@ def task_add_edit(request, task_id=0): except MultipleException as errs: for err in errs.err_list: messages.add_message(request, messages.constants.ERROR, err) + except TaskException as e: + messages.error(request, e) return render(request, 'taskapp/add_edit_task.html', { 'form': frm, @@ -169,6 +173,8 @@ def task_finish(request, task_id): except MultipleException as errs: for err in errs.err_list: messages.add_message(request, messages.constants.ERROR, err) + except TaskException as e: + messages.error(request, e) return redirect('taskapp:home') @@ -189,4 +195,6 @@ def remind(request, task_id): except MultipleException as errs: for err in errs.err_list: messages.add_message(request, messages.constants.ERROR, err) + except TaskException as e: + messages.error(request, e) return redirect('taskapp:home') From 9e1d0810de05c59abeaa71c68d132cb2a24c5dc5 Mon Sep 17 00:00:00 2001 From: bashmak Date: Mon, 14 Aug 2017 14:12:26 +0300 Subject: [PATCH 3/3] fixbug --- abonapp/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/abonapp/models.py b/abonapp/models.py index f291155..ce857b1 100644 --- a/abonapp/models.py +++ b/abonapp/models.py @@ -76,7 +76,7 @@ class AbonTariff(models.Model): class Meta: db_table = 'abonent_tariff' permissions = ( - ('can_complete_service', _('finish service perm')) + ('can_complete_service', _('finish service perm')), )