Beispiel #1
0
def call_invoicing(sender, instance, **kwargs):
    """
    Билинд для звонков через нашу телефонию
    Напоминание: instance.user1 - отправитель заявки, instance.user2 - получатель
    """
    if not instance.pk and instance.user2:
        transaction = Transaction(user=instance.user2,
                                  note=u'звонок от %s' % instance)

        # юзеры без региона должны страдать
        price_level = instance.user2.region.price_level if instance.user2.region else 'high'

        # пропущенный звонок тарифицируется как заказ звонка
        if instance.is_received():
            transaction.type = 84
            transaction.amount = -get_lead_price('call', instance.deal_type,
                                                 price_level)
        else:
            transaction.type = 85
            transaction.amount = -get_lead_price(
                'callrequest', instance.deal_type, price_level)

        # повторные звонки в течение 24 часов не тарифицируеются
        day_ago = instance.call_time - datetime.timedelta(days=1)
        if Call.objects.filter(user2=instance.user2,
                               callerid1=instance.callerid1,
                               call_time__gt=day_ago).exists():
            transaction.amount = 0

        transaction.save()
        instance.transaction = transaction
Beispiel #2
0
def add_transaction(request):
    from django import forms
    from django.http import HttpResponseForbidden
    from paid_services.models import Transaction, TRANSACTION_TYPE_CHOICES

    if request.user.groups.filter(
            id=12).count() == 0 and not request.user.is_superuser:
        return HttpResponseForbidden(u'У вас нет доступа к этой странице')

    type_choices = []
    for transaction_type, type_display in TRANSACTION_TYPE_CHOICES:
        if transaction_type in (1, 7):
            type_choices.append((transaction_type, type_display))

    class Form(forms.Form):
        email = forms.EmailField(label=u'E-mail пользователя')
        type = forms.ChoiceField(label=u'Тип транзакции', choices=type_choices)
        amount = forms.IntegerField(label=u'Сумма', min_value=1)

        def clean_email(self):
            email = self.cleaned_data['email']

            try:
                User.objects.get(email__iexact=email)
            except User.DoesNotExist:
                raise forms.ValidationError(u'У нас нет такого пользователя')
            except User.MultipleObjectsReturned:
                raise forms.ValidationError(u'Два пользователя с таким e-mail')
            else:
                return email

    if request.POST:
        form = Form(request.POST)
        if form.is_valid():
            type = int(form.cleaned_data['type'])
            user = User.objects.get(email__iexact=form.cleaned_data['email'])
            comment = u'%s, внес %s' % (dict(type_choices)[type],
                                        request.user.email)
            transaction = Transaction(user=user,
                                      amount=form.cleaned_data['amount'],
                                      type=type,
                                      comment=comment)
            transaction.save()
            return redirect(
                reverse('admin:paid_services_transaction_changelist') +
                ('?user=%d' % user.id))
    else:
        form = Form()

    return render(request, 'admin/add_transaction.html', locals())
Beispiel #3
0
    def move_money(self, request):
        class Form(forms.Form):
            from_user = UserField(label=u'От кого', help_text=u'e-mail или ID')
            to_user = UserField(label=u'Кому', help_text=u'e-mail или ID')
            amount = forms.IntegerField(label=u'Сумма перевода', min_value=1)

            def clean(self):
                if self.cleaned_data['from_user'].get_balance(
                        force=True) < self.cleaned_data['amount']:
                    raise forms.ValidationError(
                        u'Недостаточно средств у пользователя %s' %
                        self.cleaned_data['from_user'])

        if request.POST:
            from ad.models import Ad
            from paid_services.models import VipPlacement, InsufficientFundsError

            form = Form(request.POST)
            if form.is_valid():
                from_user = form.cleaned_data['from_user']
                to_user = form.cleaned_data['to_user']
                if request.user.is_superuser or request.user.groups.filter(id__in=[1, 12]).exists()\
                        or (from_user.get_agency() and from_user.get_agency() == to_user.get_agency()):
                    Transaction.move_money(from_user, to_user,
                                           form.cleaned_data['amount'],
                                           u'перевел %s' % request.user)
                    self.message_user(
                        request,
                        u'Деньги переведены. Баланс пользователя %s: %d грн' %
                        (to_user, to_user.get_balance(force=True)),
                        level=messages.SUCCESS)
                    return redirect(request.POST.get('next', '.'))
                else:
                    self.message_user(
                        request,
                        u'Пользователи не находятся в одном агентстве',
                        level=messages.ERROR)
        else:
            form = Form()
        return render(request, 'admin/move_money.html', locals())
