# coding=utf-8 import json import urllib import datetime from simplejson import JSONDecodeError from django.db import models import django.utils.timezone from access.models import User, TrafHistory from lms.settings import BILL_URL, BILL_LOGIN, DOMAIN, YANDEX_SHOP_ID, YANDEX_scid from lms.tools import random_string, gen_pay_sig, out_uri, out_date_format from courses.models import Course, MATERIALS_TYPE, CourseMap from management.letters import sent_created_my_self_bill, sent_new_my_self_bill, new_student, \ pay_no_public_course, sent_new_service_request_to_out from service.models import MailBox from courses.models import Flow class Installment(models.Model): initiative = models.ForeignKey('Price', verbose_name=u'Иниациатива') user = models.ForeignKey(User, verbose_name=u'Пользователь') price = models.IntegerField(verbose_name=u'Общая цена') first_price = models.IntegerField(verbose_name=u'Первый платеж', default=0) period = models.IntegerField(verbose_name=u'Месяцев на оплату', default=5) date = models.DateTimeField(verbose_name=u'Дата открытия', default=datetime.datetime.now, editable=False) f_date = models.DateField(verbose_name=u'Дата закрытия', blank=True) rest = models.IntegerField(verbose_name=u'Остаток по задолжности', default=0) wait = models.IntegerField(verbose_name=u'Дней в задолжности', default=0, help_text=u'Через сколько дней ' u'предоставлять доступ после ' u'просрочки') expired = models.BooleanField(verbose_name=u'Просрочено', default=False) payments = models.ManyToManyField('Bill', verbose_name=u'Платежи', blank=True, null=True, related_name='bill_point') def __str__(self): return '%s %s' % (self.user, self.price) def __unicode__(self): return u'%s %s' % (self.user, self.price) class Meta: verbose_name = u'Рассрочка' verbose_name_plural = u'Рассрочки' class Price(models.Model): # Цены freepay = models.BooleanField(verbose_name=u'Свободный счет', default=False, editable=False) m_type = models.CharField(verbose_name=u'Тип подписки', max_length=1, choices=MATERIALS_TYPE, default='B') key = models.CharField(verbose_name=u'Ключ доступа', max_length=255, blank=True, editable=False, null=True) url = models.URLField(verbose_name=u'Ссылка на оплату', blank=True, null=True, editable=False) public = models.BooleanField(verbose_name=u'Опубликовать', default=False) title = models.CharField(verbose_name=u'Услуга', max_length=255, help_text=u'Будет показано пользователям') cost = models.IntegerField(verbose_name=u'Цена') course = models.ForeignKey(Course, verbose_name=u'Курс', null=True, blank=True) description = models.TextField(verbose_name=u'Описание', help_text=u'Будет показано менеджерам') included = models.ManyToManyField(CourseMap, verbose_name=u'Включены', null=True, blank=True, help_text=u'Если задействовать эту функцию, стандартная схема подписок будет ' u'не активна') by_time = models.IntegerField(verbose_name=u'Дней доступа', default=0, blank=True, null=True, help_text=u'По истечении этого периода доступ будет закрыт для включений.') post_fire = models.IntegerField(verbose_name=u'Дней сгорания', default=0, help_text=u'Предоставлении 50% скиндки на X дней. Сработает только при наличии "дней доступа"') def get_name(self): return '{1} / {0}'.format(self.course.get_title(), self.title) if self.course else self.title def __str__(self): return '%s / %s %s' % (self.course, self.title, self.cost) def __unicode__(self): return u'%s / %s %s' % (self.course, self.title, self.cost) def check_points(self): # Проверка существования всех точек курса в услуге results = 0 for point in CourseMap.objects.filter(course=self.course): if not self.included.filter(id=point.id).exists(): self.included.add(point) results += 1 return results def save(self, *args, **kwargs): if not self.key: self.key = random_string(length=50) if self.key and not self.url: self.url = DOMAIN + '/wallet/pay/self_bill/' + self.key if not self.course and not self.freepay: self.freepay = True elif self.course and self.freepay: self.freepay = False super(Price, self).save(*args, **kwargs) class Meta: verbose_name = u'Услуга' verbose_name_plural = u'Услуги' ordering = ['-id'] class Bill(models.Model): BILL_STATUSES = ( ('W', u'Ожидание согласия'), ('P', u'На оплате'), ('F', u'Оплачен'), ('C', u'Отклонен'), ('B', u'Отклонен банком'), ('H', u'Сгорел') ) BILL_METHOD = ( ('C', u'Наличные'), ('H', u'JustClick'), ('B', u'Банковский перевод'), ('G', u'На расчетный счет'), ('A', u'Альфа-Банк'), ('P', u'PayPal'), ('W', u'WebMoney'), ('S', u'SimplePay'), ('Y', u'YandexKassa') ) gift = models.BooleanField(verbose_name=u'Подарок', default=False) status = models.CharField(verbose_name=u'Статус', max_length=1, default='W', choices=BILL_STATUSES) _method = models.CharField(verbose_name=u'Способ оплаты', max_length=2, default='Y', choices=BILL_METHOD) price = models.CharField(verbose_name=u'Сумма', max_length=255, null=True, blank=True) real_price = models.CharField(verbose_name=u'Полученная сумма', max_length=255, null=True, blank=True, help_text=u'Сумма, минус комиссия') traf_source = models.ForeignKey(TrafHistory, verbose_name=u'Обращение', blank=True, null=True, editable=False) service = models.ForeignKey(Price, verbose_name=u'Оплачиваемая услуга') flow = models.ForeignKey( Flow, verbose_name=u'Поток', blank=True, null=True) inside_data = models.TextField(verbose_name=u'Данные проверки', default='', blank=True, editable=False) # user = models.ForeignKey(User, verbose_name=u'Плательщик', related_name=u'bill_user') opener = models.ForeignKey(User, verbose_name=u'Открывший', related_name=u'bill_opener', null=True) manager = models.ForeignKey(User, verbose_name=u'Менеджер', related_name=u'bill_manager', editable=False, null=True) # source_key = models.CharField(verbose_name=u'Исходник ключа', blank=True, max_length=255, default='', editable=False) key = models.CharField(verbose_name=u'Ключ платежа', blank=True, max_length=255, default='', editable=False) out_id = models.CharField(verbose_name=u'ID внешнего заказа', max_length=100, blank=True, default='', editable=False) admitad_uid = models.CharField(verbose_name=u'Ключь admitad', max_length=100, blank=True, default='', editable=False) date = models.DateTimeField(verbose_name=u'Дата создания счета', default=django.utils.timezone.now, editable=False) status_changed = models.DateTimeField(verbose_name=u'Дата смены статуса', default=django.utils.timezone.now, editable=False) comment = models.TextField(verbose_name=u'Комментарий продавца', help_text=u'Будет показано пользователю', blank=True, editable=False) description = models.TextField(verbose_name=u'Внутренняя заметка', help_text=u'Показано только внутри', default='', blank=True) finish_date = models.DateTimeField(verbose_name=u'Дата завершения', blank=True, null=True, editable=False) salt = models.CharField(verbose_name=u'Соль', max_length=100, blank=True, default=random_string, editable=False) views = models.IntegerField(verbose_name=u'Показать напоминание', default=0, help_text=u'Количество показов ' u'напоминания', blank=True) start_fire = models.DateTimeField(verbose_name=u'Дата начала сгорания', blank=True, null=True) start_fire_sent = models.BooleanField(verbose_name=u'Письмо сгорания', default=False, editable=False) fire_date = models.DateTimeField(verbose_name=u'Дата сгорания', blank=True, null=True) fire_date_sent = models.BooleanField(verbose_name=u'Письмо сгорания', default=False, editable=False) modals_show = models.BooleanField(verbose_name=u'Модалки показаны', default=False, editable=False) created_sent = models.BooleanField(verbose_name=u'Отправлено письмо сформированного счета', default=False, editable=False) create_letters = models.ManyToManyField(MailBox, verbose_name=u'Письма при создании', null=True, blank=True, related_name='bill_create_letter', editable=False) finish_letters = models.ManyToManyField(MailBox, verbose_name=u'Письма завершения', null=True, blank=True, related_name='bill_finish_letter', editable=False) def __unicode__(self): return u'%s:%s %s %s' % (self.id, self.get_status_display(), self.user, self.manager if self.manager else '') def __str__(self): return '%s:%s %s %s' % (self.id, self.get_status_display(), self.user, self.manager if self.manager else '') def get_face(self): return { 'id': self.id, 'price': self.price, 'status': {'flag': self.status, 'title': self.get_status_display()}, 'admitad_uid': self.admitad_uid, 'pay_url': '{0}/wallet/bill_out/{1}'.format(DOMAIN, self.salt), 'service': self.service.key, 'gift': self.gift, 'title': self.get_name(), 'user': '{0} / {1} / {2}'.format(self.user.get_full_name(), self.user.get_phone(), self.user.email), 'manager': self.manager.get_short_name() if self.manager else '' } def get_name(self): if self.service: return self.service.get_name() else: return 'Свободный счет ID:{0}'.format(self.id) # TODO: Что это вообще такое? Это далеко не статус def get_status_flag(self): if not self.service.by_time and not self.service.included.exists(): return self.service.m_type elif self.service.by_time: return 'S' elif self.service.included.exists(): return 'F' def get_type(self): if self.installment: return 'I' elif self.freeprice: return 'F' elif self.service: return 'S' def get_pay_parameters(self): # Получение параметров для создания подписи parameters = { 'sp_amount': self.price, 'sp_description': '{0} {1} Заказ: ID{2} Менеджер: {3}'.format(self.get_name(), self.user.full_data(), self.id, self.manager.get_short_name() if self.manager else ''), 'sp_order_id': self.id, 'sp_outlet_id': BILL_LOGIN, 'sp_salt': self.salt, 'sp_user_name': self.user.get_full_name(), 'sp_user_phone': self.user.get_phone(), 'sp_user_contact_email': self.user.email, 'sp_user_ip': self.user.get_ip(), # IP пользователя, совершающего платеж 'sp_user_params': '', # Параметры, передаваемые на ResultURL по этому запросу, } result = {} for key, value in parameters.items(): if value: result[key] = value return result def get_comment(self): return '{0} {1} Заказ: ID{2} Менеджер: {3}'.format(self.get_name(), self.user.full_data(), self.id, self.manager.get_short_name() if self.manager else '') def gen_robokassa_url(self): _params = self.get_pay_parameters() _params['sp_sig'] = gen_pay_sig(_params, method='payment', result=False) #for key, value in _params.items(): # if value: result += '%s=%s&' % (key, value) return out_uri(BILL_URL, _params) def gen_yandex_data(self): return {'url': 'https://money.yandex.ru/eshop.xml', 'data': {'shopId': YANDEX_SHOP_ID, 'scid': YANDEX_scid, 'orderNumber': self.id, 'customerNumber': self.user.id, 'sum': self.price}} def gen_pay_link(self): return '{0}/wallet/bill_out/{1}'.format(DOMAIN, self.salt) def save(self, *args, **kwargs): if self.price == '0' or self.gift: self.finish_date = datetime.datetime.now() self.status_changed = datetime.datetime.now() self.gift = True self.status = 'F' else: if not self.comment: self.comment = self.get_comment() if not self.salt: self.salt = random_string() if not self.price: self.price = self.service.cost if (self.service.by_time and self.finish_date) and self.service.post_fire and not self.fire_date: self.fire_date = self.finish_date + datetime.timedelta(days=(self.service.by_time+self.service.post_fire)) if (self.service.by_time and self.finish_date) and not self.start_fire: self.start_fire = self.finish_date + datetime.timedelta(days=self.service.by_time) if self.fire_date or self.views: self._type = 'P' if not self.opener: if self.status == 'W' and self.price != 0 and not self.created_sent: if self.manager and self.manager.in_role in ['M', 'S'] and not self.traf_source: for supervisor in User.objects.filter(in_role='S'): sent_new_my_self_bill(self, supervisor.email) self.created_sent = True if (self.status == 'F' or self.status == 'C') and not self.finish_date: self.finish_date = django.utils.timezone.now() if self.status == 'F' and not self.gift: self.user.customer = True self.user.save() # Отправить письма куратору if self.service and self.service.course: if self.service.course.public: for mentor in self.service.course.get_mentors(): new_student(self, mentor.email) else: for mentor in self.service.course.get_mentors(): pay_no_public_course(self, mentor.email) if self.manager and self.manager.in_role in ['M', 'S'] and not self.traf_source: title = 'Оплата отклонена' if self.status == 'C' else 'Счет оплачен' sent_created_my_self_bill(self, self.manager.email, title) for supervisor in User.objects.filter(in_role='S'): sent_created_my_self_bill(self, supervisor.email, title) super(Bill, self).save(*args, **kwargs) class Meta: verbose_name = u'Счет' verbose_name_plural = u'Счета' class ServiceRequest(models.Model): SERVICE_REQUEST_STATUS = ( ('S', u'Не обработан'), ('E', u'Ошибка контекста'), ('W', u'В работе'), ('F', u'Продан'), ('B', u'Не продал') ) BY_TYPE = ( ('S', 'Органично'), ('B', 'Привлечен') ) company = models.CharField(verbose_name=u'Компания продавец', max_length=255, blank=True, default='') product = models.CharField(verbose_name=u'Продукт', max_length=255, blank=True, default='') service = models.CharField(verbose_name=u'Услуга', max_length=255, blank=True, default='') name = models.CharField(verbose_name=u'Имя', max_length=255, blank=True, default='') email = models.CharField(verbose_name=u'email', max_length=255, blank=True, default='') phone = models.CharField(verbose_name=u'phone', max_length=255, blank=True, default='') lead_name = models.CharField(verbose_name=u'Метка amo', max_length=255, blank=True, default='') data = models.TextField(verbose_name=u'Данные', help_text=u'Словарь упаковывается в строку', default='') host = models.CharField(verbose_name=u'Источник запроса', default='', editable=False, max_length=255) _type = models.CharField(verbose_name=u'Тип запроса', max_length=1, choices=BY_TYPE, default='S') status = models.CharField(verbose_name=u'Статус', max_length=1, choices=SERVICE_REQUEST_STATUS, default='S') student = models.ForeignKey(User, verbose_name=u'Студент', related_name='student_user', blank=True, null=True) course = models.ForeignKey(Course, verbose_name=u'Курс', null=True) manager = models.ForeignKey(User, verbose_name=u'Продавец', related_name='manager_user', blank=True, null=True) cancel_description = models.TextField(verbose_name=u'Причина отказа', default='', blank=True) charge = models.TextField(verbose_name=u'Поручение', default='', blank=True) date = models.DateTimeField(verbose_name=u'Дата заказа', default=datetime.datetime.now) f_date = models.DateTimeField(verbose_name=u'Дата обаботки', blank=True, null=True) send = models.BooleanField(verbose_name=u'Отправлен в AMO', default=False, editable=False) send_date = models.DateTimeField(verbose_name=u'Время отправки', default=datetime.datetime.now, editable=False) def get_name(self): if self.course: return u'Доступ к курсу "%s"' % self.course.get_title() else: return u'Счет: ID%s' % self.id def get_client_name(self): _name = '' if self.student: _name = self.student.get_full_name() elif self.name: _name = self.name return u'%s' % _name def get_lead_name(self): if self.lead_name: _name = self.lead_name else: _product = '' if self.product: _product = self.product elif self.course: _product = self.course.get_title() _name = u'%s | %s | %s' % (self.company if self.company else 'LMS', _product, self.service if self.service else 'Заявка на покупку') return u'%s' % _name def sent_to_amo(self): if self.data: try: data = json.loads(self.data.replace("'", "\"")) except JSONDecodeError: self.status = "E" else: name = '' phone = '' email = '' if self.name: name = self.name elif self.student: name = self.student.get_full_name() if self.phone: phone = self.phone elif self.student: phone = self.student.get_phone() if self.email: email = self.email elif self.student: email = self.student.email data = { 'name': name, 'phone': phone, 'email': email, 'lead_name': self.get_lead_name() } if data['name'] == '': data['name'] = 'empty' urllib.request.urlopen(out_uri('https://skill-box.ru/amocrm/CreateLead.php', data)) if not self.send and self.status != 'E': data['host'] = self.host self.send = True self.save() self.send_alert(data) def __unicode__(self): return u'%s %s' % (self.status, self.student) def __str__(self): return u'%s %s' % (self.status, self.student) def send_alert(self, data): # Отправка оповещений # Получить почты try: r = RequestAlert.objects.get(title=self.lead_name) except RequestAlert.DoesNotExists: pass else: # Отправить письма for i in r.get_mails(): sent_new_service_request_to_out(self.lead_name, data, i) def save(self, *args, **kwargs): super(ServiceRequest, self).save(*args, **kwargs) class Meta: verbose_name = u'Запрос на покупку' verbose_name_plural = u'Запросы на прокупки' class RequestAlert(models.Model): title = models.CharField(verbose_name=u'Классификатор', max_length=255, editable=False) requests = models.ManyToManyField(ServiceRequest, verbose_name=u'Количество заявок', blank=True, null=True, editable=False) mails = models.TextField(verbose_name=u'Список почт', blank=True, help_text=u'Кому разослать дубли заявки. ЧЕРЕЗ ТОЧКУ С ЗАПЯТОЙ') date = models.DateTimeField(verbose_name=u'Начало заявок', default=datetime.datetime.now, editable=False) f_date = models.DateTimeField(verbose_name=u'Последняя заявка', default=datetime.datetime.now, editable=False) def __unicode__(self): return u'%s' % self.title def __str__(self): return u'%s' % self.title def _count(self): return self.requests.filter(date__gte=self.date).count() def up_count(self, request): # Увеличение счетчика self.requests.add(request) self.f_date = datetime.datetime.now() self.save() def get_mails(self): return map(lambda x: x.replace(" ", ""), str(self.mails).split(';')) if self.mails else [] def get_mails_str(self): return str(self.mails) class Meta: verbose_name = u'Оповещение о новых заявках' verbose_name_plural = u'Оповещения о новых заявках' class YandexKassaHistory(models.Model): _type = models.CharField(verbose_name=u'Тип запроса', max_length=255, default='') date = models.DateTimeField(verbose_name=u'Дата', default=datetime.datetime.now) text = models.TextField(verbose_name=u'Текст') result = models.CharField(verbose_name=u'Результат', max_length=255, default='') def __unicode__(self): return u'%s' % out_date_format(self.date) def __str__(self): return str(out_date_format(self.date)) class Meta: verbose_name = u'Яндекс Касса' verbose_name_plural = u'Яндекс Касса'