Пример #1
0
class CallRequestAdmin(admin.ModelAdmin):
    list_display = ('id', 'time', 'get_user1', 'user2_link',
                    'transaction_display', 'get_object_display', 'name',
                    'email', 'phone', 'traffic_source')
    raw_id_fields = ('user1', 'user2', 'transaction')
    list_filter = (RequestTypeFilter, PaidRequestFilter,
                   make_datetime_filter('time'), CallRequestIPAddressFilter,
                   'traffic_source', make_userprovince_filter('user2__region'),
                   TransactionSumFilter)
    date_hierarchy = 'time'

    def get_queryset(self, request):
        return super(CallRequestAdmin, self).get_queryset(request)\
            .prefetch_related('transaction', 'user2__realtors__agency')

    def get_user1(self, obj):
        return u' '.join(map(unicode, filter(None, [obj.user1, obj.ip])))

    get_user1.allow_tags = True
    get_user1.short_description = u'отравитель'
    get_user1.admin_order_field = u'user1'

    def user2_link(self, obj):
        return get_user_filter_link(obj.user2, 'user2__exact')

    user2_link.allow_tags = True
    user2_link.short_description = u'получатель'
    user2_link.admin_order_field = u'user2'

    def get_object_display(self, obj):
        model_name = obj.content_type.model
        obj_type = {
            'ad': u'Объявл',
            'newhome': u'Новостр',
            'savedsearch': u'Поиск'
        }.get(model_name, 'прочее')
        if obj.object:
            if model_name in ['ad', 'newhome']:
                return '%s: <a href="%s">%s</a>' % (
                    obj_type, obj.object.get_absolute_url(), obj.object)
            elif model_name == 'savedsearch':
                return '%s: <a href="%s">%s</a>' % (
                    obj_type, obj.object.get_full_url(), obj.object)

        return '%s: %s' % (obj_type, obj.object)

    get_object_display.allow_tags = True
    get_object_display.short_description = u'объект'

    def transaction_display(self, obj):
        if obj.transaction:
            if obj.transaction.amount == 0:
                return u'бонус'
            else:
                return u'%s грн' % int(-obj.transaction.amount)

    transaction_display.short_description = u'цена'
Пример #2
0
class CallAdmin(admin.ModelAdmin):
    list_display = ('id', 'call_time', 'callerid1', 'callerid2', 'user2_link',
                    'transaction_display', 'deal_type', 'complaint',
                    'recordingfile_link')
    list_filter = ('complaint', 'deal_type', PaidCallFilter,
                   make_datetime_filter('call_time'), CallProxyNumberFilter,
                   'proxynumber__mobile_operator',
                   'proxynumber__traffic_source',
                   make_userprovince_filter('user2__region'),
                   TransactionSumFilter)
    raw_id_fields = ('user1', 'user2', 'transaction')
    date_hierarchy = 'call_time'
    actions = ('cancel', )

    def get_queryset(self, request):
        return super(CallAdmin, self).get_queryset(request)\
            .prefetch_related('user2__realtors__agency', 'user2__leadgenerationbonuses', 'transaction')

    def cancel(self, request, queryset):
        for call in queryset:
            call.cancel(request.user)

    cancel.short_description = u'Возврат денег за звонок'

    def user2_link(self, obj):
        return get_user_filter_link(obj.user2, 'user2__exact')

    user2_link.allow_tags = True
    user2_link.short_description = u'пользователь'

    def recordingfile_link(self, obj):
        if obj.duration:
            duration_str = u'%.1f мин' % (obj.duration / 60.0)
        else:
            duration_str = u''

        if obj.recordingfile:
            return u'<a href="%s">%s</a>' % (obj.recordingfile.url,
                                             duration_str)
        else:
            return duration_str

    recordingfile_link.allow_tags = True
    recordingfile_link.short_description = u'Запись'

    def transaction_display(self, obj):
        if obj.transaction:
            if obj.transaction.amount == 0:
                for bonus in obj.user2.leadgenerationbonuses.all():
                    if bonus.start < obj.call_time and (
                            not bonus.end or obj.call_time < bonus.end):
                        return u'бонус'
                return u'0 грн'
            else:
                return u'%s грн' % int(-obj.transaction.amount)

    transaction_display.short_description = u'цена'
Пример #3
0
class SearchCounterAdmin(admin.ModelAdmin):
    raw_id_fields = ['region']
    list_display = [
        'date', 'deal_type', 'property_type', 'rooms', 'region', 'price_from', 'price_to', 'currency',
        'area_from', 'area_to', 'facilities', 'without_commission', 'other_parameters',
        'searches_first_page', 'searches_all_pages'
    ]
    list_filter = (
        make_datetime_filter('date'), 'deal_type', 'property_type', fs.RoomsFilter, 'without_commission',
        'currency', fs.PriceFromFilter, fs.PriceToFilter, fs.AreaFromFilter, fs.AreaToFilter,
        fs.FacilitiesFilter, fs.ProvinceRegionFilter, fs.CityRegionFilter, fs.DistrictFilter,
    )