Beispiel #4
0
def realtor_topup(request, realtor_id):
    agency = request.own_agency
    realtor = agency.realtors.filter(pk=realtor_id).first()

    if not agency or not realtor:
        raise Http404

    import decimal
    amount = request.GET.get('amount') or request.POST.get('amount')
    amount = decimal.Decimal(amount.replace(',', '.'))
    balance = request.user.get_balance(force=True)

    if balance >= amount:
        Transaction.move_money(request.user, realtor.user, amount,
                               u'через кабинет')
        return redirect(
            reverse('agency_admin:realtor_detail', args=[realtor_id]))
    else:
        from django.core.cache import cache
        deficit = abs(balance - amount)
        cache.set('interrupted_purchase_url_for_user%s' % request.user.id,
                  request.get_full_path(), 60 * 10)
        return redirect(
            reverse('profile_balance_topup') + ('?amount=%s' % deficit))
Beispiel #5
0
    def purchase_paidplacement(self,
                               ad,
                               paidplacement_type,
                               move_money_from_user=None,
                               order=None):
        from paid_services.models import VipPlacement, Transaction, InsufficientFundsError, PaidPlacement, CatalogPlacement

        if ad.user != self:
            raise Exception('User #%d has not an Ad #%d' % (self.id, ad.pk))

        price = self.get_paidplacement_price(ad, paidplacement_type)

        try:
            if paidplacement_type == 'vip':
                if VipPlacement.objects.filter(is_active=True,
                                               basead=ad).exists():
                    raise PaidPlacement.AlreadyExistError()

                transaction = Transaction(user=self,
                                          type=53,
                                          amount=-price,
                                          order=order)
                transaction.save()
                VipPlacement(basead=ad, transaction=transaction).save()

            elif paidplacement_type in ('intl_mesto', 'worldwide'):
                if CatalogPlacement.objects.filter(
                        is_active=True, basead=ad,
                        catalog=paidplacement_type).exists():
                    raise PaidPlacement.AlreadyExistError()

                if paidplacement_type == 'worldwide':
                    transaction = Transaction.objects.create(user=self,
                                                             type=55,
                                                             amount=-price,
                                                             order=order)
                elif paidplacement_type == 'intl_mesto':
                    transaction = Transaction.objects.create(user=self,
                                                             type=54,
                                                             amount=-price,
                                                             order=order)

                CatalogPlacement(basead=ad,
                                 catalog=paidplacement_type,
                                 transaction=transaction).save()

        except InsufficientFundsError as insufficient_funds_error:
            if move_money_from_user:
                Transaction.move_money(
                    move_money_from_user, self,
                    insufficient_funds_error.deficit,
                    u'для покупки платного размещения риелтором')
                self.purchase_paidplacement(ad, paidplacement_type)
            else:
                raise
Beispiel #6
0
    def purchase_plan(self, plan, move_money_from_user=None, order=None):
        from paid_services.views import get_plan_action  # TODO: надо избавиться от этого, но мешают хаки с подменой active_plan, например, в profile.views_plans.plan
        active_plan = self.get_active_plan()
        action = get_plan_action(plan, active_plan)
        region = self.region or Region.get_capital_province()
        price = Plan.get_price(region.price_level, plan.ads_limit,
                               self.get_plan_discount())
        unexpired_plans = self.get_unexpired_plans().order_by('-end')

        try:
            if action:
                if action == 'purchase':
                    transaction = Transaction.objects.create(user=self,
                                                             type=11,
                                                             amount=-price,
                                                             order=order)
                    purchased_userplan = UserPlan.objects.create(
                        user=self,
                        plan=plan,
                        ads_limit=plan.ads_limit,
                        region=region)
                if action == 'prolong':
                    transaction = Transaction.objects.create(
                        user=self,
                        type=11,
                        amount=-price,
                        order=order,
                        comment=u'продление для тарифа #%d' % active_plan.id)
                    purchased_userplan = UserPlan.objects.create(
                        user=self,
                        plan=plan,
                        ads_limit=plan.ads_limit,
                        region=region,
                        start=unexpired_plans[0].end,
                        is_active=False)
                if action == 'upgrade':
                    for unexpired_plan in unexpired_plans:
                        unexpired_plan.cancel(self)

                    active_plan.cancel(self)
                    transaction = Transaction.objects.create(user=self,
                                                             type=11,
                                                             amount=-price,
                                                             order=order)
                    purchased_userplan = UserPlan.objects.create(
                        user=self,
                        plan=plan,
                        ads_limit=plan.ads_limit,
                        region=region)

                Transaction.objects.filter(id=transaction.id).update(
                    user_plan=purchased_userplan)
            else:
                raise Exception('User #%d can not buy plan #%d' %
                                (self.id, plan.id))

        except InsufficientFundsError as insufficient_funds_error:
            if move_money_from_user:
                Transaction.move_money(move_money_from_user, self,
                                       insufficient_funds_error.deficit,
                                       u'для покупки тарифа риелтором')
                self.purchase_plan(plan)
            else:
                raise
