Dmitry 9 years ago
parent
commit
e851983552
  1. 20
      abonapp/migrations/0009_abontariff_death_line.py
  2. 66
      abonapp/models.py
  3. 3
      abonapp/urls_abon.py
  4. 11
      abonapp/views.py
  5. 2
      clientsideapp/views.py
  6. 29
      cron.py
  7. 21
      mydefs.py
  8. 6
      tariff_app/base_intr.py
  9. 34
      tariff_app/custom_tariffs.py
  10. 2
      tariff_app/models.py
  11. 4
      templates/abonapp/activate_service.html
  12. 2
      templates/abonapp/buy_tariff.html
  13. 4
      templates/abonapp/services.html

20
abonapp/migrations/0009_abontariff_death_line.py

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-02-16 12:22
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0008_auto_20170209_0002'),
]
operations = [
migrations.AddField(
model_name='abontariff',
name='deadline',
field=models.DateTimeField(blank=True, default=None, null=True),
),
]

66
abonapp/models.py

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.utils import timezone from django.utils import timezone
from django.utils.datetime_safe import datetime
from django.db import models from django.db import models
from django.core.validators import DecimalValidator from django.core.validators import DecimalValidator
from agent import Transmitter, AbonStruct, TariffStruct, NasFailedResult from agent import Transmitter, AbonStruct, TariffStruct, NasFailedResult
@ -10,14 +9,7 @@ from accounts_app.models import UserProfile
class LogicError(Exception): class LogicError(Exception):
def __init__(self, value):
self.message = value
def __str__(self):
return repr(self.message)
def __str__(self):
return repr(self.message)
pass
class AbonGroup(models.Model): class AbonGroup(models.Model):
@ -56,6 +48,9 @@ class AbonTariff(models.Model):
# время начала действия, остальные что не начали действие - NULL # время начала действия, остальные что не начали действие - NULL
time_start = models.DateTimeField(null=True, blank=True, default=None) time_start = models.DateTimeField(null=True, blank=True, default=None)
# время завершения услуги
deadline = models.DateTimeField(null=True, blank=True, default=None)
def priority_up(self): def priority_up(self):
# ищем услугу с большим приоритетом(число приоритета меньше) # ищем услугу с большим приоритетом(число приоритета меньше)
target_abtar = AbonTariff.objects.filter( target_abtar = AbonTariff.objects.filter(
@ -108,21 +103,24 @@ class AbonTariff(models.Model):
# Считает текущую стоимость услуг согласно выбранной для тарифа логики оплаты (см. в документации) # Считает текущую стоимость услуг согласно выбранной для тарифа логики оплаты (см. в документации)
def calc_amount_service(self): def calc_amount_service(self):
calc_obj = self.tariff.get_calc_type()
calc_obj = self.tariff.get_calc_type()(self)
# calc_obj - instance of tariff_app.custom_tariffs.TariffBase # calc_obj - instance of tariff_app.custom_tariffs.TariffBase
amount = calc_obj.calc_amount(self)
amount = calc_obj.calc_amount()
return round(amount, 2) return round(amount, 2)
# Активируем тариф # Активируем тариф
def activate(self, current_user): def activate(self, current_user):
calc_obj = self.tariff.get_calc_type()(self)
amnt = self.calc_amount_service() amnt = self.calc_amount_service()
# если не хватает денег # если не хватает денег
if self.abon.ballance < amnt: if self.abon.ballance < amnt:
raise LogicError('Не хватает денег на счету') raise LogicError('Не хватает денег на счету')
# дата активации услуги
# считаем дату активации услуги
self.time_start = timezone.now() self.time_start = timezone.now()
# считаем дату завершения услуги
self.deadline = calc_obj.calc_deadline()
# снимаем деньги за услугу # снимаем деньги за услугу
self.abon.make_pay(current_user, amnt)
self.abon.make_pay(current_user, amnt, u_comment='Завершение и оплата услуги по истечению срока действия')
self.save() self.save()
# Используется-ли услуга сейчас, если время старта есть то он активирован # Используется-ли услуга сейчас, если время старта есть то он активирован
@ -209,7 +207,7 @@ class Abon(UserProfile):
self.ballance += amount self.ballance += amount
# покупаем тариф # покупаем тариф
def buy_tariff(self, tariff, author, comment=None):
def pick_tariff(self, tariff, author, comment=None):
assert isinstance(tariff, Tariff) assert isinstance(tariff, Tariff)
# выбераем связь ТарифАбонент с самым низким приоритетом # выбераем связь ТарифАбонент с самым низким приоритетом
@ -241,47 +239,29 @@ class Abon(UserProfile):
def activate_next_tariff(self, author): def activate_next_tariff(self, author):
ats = AbonTariff.objects.filter(abon=self).order_by('tariff_priority') ats = AbonTariff.objects.filter(abon=self).order_by('tariff_priority')
nw = datetime.now(tz=timezone.get_current_timezone())
nw = timezone.datetime.now()
for at in ats: for at in ats:
# Если активированный тариф
if not at.is_started():
return
# время к началу месяца
to_start_month = datetime(nw.year, nw.month, 1, tzinfo=timezone.get_current_timezone())
# проверяем расстояние от Сегодня до начала этого месяца.
# И от заказа тарифа до начала этого месяца
if (nw - at.time_start) > (nw - to_start_month):
# Заказ из прошлого месяца, срок действия закончен
print('Заказ из прошлого месяца, срок действия закончен')
# если услуга просрочена
if nw > at.deadline:
print("Услуга просрочена, отключаем, и подключаем новую")
# выберем следующую по приоритету # выберем следующую по приоритету
# next_tarifs = AbonTariff.objects.filter(tariff_priority__gt = self.tariff_priority, abon=self.abon) # next_tarifs = AbonTariff.objects.filter(tariff_priority__gt = self.tariff_priority, abon=self.abon)
next_tarifs = filter(lambda tr: tr.tariff_priority > at.tariff_priority, ats)[:2]
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: if len(next_tarifs) > 0:
next_tarifs[0].time_start = nw
next_tarifs[0].save(update_fields=['time_start'])
next_tarifs[0].activate(author)
# завершаем текущую услугу.
# удаляем запись о текущей услугу.
at.delete() at.delete()
# Создаём лог о завершении услуги
AbonLog.objects.create(
abon=self,
amount=0,
author=author,
comment='Завершение услуги по истечению срока действия'
)
# есть-ли доступ у абонента к услуге, смотрим в tariff_app.custom_tariffs.<TariffBase>.manage_access() # есть-ли доступ у абонента к услуге, смотрим в tariff_app.custom_tariffs.<TariffBase>.manage_access()
def is_access(self): def is_access(self):
trf = self.active_tariff() trf = self.active_tariff()
if not trf: return False if not trf: return False
ct = trf.get_calc_type()
ct = trf.get_calc_type()()
if ct.manage_access(self): if ct.manage_access(self):
return True return True
else: else:
@ -311,7 +291,7 @@ class InvoiceForPayment(models.Model):
author = models.ForeignKey(UserProfile, related_name='+') author = models.ForeignKey(UserProfile, related_name='+')
def __str__(self): def __str__(self):
return "%s -> %d $" % (self.abon.username, self.amount)
return "%s -> %.2f" % (self.abon.username, self.amount)
def set_ok(self): def set_ok(self):
self.status = True self.status = True

3
abonapp/urls_abon.py

@ -1,5 +1,4 @@
from django.conf.urls import url from django.conf.urls import url
from . import views from . import views
@ -14,7 +13,7 @@ urlpatterns = [
url(r'^(?P<uid>\d+)/pay_history', views.pay_history, name='abon_phistory'), url(r'^(?P<uid>\d+)/pay_history', views.pay_history, name='abon_phistory'),
url(r'^(?P<uid>\d+)/addinvoice$', views.add_invoice, name='add_invoice'), url(r'^(?P<uid>\d+)/addinvoice$', views.add_invoice, name='add_invoice'),
url(r'^(?P<uid>\d+)/buy$', views.buy_tariff, name='buy_tariff'),
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+)/chpriority$', views.chpriority, name='chpriority_tariff'),
url(r'^(?P<uid>\d+)/complete_service(?P<srvid>\d+)$', views.complete_service, name='compl_srv'), 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+)/activate_service(?P<srvid>\d+)$', views.activate_service, name='activate_service'),

11
abonapp/views.py

@ -285,6 +285,7 @@ def abonhome(request, gid, uid):
}) })
@mydefs.require_ssl
def terminal_pay(request): def terminal_pay(request):
from .pay_systems import allpay from .pay_systems import allpay
ret_text = allpay(request) ret_text = allpay(request)
@ -329,7 +330,7 @@ def add_invoice(request, gid, uid):
@login_required @login_required
@permission_required('abonapp.can_buy_tariff') @permission_required('abonapp.can_buy_tariff')
def buy_tariff(request, gid, uid):
def pick_tariff(request, gid, uid):
frm = None frm = None
grp = get_object_or_404(models.AbonGroup, id=gid) grp = get_object_or_404(models.AbonGroup, id=gid)
abon = get_object_or_404(models.Abon, id=uid) abon = get_object_or_404(models.Abon, id=uid)
@ -338,7 +339,7 @@ def buy_tariff(request, gid, uid):
frm = forms.BuyTariff(request.POST) frm = forms.BuyTariff(request.POST)
if frm.is_valid(): if frm.is_valid():
cd = frm.cleaned_data cd = frm.cleaned_data
abon.buy_tariff(cd['tariff'], request.user)
abon.pick_tariff(cd['tariff'], request.user)
#abon.save() #abon.save()
messages.success(request, 'Тариф успешно выбран') messages.success(request, 'Тариф успешно выбран')
return redirect('abonapp:abon_services', gid=gid, uid=abon.id) return redirect('abonapp:abon_services', gid=gid, uid=abon.id)
@ -433,7 +434,7 @@ def activate_service(request, gid, uid, srvid):
abtar.activate(request.user) abtar.activate(request.user)
messages.success(request, 'Услуга активирована') messages.success(request, 'Услуга активирована')
return redirect('abonapp:abon_home', gid, uid)
return redirect('abonapp:abon_services', gid, uid)
except NasFailedResult as e: except NasFailedResult as e:
messages.error(request, e) messages.error(request, e)
@ -441,12 +442,14 @@ def activate_service(request, gid, uid, srvid):
messages.warning(request, e) messages.warning(request, e)
except models.LogicError as e: except models.LogicError as e:
messages.error(request, e) messages.error(request, e)
calc_obj = abtar.tariff.get_calc_type()(abtar)
return render(request, 'abonapp/activate_service.html', { return render(request, 'abonapp/activate_service.html', {
'abon': abtar.abon, 'abon': abtar.abon,
'abon_group': abtar.abon.group, 'abon_group': abtar.abon.group,
'abtar': abtar, 'abtar': abtar,
'amount': amount, 'amount': amount,
'diff': abtar.abon.ballance - amount
'diff': abtar.abon.ballance - amount,
'deadline': calc_obj.calc_deadline()
}) })