Пример #4
0
class StatAdmin(admin.ModelAdmin):
    raw_id_fields = ('user', )
    list_display = ('display_user', 'user_email', 'new_properties',
                    'active_properties', 'paid_properties', 'money_spent',
                    'entrances', 'ad_views', 'ad_contacts_views', 'plan_first',
                    'plan_other', 'time_period')
    list_filter = [
        StatManagerFilter,
        make_datetime_filter('date'), AgencyFilter, StatDataFilter,
        StatByProvince
    ]
    search_fields = (
        'user__email',
        'user__agencies__name',
        'user__first_name',
        'user__last_name',
    )
    date_hierarchy = 'date'
    list_display_links = None

    def get_queryset(self, request):
        return super(StatAdmin, self).get_queryset(request).prefetch_related(
            'user', 'user__agencies')

    def display_user(self, obj):
        if obj.user:
            return get_user_filter_link(obj.user)
        else:
            return u'все пользователи'

    display_user.allow_tags = True
    display_user.short_description = u'Пользователь'
    display_user.admin_order_field = 'user'

    def user_email(self, obj):
        if obj.user:
            return obj.user.email

    user_email.short_description = u"E-mail"

    def time_period(self, obj):
        return obj.date.strftime('%Y.%m.%d')

    time_period.short_description = u"День"
    time_period.admin_order_field = 'date'
Пример #5
0
class ActivityPeriodAdmin(admin.ModelAdmin):
    list_display = ('id', 'lead_type', 'user_link', 'start', 'display_status',
                    'get_calls', 'get_requests', 'get_numbers')
    list_filter = ('lead_type', IsActiveFilter, make_datetime_filter('start'),
                   make_datetime_filter('end'), NumberTypeFilter,
                   StatManagerFilter, make_userprovince_filter('user__region'))
    raw_id_fields = ('user', )

    def get_queryset(self, request):
        return super(ActivityPeriodAdmin, self).get_queryset(request)\
            .prefetch_related('user__callrequests_to', 'user__proxynumbers', 'user__answered_ppc_calls',
                              'user__realtors__agency', 'user__transactions', 'user__leadgeneration')

    def get_calls(self, obj):
        if obj.end:
            return obj.calls
        else:
            return len([
                call for call in obj.user.answered_ppc_calls.all()
                if call.call_time > obj.start
            ])

    get_calls.short_description = u'звонков'

    def get_requests(self, obj):
        if obj.end:
            return obj.requests
        else:
            return len([
                callrequest for callrequest in obj.user.callrequests_to.all()
                if callrequest.time > obj.start
            ])

    get_requests.short_description = u'запросов'

    def get_numbers(self, obj):
        if obj.end:
            return obj.numbers
        else:
            return obj.user.proxynumbers.count()

    get_numbers.short_description = u'телефонов'

    def user_link(self, obj):
        return get_user_filter_link(obj.user)

    user_link.allow_tags = True
    user_link.short_description = u'пользователь'

    def display_status(self, obj):
        if obj.end:
            return u"завершено %s" % obj.end.strftime("%Y-%m-%d %H:%M")
        else:
            result = [u"мобильные"]
            if not obj.user.leadgeneration.dedicated_numbers:
                result.append(u"общий")
            else:
                result.append(
                    u"выделенный" if obj.user.has_paid_dedicated_numbers(
                    ) else u"нет оплаты за выделенный")

            balance = int(sum([t.amount for t in obj.user.transactions.all()]))
            result.append(
                u'баланс <a title="Показать транзакции пользователя" href="%s?user__exact=%d">%s грн</a>'
                % (reverse('admin:paid_services_transaction_changelist'),
                   obj.user.id, balance))
            return u" / ".join(result)

    display_status.allow_tags = True
    display_status.short_description = u'Статус'
