Source code for django_program.sponsors.models

"""Sponsor level, sponsor, and benefit models for django-program."""

from django.conf import settings
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.text import slugify

from django_program.pretalx.models import AbstractOverride


[docs] class SponsorLevel(models.Model): """A sponsorship tier for a conference. Defines a named tier (e.g. "Gold", "Silver", "Bronze") with pricing, a description of included benefits, and the number of complimentary tickets that sponsors at this level receive automatically. """ conference = models.ForeignKey( "program_conference.Conference", on_delete=models.CASCADE, related_name="sponsor_levels", ) name = models.CharField(max_length=200) slug = models.SlugField(max_length=200, blank=True) cost = models.DecimalField(max_digits=10, decimal_places=2) description = models.TextField(blank=True, default="") benefits_summary = models.TextField( blank=True, default="", help_text="Plain text summary of benefits for this level.", ) comp_ticket_count = models.PositiveIntegerField( default=0, help_text="Number of complimentary tickets to auto-generate for sponsors at this level.", ) order = models.PositiveIntegerField(default=0) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: ordering = ["order", "name"] unique_together = [("conference", "slug")] def __str__(self) -> str: return f"{self.name} ({self.conference.slug})"
[docs] def save(self, *args: object, **kwargs: object) -> None: """Auto-generate slug from name if not set.""" if not self.slug: self.slug = slugify(self.name) super().save(*args, **kwargs)
[docs] class SponsorOverride(AbstractOverride): """Local override applied on top of sponsor data. Allows conference organizers to patch individual fields of a sponsor without modifying the original record. Inherits ``save()``/``clean()`` conference auto-set and validation from ``AbstractOverride``. """ _parent_field = "sponsor" conference = models.ForeignKey( "program_conference.Conference", on_delete=models.CASCADE, related_name="sponsor_overrides", ) created_by = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True, related_name="created_sponsor_overrides", ) sponsor = models.OneToOneField( Sponsor, on_delete=models.CASCADE, related_name="override", ) override_name = models.CharField( max_length=200, blank=True, default="", help_text="Override the sponsor name.", ) override_description = models.TextField( blank=True, default="", help_text="Override the sponsor description.", ) override_website_url = models.URLField( blank=True, default="", help_text="Override the sponsor website URL.", ) override_logo_url = models.URLField( blank=True, default="", help_text="Override the sponsor logo URL.", ) override_contact_name = models.CharField( max_length=200, blank=True, default="", help_text="Override the sponsor contact name.", ) override_contact_email = models.EmailField( blank=True, default="", help_text="Override the sponsor contact email.", ) override_is_active = models.BooleanField( null=True, blank=True, default=None, help_text="Override the sponsor active status. Leave blank for no override.", ) override_level = models.ForeignKey( SponsorLevel, on_delete=models.SET_NULL, null=True, blank=True, related_name="sponsor_overrides", help_text="Override the sponsor level.", ) def __str__(self) -> str: level_name = self.sponsor.level.name if self.sponsor.level_id else "Unknown" return f"Override: {self.sponsor.name} ({level_name})" @property def is_empty(self) -> bool: """Return True when no override fields carry a value.""" return ( not self.override_name and not self.override_description and not self.override_website_url and not self.override_logo_url and not self.override_contact_name and not self.override_contact_email and self.override_is_active is None and not self.override_level_id )
[docs] class SponsorBenefit(models.Model): """A specific benefit tracked for a sponsor. Tracks individual deliverables owed to a sponsor as part of their sponsorship package (e.g. "Logo on website", "Booth space"). The ``is_complete`` flag marks whether the benefit has been fulfilled. """ sponsor = models.ForeignKey( Sponsor, on_delete=models.CASCADE, related_name="benefits", ) name = models.CharField(max_length=200) description = models.TextField(blank=True, default="") is_complete = models.BooleanField(default=False) notes = models.TextField(blank=True, default="") created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: ordering = ["name"] def __str__(self) -> str: return f"{self.name} - {self.sponsor.name}"