Beispiel #7
0
    def buy_plan(self, request):
        class Form(forms.Form):
            user = UserField(label=u'Пользователь', help_text=u'email или ID')
            ads_limit = forms.IntegerField(label=u'Лимит по плану',
                                           min_value=1)
            price = forms.IntegerField(label=u'Цена тарифного плана',
                                       min_value=1,
                                       required=False)
            stop_active_plan = forms.BooleanField(
                label=u'Останавливать текущий', required=False)

        if request.POST:
            form = Form(request.POST)
            if form.is_valid():
                user = form.cleaned_data['user']
                ads_limit = form.cleaned_data['ads_limit']

                if not user.region:
                    from django.utils.safestring import mark_safe
                    self.message_user(
                        request,
                        mark_safe(
                            u'У пользователя отсутствует регион. <a href="%s">Указать регион</a>.'
                            % reverse('admin:custom_user_user_change',
                                      args=[user.id])),
                        level=messages.ERROR)
                    return render(request, 'admin/buy_plan.html', locals())

                try:
                    plan = Plan.objects.get(is_active=True,
                                            ads_limit=ads_limit)
                    discount = user.get_plan_discount()
                    suggest_plan_price = Plan.get_price(
                        user.region.price_level, ads_limit, discount)
                except Plan.DoesNotExist:
                    plan = Plan.objects.get(pk=18)

                    realtor = user.get_realtor()
                    if realtor:
                        agency_users = realtor.agency.get_realtors().exclude(
                            user=user).values_list('user', flat=True)
                        agency_ads_limits = (UserPlan.objects.filter(end__gt=datetime.datetime.now(), user__in=agency_users).aggregate(sum=Sum('ads_limit'))['sum'] or 0) \
                                            + ads_limit
                    else:
                        agency_ads_limits = ads_limit

                    if agency_ads_limits < 100:
                        discount = 0.2
                    elif agency_ads_limits < 200:
                        discount = 0.3
                    elif agency_ads_limits < 500:
                        discount = 0.4
                    elif agency_ads_limits < 1000:
                        discount = 0.45
                    else:
                        discount = 0.5
                    suggest_plan_price = Plan.get_price(
                        user.region.price_level, ads_limit, discount)

                if 'calculate' in request.POST:
                    form.data._mutable = True
                    form.data['price'] = suggest_plan_price

                    self.message_user(
                        request,
                        u'%s лимит объявлений в агентстве, %s%% скидка. Цена за план %s грн. Баланс пользователя %s грн'
                        % (ads_limit, int(discount * 100), suggest_plan_price,
                           user.get_balance()),
                        level=messages.WARNING)

                if 'buy' in request.POST:
                    new_plan = UserPlan(user=user,
                                        plan=plan,
                                        ads_limit=ads_limit,
                                        region=user.region)

                    active_plan = user.get_active_plan_using_prefetch()
                    if active_plan:
                        if form.cleaned_data['stop_active_plan']:
                            active_plan.cancel(request.user)
                            self.message_user(
                                request,
                                u'Предыдущий тариф #%s был отменен с возвратом средств'
                                % active_plan.pk,
                                level=messages.ERROR)
                        else:
                            new_plan.start = user.get_unexpired_plans(
                            ).order_by('-end').first().end
                            new_plan.is_active = False

                    plan_price = form.cleaned_data[
                        'price'] or suggest_plan_price
                    if not (1 < (plan_price / ads_limit) < 30):
                        self.message_user(
                            request,
                            u'Недопустимая цена за одно объявение: %.02f грн' %
                            (plan_price / float(ads_limit)),
                            level=messages.ERROR)
                    elif user.get_balance(force=True) < plan_price:
                        self.message_user(
                            request,
                            u'Недостаточно средств на счете. Тариф оценен в %s грн, баланс пользователя - %s'
                            % (plan_price, user.get_balance()),
                            level=messages.ERROR)
                    else:
                        # только здесь создается новый план
                        new_plan.save()
                        transaction = Transaction(user=user,
                                                  type=11,
                                                  amount=-plan_price,
                                                  user_plan=new_plan)
                        transaction.save()

                        self.message_user(
                            request,
                            u'Тариф на %s объявлений c %s до %s куплен. Стоимость %s грн.'
                            % (ads_limit,
                               new_plan.start.strftime('%d.%m.%Y %H:%M'),
                               new_plan.end.strftime('%d.%m.%Y %H:%M'),
                               plan_price))
                        return redirect('.')
        else:
            form = Form()

        return render(request, 'admin/buy_plan.html', locals())