Пример #6
0
class AdAdmin(admin.ModelAdmin):
    form = AdAdminForm
    list_display = (
        'short_name', 'user_link', 'get_status_display', 'type', 'region_text', 'address', 'price_currency', 'add_date',
        'updated_date', 'item_images'
    )
    fieldsets = (
        (None, {
            'classes': ('wide_label',),
            'fields': (('user_info', 'bank'), ('status', 'moderation_status', 'vip_type'), ('deal_type', 'property_type', 'property_commercial_type'))
        }),
        (u'Основные параметры', {
            'fields': ('title', 'address',
                       ('addr_city', 'addr_street', 'addr_house', 'addr_country'),
                       ('rooms', 'area', 'area_living', 'area_kitchen'),
                       'description', ('price', 'currency'), 'iframe_url')
        }),
        (u'Дополнительные параметры', {
            'fields': (
                        ('floor', 'floors_total'),
                        ('building_layout', 'building_type', 'building_type_other'),
                        ('building_walls', 'building_windows', 'building_heating'),
                        'guests_limit',)
        }),
        (u'Прочее', {
            'classes': ('collapse',),
            'fields': (('created', 'modified'), ('updated',  'expired'), ('reserved', 'modified_calendar'), ('price_period', 'space_units'),
                'facilities', 'contact_person', ('detail_views', 'contacts_views'), ('coords_x', 'coords_y', 'geo_source'),
            )
        }),
    )
    readonly_fields = ('title', 'contact_person', 'updated', 'expired', 'user_info', 'address', 'modified',
                       'modified_calendar')
    list_filter = (
        fs.PropertyById, fs.M2MPhoneFilter, make_datetime_filter('created'), make_datetime_filter('updated'), fs.PropertyWithModeration, fs.PropertyBySource,
        fs.PropertyByContentProvider, 'status', 'moderation_status', 'vip_type', fs.CityRegionFilter, fs.ProvinceRegionFilter,
        'deal_type', 'property_type'
    )
    filter_horizontal = ['facilities', 'rules']
    exclude = ['image', 'region', 'price_uah', 'xml_id']
    search_fields = ['id']
    show_full_result_count = False
    #  date_hierarchy = 'created'
    actions = [update_region, approve_ads, to_rentdaily_ad] + change_status_actions + wrong_ad_actions + [ban_ad]
    inlines = [
        PhoneInline,
        PhotoInline,
    ]

    # custom field in fieldsets
    def user_info(self, obj):
        if obj.user:
            return u'ID %d (%s)' % (obj.user_id, obj.user.email or u'нет e-mail')
    user_info.short_description = u'пользователь'

    def get_readonly_fields(self, request, obj=None):
        readonly_fields = self.readonly_fields

        if not request.user.has_perm("%s.%s_%s" % ( 'ad', 'change', 'moderation')):
            readonly_fields = readonly_fields + ('status', 'moderation_status')

        if not request.user.has_perm("%s.%s_%s" % ( 'bank', 'change', 'bank')):
            readonly_fields = readonly_fields + ('vip_type', )

        if not request.user.is_superuser:
            readonly_fields = readonly_fields + ('addr_country',)

        # шиш вам
        if request.user.groups.filter(name__icontains=u'комитет').exists():
            return list(set(
                list(readonly_fields) + ['facilities'] +
                [field.name for field in self.opts.local_fields] +
                [field.name for field in self.opts.local_many_to_many]
            ))

        return readonly_fields

    def get_actions(self, request):
        actions = super(AdAdmin, self).get_actions(request)
        if not request.user.has_perm("%s.%s_%s" % ( 'ad', 'change', 'moderation')):
            return []
        return actions

    @property
    def media(self):
        return super(AdAdmin, self).media + forms.Media(js=['js/libs/jquery-last.min.js', 'js/admin_changeform.js', ])

    def get_queryset(self, request):
        qs = super(AdAdmin, self).get_queryset(request)
        return qs.select_related('region').prefetch_related('photos', 'bank', 'user', 'moderations',
                                                            'catalogplacements', 'user__user_plans', 'user__activityperiods',
                                                            'user__realtors__agency', 'user__leadgeneration')

    def get_status_display(self, obj):
        if not obj.moderation_status:
            status = obj.get_status_display()

            if obj.status == 1:
                for deactivation in obj.deactivations.all():
                    if not deactivation.returning_time:
                        status = u'<a href="%s?basead=%d">продано</a>' % (reverse('admin:ad_deactivationforsale_changelist'), obj.id)
                        break

            if obj.user:
                for placement in obj.catalogplacements.all():
                    if placement.until > datetime.datetime.now():
                        status += u'&nbsp;<a href="{}?basead={}" title="размещение в зарубежном каталоге"><img src="{}" style="background-color:{}"/></a> '.format(
                                    reverse('admin:paid_services_catalogplacement_changelist'), obj.id,
                                    static('admin/img/icon-dollar.png'), '#6c6874')

                if obj.addr_country == 'UA':
                    active_plan = obj.user.get_active_plan_using_prefetch()
                    if active_plan:
                        status += u'&nbsp;<a href="{}?id={}" title="{}"><img src="{}" style="background-color:{}"/></a> '.format(
                                    reverse('admin:paid_services_userplan_changelist'), active_plan.id,
                                    u'Тариф до {:%d.%m.%Y}. Лимит объявлений - {}'.format(active_plan.end, active_plan.ads_limit),
                                    static('admin/img/icon-dollar.png'), '#ecb310')

                    if obj.user.has_active_leadgeneration('ads'):
                        status += u'&nbsp;<a href="{}?id={}" title="лидогенерация"><img src="{}" style="background-color:{}"/></a> '.format(
                                    reverse('admin:ppc_leadgeneration_changelist'), obj.user.leadgeneration.id,
                                    static('admin/img/icon-dollar.png'), '#31c500')
            return status
        else:
            status = obj.get_moderation_status_display()
            return '<b class="red">%s</b>' % status[:18] + '..' if len(status) > 18 else status
    get_status_display.allow_tags = True
    get_status_display.short_description = u"статус"
    get_status_display.admin_order_field = 'status'

    def region_text(self, obj):
        if obj.region is None:
            return u'(без региона)'
        else:
            return u'<a href="?region__id__exact=%d" title="все объявления региона \'%s\'">%s</a>' % (obj.region.pk, obj.region.text, obj.region)
    region_text.allow_tags = True
    region_text.short_description = u"присв.\nрегион"
    region_text.admin_order_field = 'region'

    def short_name(self, obj):
        name = obj.title
        if obj.xml_id: name += " (#%s)" % obj.xml_id
        if len(name) > 25: name = "<span title='%s'>%s...</span>" % (name, name[:25])
        if obj.fields_for_moderation:
            active_moderations = filter(lambda moderation: not moderation.moderator_id, obj.moderations.all())
            if active_moderations:
                name += u'&nbsp;<a href="%s"><img src="%s" title="Модерация: %s"/></a>' % \
                        (reverse('moderation_detail', args=[active_moderations[0].id]), static('admin/img/icon-moderate.gif'),
                         obj.fields_for_moderation.replace("__all__", u"Новое"))
        return name
    short_name.allow_tags = True
    short_name.short_description = u"объявление"
    short_name.admin_order_field = 'title'
    
    def price_currency(self, obj):
        if obj.currency != 'UAH':
            return u'<acronym title="%s грн.">%s %s</acronym>' % (obj.price_uah, obj.price, obj.get_currency_display())
        else:
            return u'%s %s' % (obj.price, obj.get_currency_display())
    price_currency.allow_tags = True
    price_currency.short_description = u"Цена"
    price_currency.admin_order_field = 'price_uah'
    
    def add_date(self, obj):
        return obj.created.strftime('%d.%m.%y %H:%M')
    add_date.short_description = u"Добавлено"
    add_date.admin_order_field = 'created'

    def updated_date(self, obj):
        return obj.updated.strftime('%d.%m.%y %H:%M')
    updated_date.short_description = u"Обновлено"
    updated_date.admin_order_field = 'updated'

    def type(self,obj):
        return u'%s, %s' % (obj.get_deal_type_display(), obj.get_property_type_display())
    type.short_description = u"Тип"
    type.admin_order_field = 'deal_type'
    
    def user_link(self, obj):
        if obj.user:
            html = get_user_filter_link(obj.user)
            if obj.bank:
                url = reverse('admin:ad_ad_changelist') + '?bank_id=%d' % obj.bank_id
                html += u'<br/>банк: <a href="%s">%s</a>' % (url, obj.bank.name)
            return html
        else:
            if obj.source_url:
                o = urlparse(obj.source_url)
                return u'<nobr><a href="?source_url__icontains=%s" title="фильтровать по адресу сайта">%s %s</a></nobr>' % (o.netloc, icon_website, o.netloc)
            elif obj.content_provider:
                return obj.get_content_provider_display()

    user_link.allow_tags = True
    user_link.short_description = u"Источник/Юзер"
    user_link.admin_order_field = 'source_url'
    
    def item_images(self, obj):
        image_count = obj.photos.all().count()
        return u'<a href="%s?basead__exact=%d">%s шт.</a>' % (reverse('admin:ad_photo_changelist'), obj.pk, image_count)
    item_images.allow_tags = True
    item_images.short_description = u"Фото"

    def save_model(self, request, obj, form, change):
        if request.user.has_perm("%s.%s_%s" % ( 'ad', 'change', 'moderation')):
            # после сохранения в админке очищаются поля, требующие модерации
            obj.fields_for_moderation = None

            # ..., а так же закрываются заявки на модерацию
            update_fields = {'moderator':request.user, 'end_time':datetime.datetime.now()}
            if 'status' in obj.get_dirty_fields():
                update_fields['new_status'] = obj.status
            obj.moderations.filter(moderator__isnull=True).update(**update_fields)

        if obj.id is None and obj.user is None:
            obj.user = request.user

        super(AdAdmin, self).save_model(request, obj, form, change)

        if request.user.has_perm('ad.change_reserveddate') and getattr(form, 'update_m2m_reservations', False):
            obj.update_reserved_from_json(form.cleaned_data['reserved'])

    def get_urls(self):
        urls = super(AdAdmin, self).get_urls()
        return [
                   url(r'^stats_by_propertytype/$', admin_views.stats_by_propertytype),
                   url(r'^feed_sources/$', admin_views.feed_sources),
                   url(r'^duplicates/$', admin_views.show_photo_duplicates),
               ] + urls
