Browse Source

Make new functionality. Add flag Abon.autoconnect_service, if it checked then service may connect automatically when old service is expired.

devel
Dmitry Novikov 8 years ago
parent
commit
073c98887c
  1. 3
      abonapp/locale/ru/LC_MESSAGES/django.po
  2. 44
      abonapp/migrations/0004_auto_20180918_1734.py
  3. 55
      abonapp/models.py
  4. 109
      abonapp/templates/abonapp/service.html
  5. 3
      abonapp/urls.py
  6. 15
      abonapp/views.py
  7. 45
      clientsideapp/locale/ru/LC_MESSAGES/django.po
  8. 11
      clientsideapp/templates/clientsideapp/services.html
  9. 3
      clientsideapp/urls.py
  10. 15
      clientsideapp/views.py
  11. 39
      periodic.py
  12. 6
      static/clientside/my_clientside.js
  13. 6
      static/js/my.js

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

@ -1153,3 +1153,6 @@ msgstr "Отмена"
msgid "View" msgid "View"
msgstr "Открыть" msgstr "Открыть"
msgid "Auto continue service."
msgstr "Автопродление услуги."

44
abonapp/migrations/0004_auto_20180918_1734.py

@ -0,0 +1,44 @@
# Generated by Django 2.1 on 2018-09-18 17:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0003_abon_nas'),
]
operations = [
migrations.AlterModelOptions(
name='abon',
options={'ordering': ('fio',), 'permissions': (('can_buy_tariff', 'Buy service perm'), ('can_add_ballance', 'fill account'), ('can_ping', 'Can ping')), 'verbose_name': 'Abon', 'verbose_name_plural': 'Abons'},
),
migrations.AlterModelOptions(
name='abonlog',
options={'ordering': ('-date',)},
),
migrations.AlterModelOptions(
name='additionaltelephone',
options={'ordering': ('owner_name',), 'verbose_name': 'Additional telephone', 'verbose_name_plural': 'Additional telephones'},
),
migrations.AlterModelOptions(
name='invoiceforpayment',
options={'ordering': ('date_create',), 'verbose_name': 'Debt', 'verbose_name_plural': 'Debts'},
),
migrations.AddField(
model_name='abon',
name='autoconnect_service',
field=models.BooleanField(default=False, verbose_name='Automatically connect next service'),
),
migrations.AlterField(
model_name='abon',
name='is_dynamic_ip',
field=models.BooleanField(default=False, verbose_name='Is dynamic ip'),
),
migrations.AlterField(
model_name='passportinfo',
name='date_of_acceptance',
field=models.DateField(verbose_name='Date of acceptance'),
),
]

55
abonapp/models.py