Beispiel #8
0
    def buy_vip(self, request):
        vip_discounts_choices = (
            (0, 'без скидки'),
            (10, 'от 10 до 20 объяв - 10%'),
            (18, 'от 21 до 50 объяв - 18%'),
            (26, 'от 51 объяв - 26%'),
        )
        weeks_choices = (
            (1, 1),
            (2, 2),
            (4, 4),
        )

        class Form(forms.Form):
            ids = forms.CharField(label=u'ID объявлений',
                                  widget=forms.Textarea(attrs={'rows': 4}))
            discount = forms.IntegerField(
                label=u'Скидка по объему',
                widget=forms.Select(choices=vip_discounts_choices))
            weeks = forms.IntegerField(
                label=u'Длительность, недель',
                widget=forms.Select(choices=weeks_choices))
            bonus = forms.BooleanField(label=u'Бонус', required=False)

        if request.POST:
            from ad.models import Ad
            from paid_services.models import VipPlacement, InsufficientFundsError

            now = datetime.datetime.now()
            form = Form(request.POST)
            if form.is_valid():
                ad_ids = form.cleaned_data['ids'].replace(',', ' ').split()
                ads = Ad.objects.filter(pk__in=ad_ids)
                discount = form.cleaned_data['discount']
                weeks = form.cleaned_data['weeks']
                sum = 0

                bonus_comment = u'бонус от менеджера #%d %s' % (
                    request.user.id, request.user.email)
                bonus_vips_in_month = Transaction.objects.filter(
                    type=53,
                    time__year=now.year,
                    time__month=now.month,
                    comment=bonus_comment).count()

                for ad in ads:
                    user = ad.user
                    price = user.get_paidplacement_price(
                        ad, 'vip') * weeks * (100 - discount) / 100
                    transaction = Transaction(user=user,
                                              type=53,
                                              amount=-price)

                    # бесплатные ВИПы, один менеджер может дарить не большее 30 випов в месяц
                    if form.cleaned_data['bonus']:
                        if bonus_vips_in_month < 30:
                            transaction.comment = bonus_comment
                            transaction.amount = price = 0
                            bonus_vips_in_month += 1
                            weeks = 1

                    sum += price

                    message = u'[%s, объявление #%s] VIP на %d дней, стоимость %d грн - ' % (
                        user, ad.pk, weeks * 7, price)

                    if ad.vip_type:
                        self.message_user(request,
                                          u'%s уже VIP' % message,
                                          level=messages.ERROR)
                        continue

                    if 'buy' in request.POST:
                        try:
                            if price > user.get_balance(force=True):
                                agency_admin = user.get_realtor(
                                ).agency.get_admin_user()
                                Transaction.move_money(
                                    agency_admin, user, price,
                                    u'покупка VIP для объявления #%s' % ad.id)
                                message += u'(перевод денег с главного аккаунта)'

                            transaction.save()
                        except InsufficientFundsError:
                            self.message_user(
                                request,
                                u'%s недостаточно средств. Баланс %s' %
                                (message, user.get_balance()),
                                level=messages.ERROR)
                        else:
                            vip = VipPlacement.objects.create(
                                basead=ad,
                                days=weeks * 7,
                                transaction=transaction)
                            self.message_user(request,
                                              u'%s КУПЛЕН' % message,
                                              level=messages.SUCCESS)
                    else:
                        self.message_user(request,
                                          u'%s ОЦЕНЕН, еще не куплен' %
                                          message,
                                          level=messages.WARNING)

                if not ads:
                    self.message_user(request,
                                      u'Объявления не найдены',
                                      level=messages.ERROR)

                if len(ads) > 1:
                    self.message_user(request,
                                      u'Итого по всем объявлениям: %s грн' %
                                      sum,
                                      level=messages.WARNING)
        else:
            form = Form()

        return render(request, 'admin/buy_vip.html', locals())