Пример #7
0
class CustomUserAdmin(UserAdmin):
    list_display = (
        '__unicode__',
        'display_info',
        'id',
        'display_email',
        'display_phones',
        'display_is_active',
        'region',
        'display_ads_count',
        'display_date_joined',
        'display_last_action',
        'display_balance',
        'display_ban',
    )
    inlines = [PhoneInline]
    actions = [
        'move_to_managers', 'remove_from_managers', 'create_agency',
        'activate', 'deactivate', 'update_phones', 'give_leadgeneration_bonus'
    ]
    search_fields = ('id', 'agencies__name', 'first_name', 'last_name')
    list_filter = (ManagerFilter, RegionFilter, M2MPhoneFilter,
                   make_datetime_filter('date_joined'), 'is_active',
                   AgencyFilter, DeveloperFilter, NewPlanFilter,
                   make_datetime_filter('last_action'), LoyaltyFilter,
                   BanFilter, 'is_staff', 'is_superuser', IPAddressFilter,
                   BannedPhonesFilter, AdsSumFilter)
    show_full_result_count = False

    def get_search_results(self, request, queryset, search_term):
        queryset, use_distinct = super(CustomUserAdmin,
                                       self).get_search_results(
                                           request, queryset, search_term)
        filter = Q()
        for word in search_term.split():
            if '@' in word:
                filter.add(Q(email__iexact=word), Q.OR)
        if filter:
            queryset |= self.model.objects.filter(filter)
        return queryset, use_distinct

    def get_list_filter(self, request):
        list_filter = list(
            super(CustomUserAdmin, self).get_list_filter(request))
        if not request.user.groups.filter(name__icontains=u'комитет').exists():
            list_filter.insert(-1, TestPlanFilter)
        return list_filter

    def get_fieldsets(self, request, obj=None):
        fieldsets = list(
            super(CustomUserAdmin, self).get_fieldsets(request, obj))

        if not request.user.is_superuser:
            fieldsets.pop(2)  # поля с правами

        fieldsets.append((None, {
            'fields': ('manager', 'region', 'city', 'image', 'loyalty_started',
                       'show_email', 'show_message_button', 'subscribe_info',
                       'subscribe_news', 'receive_sms', 'language', 'gender',
                       'ip_addresses')
        }))

        return fieldsets

    def get_readonly_fields(self, request, obj=None):
        if request.user.is_superuser:
            readonly_fields = []
        else:
            readonly_fields = [
                'username', 'last_login', 'last_action', 'date_joined',
                'ads_count'
            ]
            if not request.user.groups.filter(id=12).exists():
                readonly_fields.append('manager')
        return readonly_fields

    def get_queryset(self, request):
        return super(CustomUserAdmin, self).get_queryset(request)\
            .prefetch_related('leadgeneration', 'developer', 'phones', 'realtors__agency', 'region', 'transactions',
                              'user_plans', 'activityperiods', 'bans', 'stat_set', 'social_auth')

    def lookup_allowed(self, key, value):
        if key in ('transactions__amount', ):
            return True
        return super(CustomUserAdmin, self).lookup_allowed(key, value)

    def get_actions(self, request):
        actions = super(CustomUserAdmin, self).get_actions(request)
        if not request.user.has_perm('ad.change_phoneinad'):
            del actions['update_phones']

        # group ID 12 - руководитель отдела менеджеров
        if not (request.user.is_superuser
                or request.user.groups.filter(id=12).exists()):
            if 'move_to_managers' in actions:
                del actions['move_to_managers']

            if 'remove_from_managers' in actions:
                del actions['remove_from_managers']

        return actions

    def display_email(self, obj):
        if obj.email:
            items = [obj.email]
        else:
            items = []

        website_icon = u'<img src="%s" alt=""/>' % static(
            'admin/img/icon-website.gif')
        for social in obj.social_auth.all():
            # TODO добавить гугл+
            link = None
            if social.provider == 'facebook':
                link = "http://facebook.com/%s" % social.uid
            elif social.provider in [
                    'vkontakte-oauth2', 'vkontakte', 'vk-oauth', 'vk-oauth2'
            ]:
                link = "http://vk.com/id%s" % social.uid
            elif social.provider == 'twitter':
                link = "https://twitter.com/intent/user?user_id=%s" % social.uid
            if link:
                items.append(u'<a href="%s" target="_blank">%s %s</a>' %
                             (link, website_icon, social.provider))

        return ' '.join(items)

    display_email.short_description = u'E-mail/соцсеть'
    display_email.allow_tags = True

    def display_phones(self, obj):
        return u'<br/>'.join([p.number for p in obj.phones.all()])

    display_phones.short_description = u'телефоны'
    display_phones.allow_tags = True

    def display_date_joined(self, obj):
        return (obj.date_joined.strftime('%d.%m.%Y')
                if obj.date_joined else None)

    display_date_joined.short_description = u'Регистрация'
    display_date_joined.admin_order_field = 'date_joined'

    def display_last_action(self, obj):
        return (obj.last_action.strftime('%d.%m.%Y')
                if obj.last_action else None)

    display_last_action.short_description = u'Активн.'
    display_last_action.admin_order_field = 'last_action'

    def display_ads_count(self, obj):
        result = u'<a href="%s?user__exact=%d">%s</a>' % (
            reverse('admin:ad_ad_changelist'), obj.id, obj.ads_count or '-')
        newhomes_amount = obj.newhomes.all().count() if obj.is_developer(
        ) else 0
        if newhomes_amount:
            result += u' / <a href="%s?user__exact=%d">%d</a>' % (reverse(
                'admin:newhome_newhome_changelist'), obj.id, newhomes_amount)
        return result

    display_ads_count.allow_tags = True
    display_ads_count.short_description = u'Объявл'
    display_ads_count.admin_order_field = 'ads_count'

    def display_is_active(self, obj):
        return obj.is_active

    display_is_active.boolean = True
    display_is_active.short_description = u'Акт'
    display_is_active.admin_order_field = 'is_active'

    def get_urls(self):
        urls = [
            url(r'^buy_plan/$',
                self.admin_site.admin_view(self.buy_plan),
                name="buy_plan"),
            url(r'^buy_vip/$',
                self.admin_site.admin_view(self.buy_vip),
                name="buy_vip"),
            url(r'^move_money/$',
                self.admin_site.admin_view(self.move_money),
                name="move_money"),
            url(r'^login_as/(?P<user_id>\d+)/$',
                self.admin_site.admin_view(self.login_as),
                name='login_as'),
            url(r'^(?P<user_id>.+)/info/$',
                self.admin_site.admin_view(self.info_view),
                name='custom_user_user_info')
        ]
        return urls + super(CustomUserAdmin, self).get_urls()

    def info_view(self, request, user_id):
        obj = User.objects.get(id=user_id)
        unexpired_plans = obj.get_unexpired_plans()
        prolonged_plans = unexpired_plans.exclude(is_active=True)
        leadgeneration = obj.get_leadgeneration()
        has_leadgeneration_ads = obj.has_active_leadgeneration('ads')
        recently_ppc_period = obj.activityperiods.filter(
            end__gt=datetime.datetime.now() -
            datetime.timedelta(days=7)).last()
        realtor = obj.get_realtor()

        if request.method == 'GET' and request.GET:
            # модераторы или руководитель отдела менеджеров
            if request.user.is_superuser or request.user.groups.filter(
                    id__in=[1, 12]).exists():
                if 'cancel_prolonged_plans' in request.GET:
                    if prolonged_plans:
                        for prolonged_plan in prolonged_plans:
                            prolonged_plan.cancel(request.user, 'full')
                    else:
                        raise Exception('No prolonged plans')
                elif 'set_ads_limit' in request.GET or 'cancel_dedicated_numbers' in request.GET:
                    if has_leadgeneration_ads:
                        if 'set_ads_limit' in request.GET:
                            leadgeneration.ads_limit = int(
                                request.GET['set_ads_limit'])
                        if 'cancel_dedicated_numbers' in request.GET:
                            # TODO: добавить related_name для corrected_transaction и заменить transaction__isnull на какой-нибудь corrections__isnull
                            for transaction in obj.transactions.filter(
                                    type=80,
                                    time__gt=datetime.datetime.now() -
                                    datetime.timedelta(days=3),
                                    transaction__isnull=True):
                                transaction.revert(
                                    comment=
                                    u'Возврат при отмене выделенного номера. Отменил пользователь #%d'
                                    % request.user.id)

                            leadgeneration.dedicated_numbers = False
                        leadgeneration.save()
                    else:
                        raise Exception('PPC for ads isn`t active')
                elif 'remove_from_agency' in request.GET:
                    if realtor:
                        if realtor.is_admin and realtor.agency.realtors.count(
                        ) == 1:
                            realtor.agency.delete()
                        else:
                            realtor.delete()
                    else:
                        raise Exception('Cannot remove user from agency')
                elif 'restore_ppc' in request.GET:
                    recently_ppc_period.end = None
                    recently_ppc_period.calls = 0
                    recently_ppc_period.requests = 0
                    recently_ppc_period.numbers = 0
                    recently_ppc_period.save()
                elif 'add_to_agency' in request.GET:
                    agency_admin = Realtor.objects.filter(
                        user__email=request.GET['add_to_agency'],
                        is_admin=True).first()
                    if agency_admin:
                        obj.realtors.all().delete()  # старые связи в печь
                        Realtor.objects.create(user=obj,
                                               agency=agency_admin.agency,
                                               is_active=True,
                                               is_admin=False)
                    else:
                        self.message_user(request,
                                          u'Агентство не найдено',
                                          level=messages.ERROR)
                elif 'move_ads_to_user' in request.GET:
                    new_user = User.objects.get(
                        email=request.GET['user_email'])
                    obj.ads.update(user=new_user)
                    # обновление счетчиков объявлений
                    for user in [obj, new_user]:
                        user.update_ads_count()
                elif 'change_manager' in request.GET:
                    new_manager = Manager.objects.get(
                        id=request.GET['manager_id'])
                    obj.manager_ptr.managed_users.update(manager=new_manager)
                elif 'remove_developer' in request.GET:
                    obj.developer.delete()

                return redirect(
                    reverse('admin:custom_user_user_info', args=[obj.id]))
            else:
                raise PermissionDenied
        else:
            context = self.admin_site.each_context(request)
            context.update(
                obj=obj,
                unexpired_plans=unexpired_plans,
                prolonged_plans=prolonged_plans,
                leadgeneration=leadgeneration,
                recently_ppc_period=recently_ppc_period,
                has_leadgeneration_ads=has_leadgeneration_ads,
                realtor=realtor,
                opts=User._meta,
                title=u'Информация о пользователе',
                has_change_permission=self.has_change_permission(request, obj),
                managers=Manager.objects.all(),
                managed_users_count=obj.manager_ptr.managed_users.count()
                if hasattr(obj, 'manager_ptr') else 0,
                all_ads_count=obj.ads.count())
            return render(request, 'admin/custom_user/user_info.html', context)

    def display_info(self, obj):
        result = u''

        result += u'<a title="Информация о пользователе" href="%s"><img src="%s"/></a> ' % (
            reverse('admin:custom_user_user_info',
                    args=[obj.id]), static('admin/img/icon-info.png'))

        if obj.stat_set.exists():
            result += u'<a title="Показать статистику пользователя" href="%s?user__exact=%d"><img src="%s"/></a> ' % (
                reverse('admin:profile_statgrouped_changelist'), obj.id,
                static('admin/img/icon-stats.gif'))

        for realtor in obj.realtors.all():
            result += u'<a href="%s?id=%d" title="%s"%s><img src="%s"/></a> ' % \
                      (reverse('admin:agency_agency_changelist'), realtor.agency_id, realtor.agency.name,
                       ' style="opacity:0.3"' if not realtor.is_active else '',
                       static('admin/img/icon-agency.gif') if realtor.is_admin else static('admin/img/icon-user.gif'))

            if realtor.is_admin and realtor.agency.import_url:
                result += u'<a title="Показать статистику импорта" href="%s?agency=%d"><img src="%s"/></a> ' % (
                    reverse('admin:import__importtask_changelist'),
                    realtor.agency.id, static('admin/img/icon-feed.png'))

        if hasattr(obj, 'developer'):
            result += u'<a href="%s?user_id=%d" title="%s"><img src="%s"/></a> ' % \
                      (reverse('admin:newhome_developer_changelist'), obj.id, obj.developer.name,
                       static('admin/img/icon-developer.gif'))

        active_plan = obj.get_active_plan_using_prefetch()
        if active_plan:
            result += u'<a href="{}?id={}" title="{}"><img src="{}" style="background-color:{}"/></a> '.format(
                reverse('admin:paid_services_userplan_changelist'),
                active_plan.id,
                u'Тариф до {:%d.%m.%Y}. Лимит объявлений - {}'.format(
                    active_plan.end, active_plan.ads_limit),
                static('admin/img/icon-dollar.png'), '#ecb310')

        active_leadgeneration = obj.has_active_leadgeneration()
        if active_leadgeneration:
            active_for = filter(None, [
                u'объявлений' if 'ads' in active_leadgeneration else '',
                u'новостроек' if 'newhomes' in active_leadgeneration else ''
            ])
            result += u'<a href="{}?id={}" title="включена для {}"><img src="{}" style="background-color:{}"/></a> '.format(
                reverse('admin:ppc_leadgeneration_changelist'),
                obj.leadgeneration.id, u' и '.join(active_for),
                static('admin/img/icon-dollar.png'), '#31c500')

        if not obj.is_staff and obj.is_active:
            result += u'<a title="Войти под этим пользователем" href="%s" onClick="return confirm(\'%s\')"><img src="%s" style="opacity:0.3"/></a> ' % (
                reverse('admin:login_as', args=[obj.id]),
                u'ВНИМАНИЕ! Произойдет выход из текущего аккаунта.         '
                u'Рекомендуется открывать ссылку в режиме инкогнито с последующим повторным вводом вашего логина/пароля.',
                static('admin/img/icon-login.svg'))

        return result

    display_info.allow_tags = True
    display_info.short_description = u'Инфо'

    def display_ban(self, obj):
        if obj.id in get_banned_users():
            sorted_bans = sorted(obj.bans.all(), key=lambda v: v.expire_date)
            return u'до %s' % sorted_bans[-1].expire_date.strftime('%d.%m.%Y')
        else:
            return u'<a href="%s?user=%d" title="Отправить в бан"><img src="%s" alt=""/></a>' % (
                reverse('admin:profile_ban_add'),
                obj.id,
                static('admin/img/icon-ban.png'),
            )

    display_ban.short_description = u'Бан'
    display_ban.allow_tags = True

    def display_balance(self, obj):
        # попытка использовать join с таблицей транзакций и sum кладет базу, поэтому так
        balance = int(sum([t.amount for t in obj.transactions.all()]))
        return u'<a title="Показать транзакции пользователя" href="%s?user__exact=%d">%s</a>' % (
            reverse('admin:paid_services_transaction_changelist'), obj.id,
            balance)

    display_balance.allow_tags = True
    display_balance.short_description = u'Баланс'

    def display_plans(self, obj):
        active_plan = obj.get_active_plan_using_prefetch()
        if active_plan:
            return u'<a title="Показать планы пользователя" href="%s?user__exact=%d">до %s</a>' % (
                reverse('admin:paid_services_userplan_changelist'), obj.id,
                active_plan.end.strftime('%Y-%m-%d'))
        return ''

    display_plans.allow_tags = True
    display_plans.short_description = u'План'

    @transaction.atomic
    def move_to_managers(self, request, queryset):
        moved = []
        for user in queryset:
            user_str = user.email or unicode(user)
            if hasattr(user, 'manager_ptr'):
                self.message_user(
                    request,
                    u'Ошибка: пользователь %s уже является менеджером' %
                    user_str,
                    level=messages.ERROR)
                return
            else:
                Manager.create_from_user(user)
                user.is_staff = True
                user.save()
                user.groups.add(Group.objects.get(id=2))
                moved.append(user_str)
        self.message_user(request,
                          u'Переведены в менеджеры: %s' % u', '.join(moved),
                          level=messages.WARNING)

    move_to_managers.short_description = u'Перевести в менеджеры'

    @transaction.atomic
    def remove_from_managers(self, request, queryset):
        removed = []
        for user in queryset:
            user_str = user.email or unicode(user)
            if hasattr(user, 'manager_ptr'):
                # запрет удаления из менеджеров, если у менеджера есть пользователи
                # внимание! если захочется все равно удалять, то перед удалением нужно разорвать связи - manager_ptr.managed_users.update(manager=None),
                # иначе из базы вместе с менеджером удалятся все его пользователи (из-за on_delete)
                if user.manager_ptr.managed_users.exists():
                    self.message_user(
                        request,
                        u'Ошибка: невозможно удалить менеджера %s - у него есть пользователи'
                        % user_str,
                        level=messages.ERROR)
                    return
                else:
                    user.manager_ptr.delete(keep_parents=True)

                user.is_staff = False
                user.save()
                user.groups.remove(Group.objects.get(id=2))
                removed.append(user_str)
            else:
                self.message_user(
                    request,
                    u'Ошибка: пользователь %s не является менеджером' %
                    user_str,
                    level=messages.ERROR)
                return
        self.message_user(request,
                          u'Удалены из менеджеров: %s' % u', '.join(removed),
                          level=messages.WARNING)

    remove_from_managers.short_description = u'Удалить из менеджеров'

    @transaction.atomic
    def create_agency(self, request, queryset):
        for user in queryset:
            user.create_agency()
        self.message_user(request,
                          u'Созданы агентства для пользователей: %s' %
                          [unicode(user) for user in queryset],
                          level=messages.INFO)

    create_agency.short_description = u'Создать агентство'

    def activate(self, request, queryset):
        for user in queryset:
            user.is_active = True
            user.save()

    activate.short_description = u'Активировать'

    def update_phones(self, request, queryset):
        for user in queryset:
            numbers = user.phones.order_by('users_m2m').values_list('number',
                                                                    flat=True)
            user.update_ads_phones(numbers)

    update_phones.short_description = u'Заменить телефоны в объявлениях телефонами из профиля'

    def deactivate(self, request, queryset):
        for user in queryset:
            user.is_active = False
            user.save()

    deactivate.short_description = u'Деактивировать'

    def give_leadgeneration_bonus(self, request, queryset):
        from ppc.models import LeadGeneration, Bonus, ActivityPeriod
        for user in queryset:
            leadgeneration, created = LeadGeneration.objects.get_or_create(
                user=user)
            leadgeneration.is_active_ads = True
            leadgeneration.weekdays = []
            leadgeneration.save()

            bonus = Bonus.objects.create(user=user,
                                         start=datetime.datetime.now())
            ActivityPeriod.objects.get_or_create(user=user,
                                                 end=None,
                                                 lead_type='ads')

    give_leadgeneration_bonus.short_description = u'Включить лидогенерацию (объявл.) с 10 бесплатными звонками/лидами'

    def login_as(self, request, user_id=None):
        from django.contrib.auth import login, logout
        user = User.objects.get(pk=user_id)
        if request.user.is_superuser or (
                not user.is_staff
                and request.user.groups.filter(id__in=[1, 2, 12]).exists()):
            logout(request)
            user.backend = 'django.contrib.auth.backends.ModelBackend'
            login(request, user)
            return redirect('/')
        else:
            self.message_user(request,
                              u'Недостаточно прав.',
                              level=messages.ERROR)
            return redirect(
                request.META.get('HTTP_REFERER', '/admin/custom_user/user/'))

    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())

    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())

    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())