2
clientsideapp/views.py

@ -45,7 +45,7 @@ def buy_service(request, srv_id):
service = get_object_or_404(Tariff, id=srv_id) service = get_object_or_404(Tariff, id=srv_id)
current_service = abon.active_tariff() current_service = abon.active_tariff()
if request.method == 'POST': if request.method == 'POST':
abon.buy_tariff(service, request.user, 'Покупка тарифного плана через личный кабинет, тариф "%s"'
abon.pick_tariff(service, request.user, 'Покупка тарифного плана через личный кабинет, тариф "%s"'
% service) % service)
messages.success(request, 'Вы подписались на новую услугу. Она встала на очередь подключений. ' messages.success(request, 'Вы подписались на новую услугу. Она встала на очередь подключений. '
'Когда закончится ваша текущая услуга, то включится эта') 'Когда закончится ваша текущая услуга, то включится эта')

29
cron.py

@ -2,14 +2,13 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import os import os
import django import django
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djing.settings") os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djing.settings")
django.setup() django.setup()
from abonapp.models import Abon
from agent import Transmitter
from abonapp.models import Abon, LogicError
from agent import Transmitter, NasNetworkError, NasFailedResult
def main():
tm = Transmitter() tm = Transmitter()
# получим инфу о записях в NAS # получим инфу о записях в NAS
@ -17,6 +16,9 @@ if __name__ == "__main__":
users = Abon.objects.all() users = Abon.objects.all()
for user in users: for user in users:
try:
# бдим за услугами абонента: просроченные отключить, заказанные подключить
user.activate_next_tariff(user)
# если нет ip то и нет смысла лезть в NAS # если нет ip то и нет смысла лезть в NAS
if user.ip_address is None: if user.ip_address is None:
@ -35,7 +37,7 @@ if __name__ == "__main__":
# ищем абонента в списке инфы из nas # ищем абонента в списке инфы из nas
abons = [queue for queue in queues if queue is not None] abons = [queue for queue in queues if queue is not None]
abons = [{'abon': queue.abon, 'mikro_id': queue.sid} for queue in queues if queue.abon.uid == user.pk]
abons = [{'abon': queue.abon, 'mikro_id': queue.sid} for queue in abons if queue.abon.uid == user.pk]
abons_len = len(abons) abons_len = len(abons)
if abons_len < 1: if abons_len < 1:
# абонент не найден в nas, добавим # абонент не найден в nas, добавим
@ -59,3 +61,18 @@ if __name__ == "__main__":
tm.start_user(abons[0]['mikro_id']) tm.start_user(abons[0]['mikro_id'])
else: else:
tm.pause_user(abons[0]['mikro_id']) tm.pause_user(abons[0]['mikro_id'])
except NasNetworkError as er:
print("Error:", er)
except NasFailedResult as er:
print("Error:", er)
except LogicError as er:
print("Notice:", er)
if __name__ == "__main__":
try:
main()
except NasNetworkError as e:
print(e)
except NasFailedResult as e:
print(e)