@ -6,7 +6,7 @@ from django.conf import settings
from django.core import validators from django.core import validators
from django.core.validators import RegexValidator from django.core.validators import RegexValidator
from django.db import models, connection, transaction from django.db import models, connection, transaction
from django.db.models.signals import post_delete, pre_delete, post_init
from django.db.models.signals import post_delete, pre_delete, post_init, pre_save
from django.dispatch import receiver from django.dispatch import receiver
from django.shortcuts import resolve_url from django.shortcuts import resolve_url
from django.utils import timezone from django.utils import timezone
@ -87,7 +87,7 @@ class AbonManager(MyUserManager):
class Abon(BaseAccount): class Abon(BaseAccount):
current_tariff = models.ForeignKey(AbonTariff, null=True, blank=True, on_delete=models.SET_NULL)
current_tariff = models.OneToOneField(AbonTariff, null=True, blank=True, on_delete=models.SET_NULL)
group = models.ForeignKey(Group, on_delete=models.SET_NULL, blank=True, null=True, verbose_name=_('User group')) group = models.ForeignKey(Group, on_delete=models.SET_NULL, blank=True, null=True, verbose_name=_('User group'))
ballance = models.FloatField(default=0.0) ballance = models.FloatField(default=0.0)
ip_addresses = models.ManyToManyField(IpLeaseModel, verbose_name=_('Ip addresses')) ip_addresses = models.ManyToManyField(IpLeaseModel, verbose_name=_('Ip addresses'))
@ -96,9 +96,10 @@ class Abon(BaseAccount):
house = models.CharField(_('House'), max_length=12, null=True, blank=True) house = models.CharField(_('House'), max_length=12, null=True, blank=True)
device = models.ForeignKey('devapp.Device', null=True, blank=True, on_delete=models.SET_NULL) device = models.ForeignKey('devapp.Device', null=True, blank=True, on_delete=models.SET_NULL)
dev_port = models.ForeignKey('devapp.Port', null=True, blank=True, on_delete=models.SET_NULL) dev_port = models.ForeignKey('devapp.Port', null=True, blank=True, on_delete=models.SET_NULL)
is_dynamic_ip = models.BooleanField(default=False)
is_dynamic_ip = models.BooleanField(_('Is dynamic ip'), default=False)
nas = models.ForeignKey('nas_app.NASModel', null=True, blank=True, on_delete=models.SET_NULL, nas = models.ForeignKey('nas_app.NASModel', null=True, blank=True, on_delete=models.SET_NULL,
verbose_name=_('Network access server'), default=None) verbose_name=_('Network access server'), default=None)
autoconnect_service = models.BooleanField(_('Automatically connect next service'), default=False)
MARKER_FLAGS = ( MARKER_FLAGS = (
('icon_donkey', _('Donkey')), ('icon_donkey', _('Donkey')),
@ -148,7 +149,16 @@ class Abon(BaseAccount):
) )
self.ballance += amount self.ballance += amount
def pick_tariff(self, tariff, author, comment=None, deadline=None):
def pick_tariff(self, tariff, author, comment=None, deadline=None) -> None:
"""
Trying to buy a service if enough money.
:param tariff: instance of tariff_app.models.Tariff.
:param author: Instance of accounts_app.models.UserProfile. Who connected this
service. May be None if author is a system.
:param comment: Optional text for logging this pay.
:param deadline: Instance of datetime.datetime. Date when service is expired.
:return: Nothing
"""
if not isinstance(tariff, Tariff): if not isinstance(tariff, Tariff):
raise TypeError raise TypeError
@ -170,22 +180,23 @@ class Abon(BaseAccount):
if self.ballance < amount: if self.ballance < amount:
raise LogicError(_('not enough money')) raise LogicError(_('not enough money'))
new_abtar = AbonTariff.objects.create(
deadline=deadline, tariff=tariff
)
self.current_tariff = new_abtar
with transaction.atomic():
new_abtar = AbonTariff.objects.create(
deadline=deadline, tariff=tariff
)
self.current_tariff = new_abtar
# charge for the service
self.ballance -= amount
# charge for the service
self.ballance -= amount
self.save()
self.save(update_fields=('ballance', 'current_tariff'))
# make log about it
AbonLog.objects.create(
abon=self, amount=-tariff.amount,
author=author,
comment=comment or _('Buy service default log')
)
# make log about it
AbonLog.objects.create(
abon=self, amount=-tariff.amount,
author=author,
comment=comment or _('Buy service default log')
)
# Destroy the service if the time has come # Destroy the service if the time has come
# def bill_service(self, author): # def bill_service(self, author):
@ -468,8 +479,16 @@ def abon_tariff_post_init(sender, **kwargs):
abon_tariff = kwargs["instance"] abon_tariff = kwargs["instance"]
if getattr(abon_tariff, 'time_start') is None: if getattr(abon_tariff, 'time_start') is None:
abon_tariff.time_start = timezone.now() abon_tariff.time_start = timezone.now()
calc_obj = abon_tariff.tariff.get_calc_type()(abon_tariff)
if getattr(abon_tariff, 'deadline') is None: if getattr(abon_tariff, 'deadline') is None:
calc_obj = abon_tariff.tariff.get_calc_type()(abon_tariff)
abon_tariff.deadline = calc_obj.calc_deadline()
@receiver(pre_save, sender=AbonTariff)
def abon_tariff_pre_save(sender, **kwargs):
abon_tariff = kwargs["instance"]
if getattr(abon_tariff, 'deadline') is None:
calc_obj = abon_tariff.tariff.get_calc_type()(abon_tariff)
abon_tariff.deadline = calc_obj.calc_deadline() abon_tariff.deadline = calc_obj.calc_deadline()

