Merge branch 'miurahr-admin_sponsor_benefit'
This commit is contained in:
commit
eff643e1bb
3 changed files with 140 additions and 11 deletions
|
@ -1,12 +1,18 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.utils.html import escape
|
from django.utils.html import escape
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from symposion.sponsorship.models import SponsorLevel, Sponsor, Benefit, BenefitLevel, \
|
from symposion.sponsorship.models import (
|
||||||
SponsorBenefit
|
Benefit,
|
||||||
|
BENEFITS,
|
||||||
|
BenefitLevel,
|
||||||
|
Sponsor,
|
||||||
|
SponsorBenefit,
|
||||||
|
SponsorLevel,
|
||||||
|
)
|
||||||
|
|
||||||
class BenefitLevelInline(admin.TabularInline):
|
class BenefitLevelInline(admin.TabularInline):
|
||||||
model = BenefitLevel
|
model = BenefitLevel
|
||||||
|
@ -47,6 +53,7 @@ class SponsorAdmin(admin.ModelAdmin):
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
inlines = [SponsorBenefitInline]
|
inlines = [SponsorBenefitInline]
|
||||||
|
list_filter = ["level", "active"]
|
||||||
list_display = ["name", "external_url", "level", "active", "contact", "applicant_field"]
|
list_display = ["name", "external_url", "level", "active", "contact", "applicant_field"]
|
||||||
|
|
||||||
def contact(self, sponsor):
|
def contact(self, sponsor):
|
||||||
|
@ -62,24 +69,60 @@ class SponsorAdmin(admin.ModelAdmin):
|
||||||
# @@@ kinda ugly but using choices= on NullBooleanField is broken
|
# @@@ kinda ugly but using choices= on NullBooleanField is broken
|
||||||
form = super(SponsorAdmin, self).get_form(*args, **kwargs)
|
form = super(SponsorAdmin, self).get_form(*args, **kwargs)
|
||||||
form.base_fields["active"].widget.choices = [
|
form.base_fields["active"].widget.choices = [
|
||||||
(u"1", "unreviewed"),
|
(u"1", _("unreviewed")),
|
||||||
(u"2", "approved"),
|
(u"2", _("approved")),
|
||||||
(u"3", "rejected")
|
(u"3", _("rejected"))
|
||||||
]
|
]
|
||||||
return form
|
return form
|
||||||
|
|
||||||
|
# Define accessor functions for our benefit fields and add them to
|
||||||
|
# list_display, so we can sort on them and give them sensible names.
|
||||||
|
# Add the fields to list_filters while we're at it.
|
||||||
|
for benefit in BENEFITS:
|
||||||
|
benefit_name = benefit['name']
|
||||||
|
field_name = benefit['field_name']
|
||||||
|
|
||||||
|
def func_generator(ben):
|
||||||
|
def column_func(obj):
|
||||||
|
return getattr(obj, ben['field_name'])
|
||||||
|
column_func.short_description = ben['column_title']
|
||||||
|
column_func.boolean = True
|
||||||
|
column_func.admin_order_field = ben['field_name']
|
||||||
|
return column_func
|
||||||
|
list_display.append(func_generator(benefit))
|
||||||
|
list_filter.append(field_name)
|
||||||
|
|
||||||
|
def save_related(self, request, form, formsets, change):
|
||||||
|
super(SponsorAdmin, self).save_related(request, form, formsets, change)
|
||||||
|
obj = form.instance
|
||||||
|
obj.save()
|
||||||
|
|
||||||
|
|
||||||
class BenefitAdmin(admin.ModelAdmin):
|
class BenefitAdmin(admin.ModelAdmin):
|
||||||
|
|
||||||
list_display = ["name", "type", "description"]
|
list_display = ["name", "type", "description", "levels"]
|
||||||
inlines = [BenefitLevelInline]
|
inlines = [BenefitLevelInline]
|
||||||
|
|
||||||
|
def levels(self, benefit):
|
||||||
|
return u", ".join(l.level.name for l in benefit.benefit_levels.all())
|
||||||
|
|
||||||
|
|
||||||
class SponsorLevelAdmin(admin.ModelAdmin):
|
class SponsorLevelAdmin(admin.ModelAdmin):
|
||||||
|
|
||||||
inlines = [BenefitLevelInline]
|
inlines = [BenefitLevelInline]
|
||||||
|
|
||||||
|
|
||||||
|
class SponsorBenefitAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ('benefit', 'sponsor', 'active', '_is_complete', 'show_text')
|
||||||
|
|
||||||
|
def show_text(self, sponsor_benefit):
|
||||||
|
if sponsor_benefit.text:
|
||||||
|
return sponsor_benefit.text[:100]
|
||||||
|
else:
|
||||||
|
return _("None")
|
||||||
|
|
||||||
|
|
||||||
admin.site.register(SponsorLevel, SponsorLevelAdmin)
|
admin.site.register(SponsorLevel, SponsorLevelAdmin)
|
||||||
admin.site.register(Sponsor, SponsorAdmin)
|
admin.site.register(Sponsor, SponsorAdmin)
|
||||||
admin.site.register(Benefit, BenefitAdmin)
|
admin.site.register(Benefit, BenefitAdmin)
|
||||||
|
admin.site.register(SponsorBenefit, SponsorBenefitAdmin)
|
||||||
|
|
|
@ -48,6 +48,9 @@ class SponsorDetailsForm(forms.ModelForm):
|
||||||
|
|
||||||
|
|
||||||
class SponsorBenefitsInlineFormSet(BaseInlineFormSet):
|
class SponsorBenefitsInlineFormSet(BaseInlineFormSet):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
kwargs['queryset'] = kwargs.get('queryset', self.model._default_manager).exclude(benefit__type="option")
|
||||||
|
super(SponsorBenefitsInlineFormSet, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
def _construct_form(self, i, **kwargs):
|
def _construct_form(self, i, **kwargs):
|
||||||
form = super(SponsorBenefitsInlineFormSet, self)._construct_form(i, **kwargs)
|
form = super(SponsorBenefitsInlineFormSet, self)._construct_form(i, **kwargs)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -12,10 +13,38 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
from symposion.conference.models import Conference
|
from symposion.conference.models import Conference
|
||||||
|
|
||||||
from symposion.sponsorship.managers import SponsorManager
|
from symposion.sponsorship.managers import SponsorManager
|
||||||
|
|
||||||
|
|
||||||
|
# The benefits we track as individual fields on sponsors
|
||||||
|
# Names are the names in the database as defined by organizers.
|
||||||
|
# Field names are the benefit names, lowercased, with
|
||||||
|
# spaces changed to _, and with "_benefit" appended.
|
||||||
|
# Column titles are arbitrary.
|
||||||
|
|
||||||
|
# "really just care about the ones we have today: print logo, web logo, print description, web description and the ad."
|
||||||
|
|
||||||
|
BENEFITS = [
|
||||||
|
{
|
||||||
|
'name': 'Web logo',
|
||||||
|
'field_name': 'web_logo_benefit',
|
||||||
|
'column_title': _(u"Web Logo"),
|
||||||
|
}, {
|
||||||
|
'name': 'Print logo',
|
||||||
|
'field_name': 'print_logo_benefit',
|
||||||
|
'column_title': _(u"Print Logo"),
|
||||||
|
}, {
|
||||||
|
'name': 'Company Description',
|
||||||
|
'field_name': 'company_description_benefit',
|
||||||
|
'column_title': _(u"Web Desc"),
|
||||||
|
}, {
|
||||||
|
'name': 'Print Description',
|
||||||
|
'field_name': 'print_description_benefit',
|
||||||
|
'column_title': _(u"Print Desc"),
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
@python_2_unicode_compatible
|
||||||
class SponsorLevel(models.Model):
|
class SponsorLevel(models.Model):
|
||||||
|
|
||||||
|
@ -31,7 +60,7 @@ class SponsorLevel(models.Model):
|
||||||
verbose_name_plural = _("sponsor levels")
|
verbose_name_plural = _("sponsor levels")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return "%s %s" % (self.conference, self.name)
|
||||||
|
|
||||||
def sponsors(self):
|
def sponsors(self):
|
||||||
return self.sponsor_set.filter(active=True).order_by("added")
|
return self.sponsor_set.filter(active=True).order_by("added")
|
||||||
|
@ -57,6 +86,13 @@ class Sponsor(models.Model):
|
||||||
sponsor_logo = models.ForeignKey("SponsorBenefit", related_name="+", null=True, blank=True,
|
sponsor_logo = models.ForeignKey("SponsorBenefit", related_name="+", null=True, blank=True,
|
||||||
editable=False)
|
editable=False)
|
||||||
|
|
||||||
|
# Whether things are complete
|
||||||
|
# True = complete, False = incomplate, Null = n/a for this sponsor level
|
||||||
|
web_logo_benefit = models.NullBooleanField(_("Web logo benefit"), help_text=_(u"Web logo benefit is complete"))
|
||||||
|
print_logo_benefit = models.NullBooleanField(_("Print logo benefit"), help_text=_(u"Print logo benefit is complete"))
|
||||||
|
print_description_benefit = models.NullBooleanField(_("Print description benefit"), help_text=_(u"Print description benefit is complete"))
|
||||||
|
company_description_benefit = models.NullBooleanField(_("Company description benefit"), help_text=_(u"Company description benefit is complete"))
|
||||||
|
|
||||||
objects = SponsorManager()
|
objects = SponsorManager()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -65,6 +101,15 @@ class Sponsor(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("sponsor")
|
verbose_name = _("sponsor")
|
||||||
verbose_name_plural = _("sponsors")
|
verbose_name_plural = _("sponsors")
|
||||||
|
ordering = ['name']
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
# Set fields related to benefits being complete
|
||||||
|
for benefit in BENEFITS:
|
||||||
|
field_name = benefit['field_name']
|
||||||
|
benefit_name = benefit['name']
|
||||||
|
setattr(self, field_name, self.benefit_is_complete(benefit_name))
|
||||||
|
super(Sponsor, self).save(*args, **kwargs)
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
if self.active:
|
if self.active:
|
||||||
|
@ -141,6 +186,19 @@ class Sponsor(models.Model):
|
||||||
def send_coordinator_emails(self):
|
def send_coordinator_emails(self):
|
||||||
pass # @@@ should this just be done centrally?
|
pass # @@@ should this just be done centrally?
|
||||||
|
|
||||||
|
def benefit_is_complete(self, name):
|
||||||
|
"""Return True - benefit is complete, False - benefit is not complete,
|
||||||
|
or None - benefit not applicable for this sponsor's level """
|
||||||
|
if BenefitLevel.objects.filter(level=self.level, benefit__name=name).exists():
|
||||||
|
try:
|
||||||
|
benefit = self.sponsor_benefits.get(benefit__name=name)
|
||||||
|
except SponsorBenefit.DoesNotExist:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return benefit.is_complete
|
||||||
|
else:
|
||||||
|
return None # Not an applicable benefit for this sponsor's level
|
||||||
|
|
||||||
|
|
||||||
def _store_initial_level(sender, instance, **kwargs):
|
def _store_initial_level(sender, instance, **kwargs):
|
||||||
if instance:
|
if instance:
|
||||||
|
@ -217,11 +275,22 @@ class SponsorBenefit(models.Model):
|
||||||
text = models.TextField(_("text"), blank=True)
|
text = models.TextField(_("text"), blank=True)
|
||||||
upload = models.FileField(_("file"), blank=True, upload_to="sponsor_files")
|
upload = models.FileField(_("file"), blank=True, upload_to="sponsor_files")
|
||||||
|
|
||||||
|
# Whether any assets required from the sponsor have been provided
|
||||||
|
# (e.g. a logo file for a Web logo benefit).
|
||||||
|
is_complete = models.NullBooleanField(_("Complete?"), help_text=_(u"True - benefit complete; False - benefit incomplete; Null - n/a"))
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ["-active"]
|
ordering = ["-active"]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s - %s" % (self.sponsor, self.benefit)
|
return "%s - %s (%s)" % (self.sponsor, self.benefit, self.benefit_type)
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
# Validate - save() doesn't clean your model by default, so call
|
||||||
|
# it explicitly before saving
|
||||||
|
self.full_clean()
|
||||||
|
self.is_complete = self._is_complete()
|
||||||
|
super(SponsorBenefit, self).save(*args, **kwargs)
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
num_words = len(self.text.split())
|
num_words = len(self.text.split())
|
||||||
|
@ -237,6 +306,20 @@ class SponsorBenefit(models.Model):
|
||||||
"""
|
"""
|
||||||
if self.benefit.type == "file" or self.benefit.type == "weblogo":
|
if self.benefit.type == "file" or self.benefit.type == "weblogo":
|
||||||
return ["upload"]
|
return ["upload"]
|
||||||
elif self.benefit.type == "text":
|
elif self.benefit.type in ("text", "richtext", "simple", "option"):
|
||||||
return ["text"]
|
return ["text"]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
def _is_complete(self):
|
||||||
|
return self.active and \
|
||||||
|
((self.benefit.type in ('text', 'richtext', 'simple') and bool(self.text))
|
||||||
|
or (self.benefit.type in ('file', 'weblogo') and bool(self.upload)))
|
||||||
|
|
||||||
|
|
||||||
|
def _denorm_weblogo(sender, instance, created, **kwargs):
|
||||||
|
if instance:
|
||||||
|
if instance.benefit.type == "weblogo" and instance.upload:
|
||||||
|
sponsor = instance.sponsor
|
||||||
|
sponsor.sponsor_logo = instance
|
||||||
|
sponsor.save()
|
||||||
|
post_save.connect(_denorm_weblogo, sender=SponsorBenefit)
|
||||||
|
|
Loading…
Reference in a new issue