21
mydefs.py

@ -5,11 +5,12 @@ import socket
import struct import struct
from collections import Iterator from collections import Iterator
import os import os
from django.http import HttpResponse, Http404
from functools import wraps
from django.http import HttpResponse, Http404, HttpResponseRedirect
from django.shortcuts import redirect from django.shortcuts import redirect
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
from django.db import models from django.db import models
from djing.settings import PAGINATION_ITEMS_PER_PAGE
from djing.settings import PAGINATION_ITEMS_PER_PAGE, DEBUG
ip_addr_regex = r'^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$' ip_addr_regex = r'^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
@ -138,6 +139,7 @@ def order_helper(request):
# Декоратор проверяет аккаунт, чтоб не пускать клиентов в страницы администрации # Декоратор проверяет аккаунт, чтоб не пускать клиентов в страницы администрации
def only_admins(fn): def only_admins(fn):
@wraps(fn)
def wrapped(request, *args, **kwargs): def wrapped(request, *args, **kwargs):
if request.user.is_admin: if request.user.is_admin:
return fn(request, *args, **kwargs) return fn(request, *args, **kwargs)
@ -180,3 +182,18 @@ class RuTimedelta(timedelta):
ru_days = 'день' ru_days = 'день'
text_date = '%d %s %s' % (self.days, ru_days, text_date) text_date = '%d %s %s' % (self.days, ru_days, text_date)
return text_date return text_date
def require_ssl(view):
"""
Decorator that requires an SSL connection. If the current connection is not SSL, we redirect to the SSL version of
the page.
from: https://gist.github.com/ckinsey/9709984
"""
@wraps(view)
def wrapper(request, *args, **kwargs):
if not DEBUG and not request.is_secure():
target_url = "https://" + request.META['HTTP_HOST'] + request.path_info
return HttpResponseRedirect(target_url)
return view(request, *args, **kwargs)
return wrapper