Beispiel #9
0
def lead_activate(request):
    user_recipient = request.user
    if 'realtor' in request.GET:
        user_recipient = user_recipient.get_own_agency().get_realtors().get(
            pk=request.GET['realtor']).user

    # периоды лидогенерации создаются в сигнале check_leadgeneration_status у LeadGeneration
    leadgeneration, created = LeadGeneration.objects.get_or_create(
        user=user_recipient)
    leadgeneration.is_active_ads = True
    leadgeneration.save()

    balance_limit_for_activation = 200

    # выделенный номер стоит 100 грн
    # TODO: пусть пока будет общая логика и минималка без учета стоимости выделенного номера
    if user_recipient.get_leadgeneration(
    ) and user_recipient.get_leadgeneration().dedicated_numbers:
        balance_limit_for_activation += 100

    user_balance = user_recipient.get_balance(force=True)
    user_plan = user_recipient.get_active_plan()

    # учитываем возврат денег за тариф при переходе на ППК
    if user_plan:
        user_balance += user_plan.get_payback()

    if not user_recipient.get_realtor() and not user_recipient.is_developer():
        messages.error(
            request,
            _(u'Данной услугой могут воспользоваться только риелторы и застройщики'
              ))

    elif user_balance < balance_limit_for_activation and not user_recipient.has_active_leadgeneration(
            'ads'):
        from paid_services.models import Transaction, Order
        topup_amount = balance_limit_for_activation - user_balance

        # если услуги покупаются не риелтора агентства, но у риелтора не хватило денег,
        # то перекидываем деньги от текущего юзера
        if user_recipient != request.user and request.user.get_balance(
                force=True) >= topup_amount:
            Transaction.move_money(request.user, user_recipient, topup_amount,
                                   u'для активации ППК из кабинета агентства')

        if 'show_topup' not in request.GET:
            html = '''
                <p>%s</p><br/><button class="btn btn-danger btn-lg btn-block" type="button" data-toggle="modal" data-target=".topup-modal">%s</button>
            ''' % (
                _(u'Для активации услуги "Оплата за звонок" остаток на балансе должен быть более %(balance_limit)s грн.'
                  ) % {
                      'balance_limit': balance_limit_for_activation
                  },
                _(u'Пополнить'),
            )
            messages.info(request, html, extra_tags='modal-style1')

        query_string = request.GET.copy()
        query_string['topup_amount'] = topup_amount
        return HttpResponseRedirect(
            '%s?%s' % (reverse('services:lead'), query_string.urlencode()))

    elif user_recipient.has_active_leadgeneration('ads'):
        if user_recipient.ads.count() > 0:
            messages.success(request, _(u'Оплата за звонок активирована'))
        else:
            if request.is_developer_cabinet_enabled:
                add_property_url = reverse('profile_newhome_object_add')
            else:
                add_property_url = reverse('profile_add_property')

            html = '''<h5>%s<br/><br/>%s:</h5><br/><a href="%s" class="btn btn-danger btn-lg btn-block">%s</a>
            ''' % (
                _(u'Услуга оплата за звонок успешно активирована.'),
                _(u'Добавьте своё первое объявление'),
                add_property_url,
                _(u'Добавить'),
            )
            messages.info(request, html, extra_tags='modal-sm text-center')

        if 'next' in request.GET:
            return redirect(request.GET['next'])

    # возвращается на REFERER, т.к. на исходной странице могут переданы параметры типа ?realtor=
    return HttpResponseRedirect(
        request.META.get('HTTP_REFERER', reverse('services:lead')))