Browse Source

На стадии реализации..

devel
Dmitry 9 years ago
parent
commit
9daac62549
  1. 30
      abonapp/locale/ru/LC_MESSAGES/django.po
  2. 237
      abonapp/models.py
  3. 2
      abonapp/templates/abonapp/buy_tariff.html
  4. 26
      abonapp/templates/abonapp/peoples.html
  5. 54
      abonapp/templates/abonapp/service.html
  6. 101
      abonapp/templates/abonapp/services.html
  7. 225
      abonapp/tests.py
  8. 2
      abonapp/urls_abon.py
  9. 67
      abonapp/views.py
  10. 3
      bugs.txt
  11. 2
      clientsideapp/views.py
  12. 2
      cron.py
  13. 2
      djing/utils/save_from_nodeny.py

30
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 "Услуга уже подключена"

237
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
# создаём новую связь с приоритетом ещё ниже
new_abtar = AbonTariff(
abon=self,
tariff=tariff,
tariff_priority=abtrf.tariff_priority + 1 if abtrf else -1
)
amount = round(tariff.amount, 2)
# Если это первая услуга в списке (фильтр по приоритету ничего не вернул)
if not abtrf:
# значит пробуем её активировать
new_abtar.activate(author, deadline)
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 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.<TariffBase>.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)

2
abonapp/templates/abonapp/buy_tariff.html

@ -22,7 +22,7 @@
<form role="form" action="{% url 'abonapp:pick_tariff' abon_group.pk abon.pk %}"
method="post">{% csrf_token %}
<div class="form-group">
<label for="id_tariff">{% trans 'Pick a service' %}</label>
<label for="id_tariffs">{% trans 'Pick a service' %}</label>
<div class="input-group">
<span class="input-group-addon"><span class="glyphicon glyphicon-bullhorn"></span></span>

26
abonapp/templates/abonapp/peoples.html

@ -50,7 +50,7 @@
{% if order_by == 'house' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
</th>
<th width="150">{% trans 'Telephone' %}</th>
<!--<th width="150">{% trans 'Service' %}</th>-->
<th width="150">{% trans 'Service' %}</th>
<th width="50">
<a href="{% url 'abonapp:people_list' abon_group.pk %}?order_by=ballance&dir={{ dir|default:"down" }}">
{% trans 'Ballance' %}
@ -83,16 +83,16 @@
<td>{{ human.street|default:_('Not assigned') }}</td>
<td>{{ human.house|default:_('Not assigned') }}</td>
<td><a href="tel:{{ human.telephone }}">{{ human.telephone }}</a></td>
<!--<td>
{ % if human.active_tariff %}
{ % if perms.tariff_app.change_tariff %}
<a href="{ % url 'tarifs:edit' human.active_tariff.pk %}">{ { human.active_tariff.title }}</a>
{ % else %}
{ { human.active_tariff.title }}
{ % endif %}
{ % else %}&mdash;&mdash;&mdash;
{ % endif %}
</td>-->
<td>
{% if human.active_tariff %}
{% if perms.tariff_app.change_tariff %}
<a href="{% url 'tarifs:edit' human.active_tariff.tariff.pk %}">{{ human.active_tariff.tariff.title }}</a>
{% else %}
{{ human.active_tariff.tariff.title }}
{% endif %}
{% else %}&mdash;&mdash;&mdash;
{% endif %}
</td>
<td>{{ human.ballance }}</td>
<td>
{% if perms.abonapp.delete_abon %}
@ -104,7 +104,7 @@
</tr>
{% empty %}
<tr>
<td colspan="10">
<td colspan="11">
{% trans 'Subscribers not found' %}.
{% if perms.abonapp.add_abon %}
<a href="{% url 'abonapp:add_abon' abon_group.pk %}">{% trans 'Add abon' %}</a>
@ -115,7 +115,7 @@
</tbody>
<tfoot>
<tr>
<td colspan="10" class="btn-group">
<td colspan="11" class="btn-group">
{% if perms.abonapp.add_abon %}
<a href="{% url 'abonapp:add_abon' abon_group.pk %}" class="btn btn-sm btn-default" title="Добавить">
<span class="glyphicon glyphicon-plus"></span> {% trans 'Add abon' %}

54
abonapp/templates/abonapp/service.html

@ -0,0 +1,54 @@
{% extends request.is_ajax|yesno:'nullcont.htm,abonapp/ext.htm' %}
{% load i18n %}
{% block content %}
<div class="row">
<div class="col-sm-6">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans 'Services of subscriber' %}</h3>
</div>
<div class="panel-body">
{% if abon_tariff %}
<p>
<b>{% trans 'Service' %}</b>:
{% if perms.tariff_app.change_tariff %}
<a href="{% url 'tarifs:edit' abon_tariff.pk %}" title="{{ abon_tariff.time_start|default:'' }}">
{{ abon_tariff.tariff.title }}
</a>
{% else %}
{{ abon_tariff.tariff.title }}
{% endif %}
</p>
<i><b>{% trans 'Sum' %}</b>: {{ abon_tariff.tarif.amount }} руб.</i>
<p><b>{% trans 'Input speed' %}</b>: {{ abon_tariff.tariff.speedIn }}</p>
<p><b>{% trans 'Output speed' %}</b>: {{ abon_tariff.tariff.speedOut }}</p>
<p><b>{% trans 'Works until' %}</b>: {{ abon_tariff.deadline|date:"d E Y, l" }}</p>
<p>{{ abon_tariff.tarif.descr }}</p>
{% else %}
No service, <a href="{% url 'abonapp:pick_tariff' abon_group.pk abon.pk %}" class="btn btn-sm btn-success">
<span class="glyphicon glyphicon-plus"></span> {% trans 'Buy service' %}
</a>
{% endif %}
</div>
</div>
</div>
<div class="col-sm-6">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Услуги для заказа</h3>
</div>
<div class="panel-body">
</div>
</div>
</div>
</div>
</div>
{% endblock %}