6
tariff_app/base_intr.py

@ -5,12 +5,12 @@ from abc import ABCMeta, abstractmethod
class TariffBase(metaclass=ABCMeta): class TariffBase(metaclass=ABCMeta):
@abstractmethod @abstractmethod
def calc_amount(self, abon_tariff):
def calc_amount(self):
"""Считает итоговую сумму платежа""" """Считает итоговую сумму платежа"""
@abstractmethod @abstractmethod
def get_avail_time(self):
"""Возвращает оставшееся время услуги в секундах"""
def calc_deadline(self):
"""Считаем дату, до которой действкет тариф"""
@staticmethod @staticmethod
def description(): def description():

34
tariff_app/custom_tariffs.py

@ -1,42 +1,46 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from datetime import datetime, timedelta
from datetime import timedelta
from django.utils import timezone from django.utils import timezone
from .base_intr import TariffBase from .base_intr import TariffBase
from calendar import monthrange
# from abonapp import AbonTariff # from abonapp import AbonTariff
class TariffDefault(TariffBase): class TariffDefault(TariffBase):
# Базовый функционал считает стоимость пропорционально использованному времени
def calc_amount(self, abon_tariff):
def __init__(self, abon_tariff):
#assert isinstance(abon_tariff, AbonTariff) #assert isinstance(abon_tariff, AbonTariff)
self.abon_tariff = abon_tariff
# Базовый функционал считает стоимость пропорционально использованному времени
def calc_amount(self):
# сейчас # сейчас
nw = timezone.now() nw = timezone.now()
# сколько прошло с начала действия услуги # сколько прошло с начала действия услуги
# если времени начала нет то это начало действия, использованное время 0 # если времени начала нет то это начало действия, использованное время 0
time_diff = nw - abon_tariff.time_start if abon_tariff.time_start else timedelta(0)
time_diff = nw - self.abon_tariff.time_start if self.abon_tariff.time_start else timedelta(0)
# времени в этом месяце # времени в этом месяце
curr_month_time = datetime(nw.year, nw.month if nw.month == 12 else nw.month + 1, 1) - timedelta(days=1)
curr_month_time = timezone.datetime(nw.year, nw.month if nw.month == 12 else nw.month + 1, 1) - timedelta(days=1)
curr_month_time = timedelta(days=curr_month_time.day) curr_month_time = timedelta(days=curr_month_time.day)
# Сколько это в процентах от всего месяца (k - коеффициент) # Сколько это в процентах от всего месяца (k - коеффициент)
k = time_diff.total_seconds() / curr_month_time.total_seconds() k = time_diff.total_seconds() / curr_month_time.total_seconds()
# результат - это полная стоимость тарифа умноженная на k # результат - это полная стоимость тарифа умноженная на k
res = k * abon_tariff.tariff.amount
res = k * self.abon_tariff.tariff.amount
return float(res) return float(res)
# возвращаем сколько времени осталось до завершения услуги (конца месяца)
def get_avail_time(self):
from calendar import monthrange
# Тут мы расчитываем конец действия услуги, завершение будет в конце месяца
def calc_deadline(self):
nw = timezone.now() nw = timezone.now()
last_day = monthrange(nw.year, nw.month)[1] last_day = monthrange(nw.year, nw.month)[1]
last_month_date = datetime(year=nw.year, month=nw.month, day=last_day,
hour=23,minute=59, second=59,tzinfo=nw.tzinfo)
return last_month_date - nw
last_month_date = timezone.datetime(year=nw.year, month=nw.month, day=last_day,
hour=23, minute=59, second=59)
return timezone.make_aware(last_month_date)
@staticmethod @staticmethod
def description(): def description():
@ -47,8 +51,8 @@ class TariffDp(TariffDefault):
# в IS снимается вся стоимость тарифа вне зависимости от времени использования # в IS снимается вся стоимость тарифа вне зависимости от времени использования
# просто возвращаем всю стоимость тарифа # просто возвращаем всю стоимость тарифа
def calc_amount(self, abon_tariff):
return float(abon_tariff.tariff.amount)
def calc_amount(self):
return float(self.abon_tariff.tariff.amount)
@staticmethod @staticmethod
def description(): def description():
@ -56,7 +60,7 @@ class TariffDp(TariffDefault):
class TariffCp(TariffDefault): class TariffCp(TariffDefault):
def calc_amount(self, abon_tariff):
def calc_amount(self):
return 12.6 return 12.6
@staticmethod @staticmethod