109
abonapp/templates/abonapp/service.html

@ -3,6 +3,58 @@
{% block content %} {% block content %}
<div class="row"> <div class="row">
<div class="col-sm-6">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans 'Services for buy' %}</h3>
</div>
<div class="panel-body">
<table class="table table-condensed">
<thead>
<tr>
<th>{% trans 'Pick a service' %}</th>
<th>{% trans 'Service' %}</th>
<th>{% trans 'Price' %}</th>
<th>{% trans 'Speed In' %}</th>
<th>{% trans 'Speed Out' %}</th>
</tr>
</thead>
<tbody>
{% with can_ch_trf=perms.tariff_app.change_tariff %}
{% for service in services %}
<tr>
<td><a href="{% url 'abonapp:pick_tariff' group.pk abon.username %}?selected_tariff={{ service.pk }}"
class="btn btn-sm btn-default" title="{{ service.get_calc_type_display }}" data-toggle="tooltip"{% if abon_tariff %} disabled{% endif %}>
<span class="glyphicon glyphicon-shopping-cart"></span>
</a></td>
<td>
{% if can_ch_trf %}
<a href="{% url 'tarifs:edit' service.pk %}" title="{{ service.descr }}" data-toggle="tooltip"><b>{{ service.title }}</b></a>
{% else %}
{{ service.title }}
{% endif %}
</td>
<td>{{ service.amount }} {% trans 'currency' %}</td>
<td>{{ service.speedIn }}</td>
<td>{{ service.speedOut }}</td>
</tr>
{% empty %}
<tr><td colspan="5">
{% trans 'This group has no services' %}
<a href="{% url 'abonapp:ch_group_tariff' group.pk %}" class="btn btn-sm btn-default" title="{% trans 'User groups' %}">
<span class="glyphicon glyphicon-cog"></span> {% trans 'Tariffs in groups' %}
</a>
</td></tr>
{% endfor %}
{% endwith %}
</tbody>
</table>
<a href="{% url 'abonapp:ch_group_tariff' group.pk %}" class="btn btn-sm btn-primary" title="{% trans 'User groups' %}">
<span class="glyphicon glyphicon-cog"></span> {% trans 'Attach services to group' %}
</a>
</div>
</div>
</div>
<div class="col-sm-6"> <div class="col-sm-6">
<div class="panel panel-default"> <div class="panel panel-default">
@ -44,6 +96,10 @@
</dl> </dl>
<blockquote> <blockquote>
<p>
{% trans 'Auto continue service.' %}
<input type="checkbox" data-url="{% url 'abonapp:set_auto_continue_service' group.pk abon.username %}" class="autosave" {{ abon.autoconnect_service|yesno:'checked,' }}>
</p>
<p>{{ abon_tariff.tariff.descr }}</p> <p>{{ abon_tariff.tariff.descr }}</p>
</blockquote> </blockquote>
@ -68,58 +124,6 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-sm-6">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans 'Services for buy' %}</h3>
</div>
<div class="panel-body">
<table class="table table-condensed">
<thead>
<tr>
<th>{% trans 'Pick a service' %}</th>
<th>{% trans 'Service' %}</th>
<th>{% trans 'Price' %}</th>
<th>{% trans 'Speed In' %}</th>
<th>{% trans 'Speed Out' %}</th>
</tr>
</thead>
<tbody>
{% with can_ch_trf=perms.tariff_app.change_tariff %}
{% for service in services %}
<tr>
<td><a href="{% url 'abonapp:pick_tariff' group.pk abon.username %}?selected_tariff={{ service.pk }}"
class="btn btn-sm btn-default" title="{{ service.get_calc_type_display }}" data-toggle="tooltip"{% if abon_tariff %} disabled{% endif %}>
<span class="glyphicon glyphicon-shopping-cart"></span>
</a></td>
<td>
{% if can_ch_trf %}
<a href="{% url 'tarifs:edit' service.pk %}" title="{{ service.descr }}" data-toggle="tooltip"><b>{{ service.title }}</b></a>
{% else %}
{{ service.title }}
{% endif %}
</td>
<td>{{ service.amount }} {% trans 'currency' %}</td>
<td>{{ service.speedIn }}</td>
<td>{{ service.speedOut }}</td>
</tr>
{% empty %}
<tr><td colspan="5">
{% trans 'This group has no services' %}
<a href="{% url 'abonapp:ch_group_tariff' group.pk %}" class="btn btn-sm btn-default" title="{% trans 'User groups' %}">
<span class="glyphicon glyphicon-cog"></span> {% trans 'Tariffs in groups' %}
</a>
</td></tr>
{% endfor %}
{% endwith %}
</tbody>
</table>
<a href="{% url 'abonapp:ch_group_tariff' group.pk %}" class="btn btn-sm btn-primary" title="{% trans 'User groups' %}">
<span class="glyphicon glyphicon-cog"></span> {% trans 'Attach services to group' %}
</a>
</div>
</div>
</div>
{% if perms.tariff_app.view_periodic_pay %} {% if perms.tariff_app.view_periodic_pay %}
<div class="col-sm-6"> <div class="col-sm-6">
@ -149,6 +153,7 @@
</div> </div>
</div> </div>
{% endif %} {% endif %}
</div> </div>
{% endblock %} {% endblock %}