Пример #8
0
class VipPlacementAdmin(ReadOnlyModelAdmin):
    raw_id_fields = ('transaction', 'basead')
    list_display = ('id', 'user_link', 'property_link', 'days', 'since', 'until', 'transaction_link', 'is_active')
    list_filter = (make_datetime_filter('since'), make_datetime_filter('until'))
    actions = ('cancel',)

    def is_active(self, obj):
        return obj.is_active
    is_active.boolean = True

    def get_actions(self, request):
        actions = super(VipPlacementAdmin, self).get_actions(request)
        if not request.user.has_perm('paid_services.cancel_vipplacement'):
            del actions['cancel']
        return actions

    def get_queryset(self, request):
        qs = super(VipPlacementAdmin, self).get_queryset(request)
        return qs.prefetch_related('basead', 'basead__ad__user', 'basead__ad__user__realtors__agency', 'transaction')

    def user_link(self, obj):
        if obj.basead_id:
            return get_user_filter_link(obj.basead.ad.user, lookup='basead__ad__user__exact')
        else:
            return u'нет объявления'
    user_link.allow_tags = True
    user_link.short_description = u"Пользователь"
    user_link.admin_order_field = 'ad__user'

    def transaction_link(self, obj):
        return u'<a href="%s">#%s</a>' % (
        reverse('admin:paid_services_transaction_change', args=[obj.transaction_id]), obj.transaction_id)
    transaction_link.allow_tags = True
    transaction_link.short_description = u'транзакция'

    def lookup_allowed(self, key, value):
        if key in ('basead__ad__user', 'basead__ad__user__exact'):
            return True
        return super(VipPlacementAdmin, self).lookup_allowed(key, value)

    def property_link(self, obj):
        if obj.basead:
            return u'<a href="%s">#%s</a>' % (reverse('admin:ad_ad_change', args=[obj.basead_id]), obj.basead_id)
        else:
            return u'нет объявления'
    property_link.allow_tags = True
    property_link.short_description = u"Объявление"
    property_link.admin_order_field = 'ad'

    def cancel(self, request, queryset):
        cancelled = []
        errors = []
        for vip_placement in queryset.all():
            if datetime.datetime.now() < vip_placement.until:
                vip_placement.cancel(request.user)
                cancelled.append('#%d' % vip_placement.id)
            else:
                errors.append('#%d' % vip_placement.id)
        message = u'Отменено %d платных размещений %s' % (len(cancelled), ', '.join(cancelled))
        if errors:
            message += u', невозможно отменить %d платных размещений %s (уже закончились)' % (
                len(errors),
                ', '.join(errors)
            )
        self.message_user(request, message)
    cancel.short_description = u'Отмена платного размещения, возврат полной суммы на баланс'