101
abonapp/templates/abonapp/services.html

@ -1,101 +0,0 @@
{% extends request.is_ajax|yesno:'nullcont.htm,abonapp/ext.htm' %}
{% load i18n %}
{% block content %}
<legend>{% trans 'Services of subscriber' %}</legend>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th width="50">{% trans 'Priority' %}</th>
<th>{% trans 'Service' %}</th>
<th>{% trans 'Sum' %}</th>
<th>{% trans 'Input speed' %}</th>
<th>{% trans 'Output speed' %}</th>
<th>{% trans 'Works until' %}</th>
<th>{% trans 'Do' %}</th>
</tr>
</thead>
<tbody>
{% for trf in abon_tarifs %}
<tr{% if trf.id == active_abontariff_id %} class="active"{% endif %}>
<td>{{ trf.tariff_priority }}</td>
<td>
{% if perms.tariff_app.change_tariff %}
<a href="{% url 'tarifs:edit' trf.tariff.id %}" title="{{ trf.time_start|default:'' }}">
{{ trf.tariff.title }}
</a>
{% else %}
{{ trf.tariff.title }}
{% endif %}
</td>
<td>{{ trf.tariff.amount }}</td>
<td>{{ trf.tariff.speedIn }}</td>
<td>{{ trf.tariff.speedOut }}</td>
<td>{{ trf.deadline|date:"d E Y, l" }}</td>
{% if trf.id != active_abontariff_id %}
<td class="btn-group">
{% if perms.abonapp.can_activate_service %}
{% if not active_abontariff_id %}
<a href="{% url 'abonapp:activate_service' abon_group.id abon.id trf.id %}"
class="btn btn-success btn-sm" title="{% trans 'Activate service' %}">
<i class="glyphicon glyphicon-shopping-cart"></i>
</a>
{% endif %}
{% endif %}
<!-- "{ % url 'abonapp:chpriority_tariff' abon_group.id abon.id % }?t={ { trf.id } }&a=up" -->
<a href="#"
class="btn btn-default btn-sm disabled" title="{% trans 'Priority up' %}">
<i class="glyphicon glyphicon-hand-up"></i>
</a>
<!-- "{ % url 'abonapp:chpriority_tariff' abon_group.id abon.id % }?t={ { trf.id } }&a=down" -->
<a href="#"
class="btn btn-default btn-sm disabled" title="{% trans 'Priority down' %}">
<i class="glyphicon glyphicon-hand-down"></i>
</a>
{% if perms.abonapp.delete_abontariff %}
<a href="{% url 'abonapp:unsubscribe_service' abon_group.id abon.id trf.id %}"
class="btn btn-danger btn-sm" title="{% trans 'Delete service' %}">
<i class="glyphicon glyphicon-remove"></i>
</a>
{% endif %}
</td>
{% else %}
<td>
<a href="{% url 'abonapp:compl_srv' abon_group.id abon.id trf.id %}" class="btn btn-danger btn-sm">
<i class="glyphicon glyphicon-remove"></i> {% trans 'Finish service' %}
</a>
</td>
{% endif %}
</tr>
{% empty %}
<tr>
<td colspan="7">{% trans 'Services of subscribers not found' %}.
{% if perms.abonapp.can_buy_tariff %}
<a href="{% url 'abonapp:pick_tariff' abon_group.id abon.id %}" class="lgtbx">{% trans 'Buy' %}</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
{% if perms.abonapp.can_buy_tariff %}
<tfoot>
<tr>
<th colspan="7">
<a href="{% url 'abonapp:pick_tariff' abon_group.id abon.id %}" class="btn btn-sm btn-success">
<span class="glyphicon glyphicon-plus"></span> {% trans 'Buy service' %}
</a>
</th>
</tr>
</tfoot>
{% endif %}
</table>
{% endblock %}

225
abonapp/tests.py

@ -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
)

2
abonapp/urls_abon.py

@ -15,10 +15,8 @@ urlpatterns = [
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+)/chpriority$', views.chpriority, name='chpriority_tariff'),
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+)/activate_service(?P<srvid>\d+)$', views.activate_service, name='activate_service'),
url(r'^(?P<uid>\d+)/opt82$', views.opt82, name='opt82'),
url(r'^(?P<uid>\d+)/chart$', views.charts, name='charts'),
url(r'^(?P<uid>\d+)/dials$', views.dials, name='dials'),

67
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()]

3
bugs.txt

@ -8,3 +8,6 @@
- Не надо коннектиться к микротику когда не собираемся ничего изменять. А то при сохранении залогинились и вышли без действий
- Не удаляет просроченные услуги если не пингуется NAS
- Надо отменить учёт временной зоны
!!! Обязательно проверить как отрабатывает на NAS удаление и изменение AbonTariff
!!! Удалить всё что связано с активацией услуги
!!! Убрать досрочное завершение услуги

2
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)

2
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:

2
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:

Loading…
Cancel
Save