3
abonapp/urls.py

@ -32,7 +32,8 @@ subscriber_patterns = [
path('periodic_pay/<int:periodic_pay_id>/', views.add_edit_periodic_pay, name='add_periodic_pay'), path('periodic_pay/<int:periodic_pay_id>/', views.add_edit_periodic_pay, name='add_periodic_pay'),
path('periodic_pay/<int:periodic_pay_id>/del/', views.del_periodic_pay, name='del_periodic_pay'), path('periodic_pay/<int:periodic_pay_id>/del/', views.del_periodic_pay, name='del_periodic_pay'),
path('lease/add/', views.lease_add, name='lease_add'), path('lease/add/', views.lease_add, name='lease_add'),
path('ping/', views.abon_ping, name='ping')
path('ping/', views.abon_ping, name='ping'),
path('set_auto_continue_service/', views.set_auto_continue_service, name='set_auto_continue_service')
] ]
group_patterns = [ group_patterns = [

15
abonapp/views.py

@ -408,7 +408,6 @@ def add_invoice(request, gid: int, uname: str):
@login_required @login_required
@only_admins @only_admins
@permission_required('abonapp.can_buy_tariff') @permission_required('abonapp.can_buy_tariff')
@transaction.atomic
def pick_tariff(request, gid: int, uname): def pick_tariff(request, gid: int, uname):
grp = get_object_or_404(Group, pk=gid) grp = get_object_or_404(Group, pk=gid)
abon = get_object_or_404(models.Abon, username=uname) abon = get_object_or_404(models.Abon, username=uname)
@ -719,6 +718,20 @@ def abon_ping(request, gid: int, uname):
} }
@login_required
@only_admins
@json_view
def set_auto_continue_service(request, gid: int, uname):
checked = request.GET.get('checked')
checked = True if checked == 'true' else False
abon = get_object_or_404(models.Abon, username=uname)
abon.autoconnect_service = checked
abon.save(update_fields=('autoconnect_service',))
return {
'status': 0
}
@login_required @login_required
@only_admins @only_admins
def vcards(r): def vcards(r):