2
tariff_app/models.py

@ -28,7 +28,7 @@ class Tariff(models.Model):
if len(ob) > 0: if len(ob) > 0:
res_type = ob[0][1] res_type = ob[0][1]
assert issubclass(res_type, TariffBase) assert issubclass(res_type, TariffBase)
return res_type()
return res_type
def __str__(self): def __str__(self):
return "%s (%.2f)" % (self.title, self.amount) return "%s (%.2f)" % (self.title, self.amount)

4
templates/abonapp/activate_service.html

@ -24,7 +24,9 @@
<p>Вы уверены что хотите активировать абоненту эту услугу?<br> <p>Вы уверены что хотите активировать абоненту эту услугу?<br>
Обратите внимание что с его счёта <b>снимутся деньги</b> и откроется доступ к ресурсам оплаченной Обратите внимание что с его счёта <b>снимутся деньги</b> и откроется доступ к ресурсам оплаченной
услуги.<br> услуги.<br>
Стоимость услуги: {{ amount }}руб. На счету {{ abon.ballance }} руб, останется {{ diff }} руб.</p>
Стоимость услуги: {{ amount }}руб. На счету {{ abon.ballance }} руб, останется {{ diff }} руб.<br>
Услуга будет действовать до {{ deadline|date:'d F Y, H:i:s' }}
</p>
<button type="submit" class="btn btn-sm btn-primary"> <button type="submit" class="btn btn-sm btn-primary">
<span class="glyphicon glyphicon-save"></span> Подтвердить <span class="glyphicon glyphicon-save"></span> Подтвердить