Пример #9
0
class TransactionAdmin(admin.ModelAdmin):
    raw_id_fields = ('user', 'order', 'user_plan', 'corrected_transaction')
    list_display = ('id', 'time', 'user_link', 'amount', 'display_type', 'purchased', 'display_order', 'comment')
    list_display_links = ['id']
    readonly_fields = ('user', 'type', 'amount', 'time')
    list_filter = (ManagerFilter, TypeFilter, RevertTypeFilter, make_datetime_filter('time'), UserFilter, PlanFilter, RegionFilter, MoneySumFilter)
    actions = ('cancel',)

    def cancel(self, request, queryset):
        for transaction in queryset:
            if transaction.type == 11:
                transaction.user_plan.cancel(request.user)
            elif transaction.type in [53,54,55]:
                for placement in list(obj.vipplacements.all()) + list(obj.catalogplacements.all()):
                    placement.cancel(request.user)
            elif transaction.type in [84,85]:
                for call in transaction.paidcalls.all():
                    call.cancel(request.user)
            else:
                transaction.revert(comment=u'транзакция отменена %s' % request.user)
    cancel.short_description = u'Вернуть деньги'

    def get_readonly_fields(self, request, obj=None):
        if request.user.is_superuser:
            return []
        else:
            return super(TransactionAdmin, self).get_readonly_fields(request, obj)

    def get_queryset(self, request):
        qs = super(TransactionAdmin, self).get_queryset(request)
        return qs.prefetch_related('vipplacements', 'catalogplacements', 'order', 'user_plan', 'user', 'user__realtors__agency')

    def user_link(self, obj):
        return get_user_filter_link(obj.user)
    user_link.allow_tags = True
    user_link.short_description = u'пользователь'

    def display_type(self, obj):
        if obj.type == 100 and obj.corrected_transaction:
            return u'%s (коррекция)' % (obj.corrected_transaction.get_type_display())
        else:
            return obj.get_type_display()
    display_type.admin_order_field = 'type'
    display_type.short_description = u'тип'

    def purchased(self, obj):
        links = []
        related = list(obj.vipplacements.all()) + list(obj.catalogplacements.all())
        if obj.user_plan:
            related.append(obj.user_plan)

        for rel in related:
            url = reverse(
                'admin:paid_services_%s_changelist' % rel._meta.model_name) + '?id=%s' % rel.id
            links.append(u'<a href="%s">%s #%s</a>' % (url, rel._meta.verbose_name, rel.id))
        return u', '.join(links)

    purchased.allow_tags = True
    purchased.short_description = u'покупки'

    def display_order(self, obj):
        if obj.order:
            return '<a href="%s?id=%d">%d</a>' % (reverse('admin:paid_services_order_changelist'), obj.order_id, obj.order_id)
        else:
            return ''
    display_order.allow_tags = True
    display_order.short_description = u'заказ'