45
clientsideapp/locale/ru/LC_MESSAGES/django.po

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-08-09 14:57+0300\n"
"POT-Creation-Date: 2018-09-18 15:18+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Dmitry Novikov nerosketch@gmail.com\n" "Last-Translator: Dmitry Novikov nerosketch@gmail.com\n"
"Language: ru\n" "Language: ru\n"
@ -59,7 +59,7 @@ msgid "Your debt"
msgstr "Ваши долги" msgstr "Ваши долги"
#: templates/clientsideapp/debts.html:11 #: templates/clientsideapp/debts.html:11
#: templates/clientsideapp/tasklist.html:14
#: templates/clientsideapp/tasklist.html:13
msgid "State" msgid "State"
msgstr "Состояние" msgstr "Состояние"
@ -72,7 +72,7 @@ msgid "Description"
msgstr "Описание" msgstr "Описание"
#: templates/clientsideapp/debts.html:14 #: templates/clientsideapp/debts.html:14
#: templates/clientsideapp/tasklist.html:15
#: templates/clientsideapp/tasklist.html:14
msgid "Date of create" msgid "Date of create"
msgstr "Дата создания" msgstr "Дата создания"
@ -87,7 +87,7 @@ msgstr "Оплатить"
#: templates/clientsideapp/debts.html:23 templates/clientsideapp/ext.html:77 #: templates/clientsideapp/debts.html:23 templates/clientsideapp/ext.html:77
#: templates/clientsideapp/modal_service_buy.html:19 #: templates/clientsideapp/modal_service_buy.html:19
#: templates/clientsideapp/services.html:26 #: templates/clientsideapp/services.html:26
#: templates/clientsideapp/services.html:55
#: templates/clientsideapp/services.html:66
msgid "currency" msgid "currency"
msgstr "руб." msgstr "руб."
@ -195,6 +195,8 @@ msgid ""
"Inbound speed: %(speedIn)s MBit/s<br> Outgoing speed: %(speedOut)s MBit/" "Inbound speed: %(speedIn)s MBit/s<br> Outgoing speed: %(speedOut)s MBit/"
"s<br> Cost: %(amount)s rubles." "s<br> Cost: %(amount)s rubles."
msgstr "" msgstr ""
"Входящая скорость: %(speedIn)s MBit/s<br> Исходяшая скорость: %(speedOut)s "
"MBit/s<br> Стоимость: %(amount)s руб."
#: templates/clientsideapp/modal_service_buy.html:19 #: templates/clientsideapp/modal_service_buy.html:19
#, python-format #, python-format
@ -202,7 +204,7 @@ msgid "The cost is %(amount)s"
msgstr "Стоимость %(amount)s" msgstr "Стоимость %(amount)s"
#: templates/clientsideapp/modal_service_buy.html:23 #: templates/clientsideapp/modal_service_buy.html:23
#: templates/clientsideapp/services.html:63
#: templates/clientsideapp/services.html:74
msgid "Pick" msgid "Pick"
msgstr "Заказать" msgstr "Заказать"
@ -246,7 +248,26 @@ msgstr "Дата завершения услуги"
msgid "Cost" msgid "Cost"
msgstr "Стоимость" msgstr "Стоимость"
#: templates/clientsideapp/services.html:35
#: templates/clientsideapp/services.html:28
msgid "Auto continue service."
msgstr "Автопродление услуги."
#: templates/clientsideapp/services.html:33
msgid ""
"The check box <b>Auto continue service</b> for auto-renewal service is "
"designed so that the following <u>automatically</u> connected to the service "
"that you had last month. Connection will occur if the account has enough "
"funds.</p> <p>If you do not have time to make a Deposit before the service "
"ended, replenish your account and log back into your personal account to "
"connect it.</p>"
msgstr ""
"<p>Флажок <b>Автопрдление услуги</b> предназначен для того чтоб в следующем "
"месяце <u>автоматически</u> подключилась услуга которая была у вас в прошлом "
"месяце. Подключение произойдёт если на счету достаточно средств.</p> <p>Если "
"вы не успели внести средства до того как закочилась услуга, пополните счёт и "
"снова войдите в личный кабинет чтоб подключить её.</p>"
#: templates/clientsideapp/services.html:46
msgid "" msgid ""
"<strong>Attantion!</strong> You have not yet a service, for use the services " "<strong>Attantion!</strong> You have not yet a service, for use the services "
"please purchase service you want." "please purchase service you want."
@ -254,27 +275,27 @@ msgstr ""
"<strong>Внимание!</strong> У вас нет услуги, для использования ресурсов " "<strong>Внимание!</strong> У вас нет услуги, для использования ресурсов "
"приобретите нужную услугу из представленных тут." "приобретите нужную услугу из представленных тут."
#: templates/clientsideapp/services.html:46
#: templates/clientsideapp/services.html:57
msgid "Services available for ordering" msgid "Services available for ordering"
msgstr "Доступные для заказа услуги" msgstr "Доступные для заказа услуги"
#: templates/clientsideapp/services.html:68
#: templates/clientsideapp/services.html:79
msgid "No services available for ordering" msgid "No services available for ordering"
msgstr "Нет доступных для заказа услуг" msgstr "Нет доступных для заказа услуг"
#: templates/clientsideapp/tasklist.html:7
#: templates/clientsideapp/tasklist.html:6
msgid "Task history" msgid "Task history"
msgstr "История заявок" msgstr "История заявок"
#: templates/clientsideapp/tasklist.html:16
#: templates/clientsideapp/tasklist.html:15
msgid "The nature of the damage" msgid "The nature of the damage"
msgstr "Характер заявки" msgstr "Характер заявки"
#: templates/clientsideapp/tasklist.html:17
#: templates/clientsideapp/tasklist.html:16
msgid "Expected or real completion date" msgid "Expected or real completion date"
msgstr "Ожидаемый или реальный срок выполнения" msgstr "Ожидаемый или реальный срок выполнения"
#: templates/clientsideapp/tasklist.html:43
#: templates/clientsideapp/tasklist.html:42
msgid "You didn't leave any requests for breakdowns." msgid "You didn't leave any requests for breakdowns."
msgstr "Заявки по вашей учётной записи не найдены" msgstr "Заявки по вашей учётной записи не найдены"