2
templates/abonapp/buy_tariff.html

@ -19,7 +19,7 @@
</h3> </h3>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<form role="form" action="{% url 'abonapp:buy_tariff' abon_group.id abon.id %}"
<form role="form" action="{% url 'abonapp:pick_tariff' abon_group.id abon.id %}"
method="post">{% csrf_token %} method="post">{% csrf_token %}
<div class="form-group"> <div class="form-group">
<label for="id_tariff">Выбирите тарифф</label> <label for="id_tariff">Выбирите тарифф</label>

4
templates/abonapp/services.html

@ -78,7 +78,7 @@
<tr> <tr>
<td colspan="7">Нет подключённых абоненту услуг. <td colspan="7">Нет подключённых абоненту услуг.
{% if perms.abonapp.can_buy_tariff %} {% if perms.abonapp.can_buy_tariff %}
<a href="{% url 'abonapp:buy_tariff' abon_group.id abon.id %}" class="lgtbx">Купить</a>
<a href="{% url 'abonapp:pick_tariff' abon_group.id abon.id %}" class="lgtbx">Купить</a>
{% endif %} {% endif %}
</td> </td>
</tr> </tr>
@ -88,7 +88,7 @@
<tfoot> <tfoot>
<tr> <tr>
<th colspan="7"> <th colspan="7">
<a href="{% url 'abonapp:buy_tariff' abon_group.id abon.id %}" class="btn btn-sm btn-success">
<a href="{% url 'abonapp:pick_tariff' abon_group.id abon.id %}" class="btn btn-sm btn-success">
<span class="glyphicon glyphicon-plus"></span> Купить услугу <span class="glyphicon glyphicon-plus"></span> Купить услугу
</a> </a>
</th> </th>

Loading…
Cancel
Save