From 073c98887cb5abaf0b3ac0f1647835037c2938e8 Mon Sep 17 00:00:00 2001
From: Dmitry Novikov
Date: Tue, 18 Sep 2018 17:58:23 +0300
Subject: [PATCH] Make new functionality. Add flag Abon.autoconnect_service, if
it checked then service may connect automatically when old service is
expired.
---
abonapp/locale/ru/LC_MESSAGES/django.po | 3 +
abonapp/migrations/0004_auto_20180918_1734.py | 44 +++++++
abonapp/models.py | 55 ++++++---
abonapp/templates/abonapp/service.html | 109 +++++++++---------
abonapp/urls.py | 3 +-
abonapp/views.py | 15 ++-
clientsideapp/locale/ru/LC_MESSAGES/django.po | 45 ++++++--
.../templates/clientsideapp/services.html | 11 ++
clientsideapp/urls.py | 3 +-
clientsideapp/views.py | 15 ++-
periodic.py | 39 ++++++-
static/clientside/my_clientside.js | 6 +
static/js/my.js | 6 +
13 files changed, 267 insertions(+), 87 deletions(-)
create mode 100644 abonapp/migrations/0004_auto_20180918_1734.py
diff --git a/abonapp/locale/ru/LC_MESSAGES/django.po b/abonapp/locale/ru/LC_MESSAGES/django.po
index 9e89ca2..cc058bc 100644
--- a/abonapp/locale/ru/LC_MESSAGES/django.po
+++ b/abonapp/locale/ru/LC_MESSAGES/django.po
@@ -1153,3 +1153,6 @@ msgstr "Отмена"
msgid "View"
msgstr "Открыть"
+
+msgid "Auto continue service."
+msgstr "Автопродление услуги."
diff --git a/abonapp/migrations/0004_auto_20180918_1734.py b/abonapp/migrations/0004_auto_20180918_1734.py
new file mode 100644
index 0000000..cf7bba3
--- /dev/null
+++ b/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'),
+ ),
+ ]
diff --git a/abonapp/models.py b/abonapp/models.py
index 00cfb73..71e5c7d 100644
--- a/abonapp/models.py
+++ b/abonapp/models.py
@@ -6,7 +6,7 @@ from django.conf import settings
from django.core import validators
from django.core.validators import RegexValidator
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.shortcuts import resolve_url
from django.utils import timezone
@@ -87,7 +87,7 @@ class AbonManager(MyUserManager):
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'))
ballance = models.FloatField(default=0.0)
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)
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)
- 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,
verbose_name=_('Network access server'), default=None)
+ autoconnect_service = models.BooleanField(_('Automatically connect next service'), default=False)
MARKER_FLAGS = (
('icon_donkey', _('Donkey')),
@@ -148,7 +149,16 @@ class Abon(BaseAccount):
)
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):
raise TypeError
@@ -170,22 +180,23 @@ class Abon(BaseAccount):
if self.ballance < amount:
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
# def bill_service(self, author):
@@ -468,8 +479,16 @@ def abon_tariff_post_init(sender, **kwargs):
abon_tariff = kwargs["instance"]
if getattr(abon_tariff, 'time_start') is None:
abon_tariff.time_start = timezone.now()
- calc_obj = abon_tariff.tariff.get_calc_type()(abon_tariff)
if getattr(abon_tariff, 'deadline') is None:
+ 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()
diff --git a/abonapp/templates/abonapp/service.html b/abonapp/templates/abonapp/service.html
index 3774ddf..a00c3bd 100644
--- a/abonapp/templates/abonapp/service.html
+++ b/abonapp/templates/abonapp/service.html
@@ -3,6 +3,58 @@
{% block content %}
+
+
+
+
{% trans 'Services for buy' %}
+
+
+
+
+
+ {% trans 'Pick a service' %}
+ {% trans 'Service' %}
+ {% trans 'Price' %}
+ {% trans 'Speed In' %}
+ {% trans 'Speed Out' %}
+
+
+
+ {% with can_ch_trf=perms.tariff_app.change_tariff %}
+ {% for service in services %}
+
+
+
+
+
+ {% if can_ch_trf %}
+ {{ service.title }}
+ {% else %}
+ {{ service.title }}
+ {% endif %}
+
+ {{ service.amount }} {% trans 'currency' %}
+ {{ service.speedIn }}
+ {{ service.speedOut }}
+
+ {% empty %}
+
+ {% trans 'This group has no services' %}
+
+ {% trans 'Tariffs in groups' %}
+
+
+ {% endfor %}
+ {% endwith %}
+
+
+
+ {% trans 'Attach services to group' %}
+
+
+
+
@@ -44,6 +96,10 @@
+
+ {% trans 'Auto continue service.' %}
+
+
{{ abon_tariff.tariff.descr }}
@@ -68,58 +124,6 @@
-
-
-
-
{% trans 'Services for buy' %}
-
-
-
-
-
- {% trans 'Pick a service' %}
- {% trans 'Service' %}
- {% trans 'Price' %}
- {% trans 'Speed In' %}
- {% trans 'Speed Out' %}
-
-
-
- {% with can_ch_trf=perms.tariff_app.change_tariff %}
- {% for service in services %}
-
-
-
-
-
- {% if can_ch_trf %}
- {{ service.title }}
- {% else %}
- {{ service.title }}
- {% endif %}
-
- {{ service.amount }} {% trans 'currency' %}
- {{ service.speedIn }}
- {{ service.speedOut }}
-
- {% empty %}
-
- {% trans 'This group has no services' %}
-
- {% trans 'Tariffs in groups' %}
-
-
- {% endfor %}
- {% endwith %}
-
-
-
- {% trans 'Attach services to group' %}
-
-
-
-
{% if perms.tariff_app.view_periodic_pay %}
@@ -149,6 +153,7 @@
{% endif %}
+
{% endblock %}
diff --git a/abonapp/urls.py b/abonapp/urls.py
index ad06746..d13a2fd 100644
--- a/abonapp/urls.py
+++ b/abonapp/urls.py
@@ -32,7 +32,8 @@ subscriber_patterns = [
path('periodic_pay//', views.add_edit_periodic_pay, name='add_periodic_pay'),
path('periodic_pay//del/', views.del_periodic_pay, name='del_periodic_pay'),
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 = [
diff --git a/abonapp/views.py b/abonapp/views.py
index 1534e7f..22c3531 100644
--- a/abonapp/views.py
+++ b/abonapp/views.py
@@ -408,7 +408,6 @@ def add_invoice(request, gid: int, uname: str):
@login_required
@only_admins
@permission_required('abonapp.can_buy_tariff')
-@transaction.atomic
def pick_tariff(request, gid: int, uname):
grp = get_object_or_404(Group, pk=gid)
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
@only_admins
def vcards(r):
diff --git a/clientsideapp/locale/ru/LC_MESSAGES/django.po b/clientsideapp/locale/ru/LC_MESSAGES/django.po
index c8726c4..744d0ac 100644
--- a/clientsideapp/locale/ru/LC_MESSAGES/django.po
+++ b/clientsideapp/locale/ru/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\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"
"Last-Translator: Dmitry Novikov nerosketch@gmail.com\n"
"Language: ru\n"
@@ -59,7 +59,7 @@ msgid "Your debt"
msgstr "Ваши долги"
#: templates/clientsideapp/debts.html:11
-#: templates/clientsideapp/tasklist.html:14
+#: templates/clientsideapp/tasklist.html:13
msgid "State"
msgstr "Состояние"
@@ -72,7 +72,7 @@ msgid "Description"
msgstr "Описание"
#: templates/clientsideapp/debts.html:14
-#: templates/clientsideapp/tasklist.html:15
+#: templates/clientsideapp/tasklist.html:14
msgid "Date of create"
msgstr "Дата создания"
@@ -87,7 +87,7 @@ msgstr "Оплатить"
#: templates/clientsideapp/debts.html:23 templates/clientsideapp/ext.html:77
#: templates/clientsideapp/modal_service_buy.html:19
#: templates/clientsideapp/services.html:26
-#: templates/clientsideapp/services.html:55
+#: templates/clientsideapp/services.html:66
msgid "currency"
msgstr "руб."
@@ -195,6 +195,8 @@ msgid ""
"Inbound speed: %(speedIn)s MBit/s Outgoing speed: %(speedOut)s MBit/"
"s Cost: %(amount)s rubles."
msgstr ""
+"Входящая скорость: %(speedIn)s MBit/s Исходяшая скорость: %(speedOut)s "
+"MBit/s Стоимость: %(amount)s руб."
#: templates/clientsideapp/modal_service_buy.html:19
#, python-format
@@ -202,7 +204,7 @@ msgid "The cost is %(amount)s"
msgstr "Стоимость %(amount)s"
#: templates/clientsideapp/modal_service_buy.html:23
-#: templates/clientsideapp/services.html:63
+#: templates/clientsideapp/services.html:74
msgid "Pick"
msgstr "Заказать"
@@ -246,7 +248,26 @@ msgstr "Дата завершения услуги"
msgid "Cost"
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 Auto continue service for auto-renewal service is "
+"designed so that the following automatically connected to the service "
+"that you had last month. Connection will occur if the account has enough "
+"funds.
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.
"
+msgstr ""
+"Флажок Автопрдление услуги предназначен для того чтоб в следующем "
+"месяце автоматически подключилась услуга которая была у вас в прошлом "
+"месяце. Подключение произойдёт если на счету достаточно средств.
Если "
+"вы не успели внести средства до того как закочилась услуга, пополните счёт и "
+"снова войдите в личный кабинет чтоб подключить её.
"
+
+#: templates/clientsideapp/services.html:46
msgid ""
"Attantion! You have not yet a service, for use the services "
"please purchase service you want."
@@ -254,27 +275,27 @@ msgstr ""
"Внимание! У вас нет услуги, для использования ресурсов "
"приобретите нужную услугу из представленных тут."
-#: templates/clientsideapp/services.html:46
+#: templates/clientsideapp/services.html:57
msgid "Services available for ordering"
msgstr "Доступные для заказа услуги"
-#: templates/clientsideapp/services.html:68
+#: templates/clientsideapp/services.html:79
msgid "No services available for ordering"
msgstr "Нет доступных для заказа услуг"
-#: templates/clientsideapp/tasklist.html:7
+#: templates/clientsideapp/tasklist.html:6
msgid "Task history"
msgstr "История заявок"
-#: templates/clientsideapp/tasklist.html:16
+#: templates/clientsideapp/tasklist.html:15
msgid "The nature of the damage"
msgstr "Характер заявки"
-#: templates/clientsideapp/tasklist.html:17
+#: templates/clientsideapp/tasklist.html:16
msgid "Expected or real completion date"
msgstr "Ожидаемый или реальный срок выполнения"
-#: templates/clientsideapp/tasklist.html:43
+#: templates/clientsideapp/tasklist.html:42
msgid "You didn't leave any requests for breakdowns."
msgstr "Заявки по вашей учётной записи не найдены"
diff --git a/clientsideapp/templates/clientsideapp/services.html b/clientsideapp/templates/clientsideapp/services.html
index 45abb0d..265999b 100644
--- a/clientsideapp/templates/clientsideapp/services.html
+++ b/clientsideapp/templates/clientsideapp/services.html
@@ -24,8 +24,19 @@
{% trans 'Cost' %}
{{ current_service.tariff.amount }} {% trans 'currency' %}
+
+ {% trans 'Auto continue service.' %}
+
+
{{ current_service.tariff.descr }}
+ {% blocktrans trimmed %}
+ The check box Auto continue service for auto-renewal service
+ is designed so that the following automatically connected to the service
+ that you had last month. Connection will occur if the account has enough funds.
+ 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.
+ {% endblocktrans %}
diff --git a/clientsideapp/urls.py b/clientsideapp/urls.py
index fa6fa18..10ec57a 100644
--- a/clientsideapp/urls.py
+++ b/clientsideapp/urls.py
@@ -10,5 +10,6 @@ urlpatterns = [
path('services//buy/', views.buy_service, name='buy_service'),
path('debts/', views.debts_list, name='debts'),
path('debts//', 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')
]
diff --git a/clientsideapp/views.py b/clientsideapp/views.py
index ae7a063..367e53b 100644
--- a/clientsideapp/views.py
+++ b/clientsideapp/views.py
@@ -5,6 +5,7 @@ from django.db import transaction
from django.utils.translation import gettext_lazy as _, gettext
from abonapp.models import AbonLog, InvoiceForPayment, Abon
+from djing.lib.decorators import json_view
from tariff_app.models import Tariff
from taskapp.models import Task
from djing.lib import LogicError
@@ -43,7 +44,6 @@ def services(request):
@login_required
-@transaction.atomic
def buy_service(request, srv_id):
abon = request.user
service = get_object_or_404(Tariff, pk=srv_id)
@@ -115,3 +115,16 @@ def task_history(request):
return render(request, 'clientsideapp/tasklist.html', {
'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
+ }
diff --git a/periodic.py b/periodic.py
index ed40fae..128cb0b 100755
--- a/periodic.py
+++ b/periodic.py
@@ -41,7 +41,8 @@ def main():
AbonTariff.objects.filter(abon=None).delete()
now = timezone.now()
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
with transaction.atomic():
@@ -57,6 +58,42 @@ def main():
)
print(log)
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)
# manage periodic pays
diff --git a/static/clientside/my_clientside.js b/static/clientside/my_clientside.js
index 3fcba4b..10d40a2 100644
--- a/static/clientside/my_clientside.js
+++ b/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(){
$.get(this.href, function(r){
show_ModalMyContent(r);
diff --git a/static/js/my.js b/static/js/my.js
index 80c8ecf..91649f7 100644
--- a/static/js/my.js
+++ b/static/js/my.js
@@ -297,6 +297,12 @@ $(document).ready(function () {
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();
$('[data-toggle="tooltip"]').tooltip({container:'body'});