11
clientsideapp/templates/clientsideapp/services.html

@ -24,8 +24,19 @@
<dt>{% trans 'Cost' %}</dt> <dt>{% trans 'Cost' %}</dt>
<dd>{{ current_service.tariff.amount }} {% trans 'currency' %}</dd> <dd>{{ current_service.tariff.amount }} {% trans 'currency' %}</dd>
<dt>{% trans 'Auto continue service.' %}</dt>
<dd><input type="checkbox" data-url="{% url 'clientsideapp:set_auto_continue_service' %}" class="autosave" {{ request.user.autoconnect_service|yesno:'checked,' }}></dd>
</dl> </dl>
<p>{{ current_service.tariff.descr }}</p> <p>{{ current_service.tariff.descr }}</p>
{% blocktrans trimmed %}
The check box <b>Auto continue service</b> for auto-renewal service
is designed so that the following <u>automatically</u> connected to the service
that you had last month. Connection will occur if the account has enough funds.</p>
<p>If you do not have time to make a Deposit before the service ended,
replenish your account and log back into your personal account to connect it.</p>
{% endblocktrans %}
</div> </div>
</div> </div>

3
clientsideapp/urls.py

@ -10,5 +10,6 @@ urlpatterns = [
path('services/<int:srv_id>/buy/', views.buy_service, name='buy_service'), path('services/<int:srv_id>/buy/', views.buy_service, name='buy_service'),
path('debts/', views.debts_list, name='debts'), path('debts/', views.debts_list, name='debts'),
path('debts/<int:d_id>/', views.debt_buy, name='debt_buy'), path('debts/<int:d_id>/', views.debt_buy, name='debt_buy'),
path('tasks/', views.task_history, name='task_history')
path('tasks/', views.task_history, name='task_history'),
path('set_auto_continue_service/', views.set_auto_continue_service, name='set_auto_continue_service')
] ]

15
clientsideapp/views.py

