From e2bee3aee28c4de4e7279574b709c0ce089bd86d Mon Sep 17 00:00:00 2001 From: bashmak Date: Thu, 16 Feb 2017 17:47:58 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A2=D0=B5=D0=BF=D0=B5=D1=80=D1=8C=20=D0=B4?= =?UTF-8?q?=D0=B0=D1=82=D0=B0=20=D0=B7=D0=B0=D0=B2=D0=B5=D1=80=D1=88=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D1=83=D1=81=D0=BB=D1=83=D0=B3=D0=B8=20?= =?UTF-8?q?=D1=80=D0=B0=D1=81=D1=87=D0=B8=D1=82=D1=8B=D0=B2=D0=B0=D0=B5?= =?UTF-8?q?=D1=82=D1=81=D1=8F=20=D0=BF=D1=80=D0=B8=20=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D0=B8=20=D1=83=D1=81?= =?UTF-8?q?=D0=BB=D1=83=D0=B3=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- abonapp/models.py | 66 +++++++++---------------- abonapp/views.py | 11 +++-- tariff_app/base_intr.py | 6 +-- tariff_app/custom_tariffs.py | 34 +++++++------ tariff_app/models.py | 2 +- templates/abonapp/activate_service.html | 4 +- 6 files changed, 56 insertions(+), 67 deletions(-) diff --git a/abonapp/models.py b/abonapp/models.py index 8d20b02..2f243b9 100644 --- a/abonapp/models.py +++ b/abonapp/models.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- from django.utils import timezone -from django.utils.datetime_safe import datetime from django.db import models from django.core.validators import DecimalValidator from agent import Transmitter, AbonStruct, TariffStruct, NasFailedResult @@ -10,14 +9,7 @@ from accounts_app.models import UserProfile 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): @@ -56,6 +48,9 @@ class AbonTariff(models.Model): # время начала действия, остальные что не начали действие - 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( @@ -108,21 +103,24 @@ class AbonTariff(models.Model): # Считает текущую стоимость услуг согласно выбранной для тарифа логики оплаты (см. в документации) 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 - amount = calc_obj.calc_amount(self) + amount = calc_obj.calc_amount() return round(amount, 2) # Активируем тариф def activate(self, current_user): + calc_obj = self.tariff.get_calc_type()(self) amnt = self.calc_amount_service() # если не хватает денег if self.abon.ballance < amnt: raise LogicError('Не хватает денег на счету') - # дата активации услуги + # считаем дату активации услуги 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() # Используется-ли услуга сейчас, если время старта есть то он активирован @@ -209,7 +207,7 @@ class Abon(UserProfile): self.ballance += amount # покупаем тариф - def buy_tariff(self, tariff, author, comment=None): + def pick_tariff(self, tariff, author, comment=None): assert isinstance(tariff, Tariff) # выбераем связь ТарифАбонент с самым низким приоритетом @@ -241,47 +239,29 @@ class Abon(UserProfile): def activate_next_tariff(self, author): 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: - # Если активированный тариф - 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 = 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: - next_tarifs[0].time_start = nw - next_tarifs[0].save(update_fields=['time_start']) + next_tarifs[0].activate(author) - # завершаем текущую услугу. + # удаляем запись о текущей услугу. at.delete() - # Создаём лог о завершении услуги - AbonLog.objects.create( - abon=self, - amount=0, - author=author, - comment='Завершение услуги по истечению срока действия' - ) - # есть-ли доступ у абонента к услуге, смотрим в tariff_app.custom_tariffs..manage_access() def is_access(self): trf = self.active_tariff() if not trf: return False - ct = trf.get_calc_type() + ct = trf.get_calc_type()() if ct.manage_access(self): return True else: @@ -311,7 +291,7 @@ class InvoiceForPayment(models.Model): author = models.ForeignKey(UserProfile, related_name='+') def __str__(self): - return "%s -> %d $" % (self.abon.username, self.amount) + return "%s -> %.2f" % (self.abon.username, self.amount) def set_ok(self): self.status = True diff --git a/abonapp/views.py b/abonapp/views.py index c911460..d4d51e9 100644 --- a/abonapp/views.py +++ b/abonapp/views.py @@ -285,6 +285,7 @@ def abonhome(request, gid, uid): }) +@mydefs.require_ssl def terminal_pay(request): from .pay_systems import allpay ret_text = allpay(request) @@ -329,7 +330,7 @@ def add_invoice(request, gid, uid): @login_required @permission_required('abonapp.can_buy_tariff') -def buy_tariff(request, gid, uid): +def pick_tariff(request, gid, uid): frm = None grp = get_object_or_404(models.AbonGroup, id=gid) abon = get_object_or_404(models.Abon, id=uid) @@ -338,7 +339,7 @@ def buy_tariff(request, gid, uid): frm = forms.BuyTariff(request.POST) if frm.is_valid(): cd = frm.cleaned_data - abon.buy_tariff(cd['tariff'], request.user) + abon.pick_tariff(cd['tariff'], request.user) #abon.save() messages.success(request, 'Тариф успешно выбран') 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) messages.success(request, 'Услуга активирована') - return redirect('abonapp:abon_home', gid, uid) + return redirect('abonapp:abon_services', gid, uid) except NasFailedResult as e: messages.error(request, e) @@ -441,12 +442,14 @@ def activate_service(request, gid, uid, srvid): messages.warning(request, e) except models.LogicError as e: messages.error(request, e) + 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 + 'diff': abtar.abon.ballance - amount, + 'deadline': calc_obj.calc_deadline() }) diff --git a/tariff_app/base_intr.py b/tariff_app/base_intr.py index 2014a5e..caa6723 100644 --- a/tariff_app/base_intr.py +++ b/tariff_app/base_intr.py @@ -5,12 +5,12 @@ from abc import ABCMeta, abstractmethod class TariffBase(metaclass=ABCMeta): @abstractmethod - def calc_amount(self, abon_tariff): + def calc_amount(self): """Считает итоговую сумму платежа""" @abstractmethod - def get_avail_time(self): - """Возвращает оставшееся время услуги в секундах""" + def calc_deadline(self): + """Считаем дату, до которой действкет тариф""" @staticmethod def description(): diff --git a/tariff_app/custom_tariffs.py b/tariff_app/custom_tariffs.py index b4f0abe..7cef333 100644 --- a/tariff_app/custom_tariffs.py +++ b/tariff_app/custom_tariffs.py @@ -1,42 +1,46 @@ # -*- coding: utf-8 -*- -from datetime import datetime, timedelta +from datetime import timedelta from django.utils import timezone from .base_intr import TariffBase +from calendar import monthrange # from abonapp import AbonTariff class TariffDefault(TariffBase): - # Базовый функционал считает стоимость пропорционально использованному времени - def calc_amount(self, abon_tariff): + + def __init__(self, abon_tariff): #assert isinstance(abon_tariff, AbonTariff) + self.abon_tariff = abon_tariff + + # Базовый функционал считает стоимость пропорционально использованному времени + def calc_amount(self): # сейчас nw = timezone.now() # сколько прошло с начала действия услуги # если времени начала нет то это начало действия, использованное время 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) # Сколько это в процентах от всего месяца (k - коеффициент) k = time_diff.total_seconds() / curr_month_time.total_seconds() # результат - это полная стоимость тарифа умноженная на k - res = k * abon_tariff.tariff.amount + res = k * self.abon_tariff.tariff.amount return float(res) - # возвращаем сколько времени осталось до завершения услуги (конца месяца) - def get_avail_time(self): - from calendar import monthrange + # Тут мы расчитываем конец действия услуги, завершение будет в конце месяца + def calc_deadline(self): nw = timezone.now() 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 def description(): @@ -47,8 +51,8 @@ class TariffDp(TariffDefault): # в 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 def description(): @@ -56,7 +60,7 @@ class TariffDp(TariffDefault): class TariffCp(TariffDefault): - def calc_amount(self, abon_tariff): + def calc_amount(self): return 12.6 @staticmethod diff --git a/tariff_app/models.py b/tariff_app/models.py index 411f5c0..508276a 100644 --- a/tariff_app/models.py +++ b/tariff_app/models.py @@ -28,7 +28,7 @@ class Tariff(models.Model): if len(ob) > 0: res_type = ob[0][1] assert issubclass(res_type, TariffBase) - return res_type() + return res_type def __str__(self): return "%s (%.2f)" % (self.title, self.amount) diff --git a/templates/abonapp/activate_service.html b/templates/abonapp/activate_service.html index 14c2827..bfa6dfd 100644 --- a/templates/abonapp/activate_service.html +++ b/templates/abonapp/activate_service.html @@ -24,7 +24,9 @@

Вы уверены что хотите активировать абоненту эту услугу?
Обратите внимание что с его счёта снимутся деньги и откроется доступ к ресурсам оплаченной услуги.
- Стоимость услуги: {{ amount }}руб. На счету {{ abon.ballance }} руб, останется {{ diff }} руб.

+ Стоимость услуги: {{ amount }}руб. На счету {{ abon.ballance }} руб, останется {{ diff }} руб.
+ Услуга будет действовать до {{ deadline|date:'d F Y, H:i:s' }} +