@ -5,6 +5,7 @@ from django.db import transaction
from django.utils.translation import gettext_lazy as _, gettext from django.utils.translation import gettext_lazy as _, gettext
from abonapp.models import AbonLog, InvoiceForPayment, Abon from abonapp.models import AbonLog, InvoiceForPayment, Abon
from djing.lib.decorators import json_view
from tariff_app.models import Tariff from tariff_app.models import Tariff
from taskapp.models import Task from taskapp.models import Task
from djing.lib import LogicError from djing.lib import LogicError
@ -43,7 +44,6 @@ def services(request):
@login_required @login_required
@transaction.atomic
def buy_service(request, srv_id): def buy_service(request, srv_id):
abon = request.user abon = request.user
service = get_object_or_404(Tariff, pk=srv_id) service = get_object_or_404(Tariff, pk=srv_id)
@ -115,3 +115,16 @@ def task_history(request):
return render(request, 'clientsideapp/tasklist.html', { return render(request, 'clientsideapp/tasklist.html', {
'tasks': tasks 'tasks': tasks
}) })
@login_required
@json_view
def set_auto_continue_service(request):
checked = request.GET.get('checked')
checked = True if checked == 'true' else False
abon = request.user
abon.autoconnect_service = checked
abon.save(update_fields=('autoconnect_service',))
return {
'status': 0
}

39
periodic.py

@ -41,7 +41,8 @@ def main():
AbonTariff.objects.filter(abon=None).delete() AbonTariff.objects.filter(abon=None).delete()
now = timezone.now() now = timezone.now()
fields = ('id', 'tariff__title', 'abon__id') fields = ('id', 'tariff__title', 'abon__id')
expired_services = AbonTariff.objects.filter(deadline__lt=now).exclude(abon=None)
expired_services = AbonTariff.objects.exclude(abon=None).filter(deadline__lt=now,
abon__autoconnect_service=False)
# finishing expires services # finishing expires services
with transaction.atomic(): with transaction.atomic():
@ -57,6 +58,42 @@ def main():
) )
print(log) print(log)
expired_services.delete() expired_services.delete()
# Automatically connect new service
for ex in AbonTariff.objects.filter(deadline__lt=now, abon__autoconnect_service=True).exclude(
abon=None).iterator():
abon = ex.abon
trf = ex.tariff
amount = round(trf.amount, 2)
if abon.ballance >= amount:
# can continue service
with transaction.atomic():
abon.ballance -= amount
ex.time_start = now
ex.deadline = None # Deadline sets automatically in signal pre_save
ex.save(update_fields=('time_start', 'deadline'))
abon.save(update_fields=('ballance',))
# make log about it
l = AbonLog.objects.create(
abon=abon, amount=-amount,
comment="Автоматическое продление услуги '%s'" % trf.title
)
print(l.comment)
else:
# finish service
with transaction.atomic():
ex.delete()
l = AbonLog.objects.create(
abon_id=ex.abon.id,
amount=0,
author=None,
date=now,
comment="Срок действия услуги '%(service_name)s' истёк" % {
'service_name': ex.tariff.title
}
)
print(l.comment)
signals.pre_delete.connect(abontariff_pre_delete, sender=AbonTariff) signals.pre_delete.connect(abontariff_pre_delete, sender=AbonTariff)
# manage periodic pays # manage periodic pays

6
static/clientside/my_clientside.js

@ -40,6 +40,12 @@ $(document).ready(function () {
} }
}); });
// autosave checkbox
$('input[type=checkbox].autosave').on('click', function(){
var data_url = $(this).attr('data-url');
$.getJSON(data_url, {checked: this.checked});
});
$('.btn-modal').on('click', function(){ $('.btn-modal').on('click', function(){
$.get(this.href, function(r){ $.get(this.href, function(r){
show_ModalMyContent(r); show_ModalMyContent(r);

6
static/js/my.js

@ -297,6 +297,12 @@ $(document).ready(function () {
return false; return false;
}); });
// autosave checkbox
$('input[type=checkbox].autosave').on('click', function(){
var data_url = $(this).attr('data-url');
$.getJSON(data_url, {checked: this.checked});
});
$('button.player-btn').aplayer(); $('button.player-btn').aplayer();
$('[data-toggle="tooltip"]').tooltip({container:'body'}); $('[data-toggle="tooltip"]').tooltip({container:'body'});

Loading…
Cancel
Save