68 lines
2.6 KiB
Python
68 lines
2.6 KiB
Python
from django.conf import settings
|
|
from django.db import models
|
|
from django.db.models import Q
|
|
|
|
|
|
class ListingClick(models.Model):
|
|
"""Server-side record of a public listing detail view with optional UTM / ad parameters."""
|
|
|
|
class ListingType(models.TextChoices):
|
|
EQUIPMENT = "equipment", "Equipment"
|
|
ADVENTURE = "adventure", "Adventure"
|
|
|
|
class TrafficType(models.TextChoices):
|
|
ORGANIC = "organic", "Organic"
|
|
MARKETING = "marketing", "Marketing"
|
|
|
|
vendor = models.ForeignKey("accounts.VendorProfile", on_delete=models.CASCADE, related_name="listing_clicks")
|
|
listing_type = models.CharField(max_length=16, choices=ListingType.choices)
|
|
equipment_item = models.ForeignKey(
|
|
"equipment.EquipmentItem",
|
|
on_delete=models.CASCADE,
|
|
null=True,
|
|
blank=True,
|
|
related_name="marketing_clicks",
|
|
)
|
|
adventure_offering = models.ForeignKey(
|
|
"adventrues.AdventureOffering",
|
|
on_delete=models.CASCADE,
|
|
null=True,
|
|
blank=True,
|
|
related_name="marketing_clicks",
|
|
)
|
|
traffic_type = models.CharField(max_length=16, choices=TrafficType.choices)
|
|
utm_source = models.CharField(max_length=255, blank=True)
|
|
utm_medium = models.CharField(max_length=255, blank=True)
|
|
utm_campaign = models.CharField(max_length=255, blank=True)
|
|
utm_term = models.CharField(max_length=255, blank=True)
|
|
utm_content = models.CharField(max_length=255, blank=True)
|
|
gclid = models.CharField(max_length=255, blank=True)
|
|
fbclid = models.CharField(max_length=255, blank=True)
|
|
referrer = models.TextField(blank=True)
|
|
user = models.ForeignKey(
|
|
settings.AUTH_USER_MODEL,
|
|
on_delete=models.SET_NULL,
|
|
null=True,
|
|
blank=True,
|
|
related_name="listing_clicks",
|
|
)
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|
|
|
class Meta:
|
|
ordering = ("-created_at",)
|
|
indexes = [
|
|
models.Index(fields=["vendor", "created_at"]),
|
|
models.Index(fields=["vendor", "traffic_type", "created_at"]),
|
|
models.Index(fields=["utm_campaign", "created_at"]),
|
|
]
|
|
constraints = [
|
|
models.CheckConstraint(
|
|
condition=Q(listing_type="equipment", equipment_item__isnull=False, adventure_offering__isnull=True)
|
|
| Q(listing_type="adventure", equipment_item__isnull=True, adventure_offering__isnull=False),
|
|
name="listing_click_exactly_one_listing",
|
|
),
|
|
]
|
|
|
|
def __str__(self) -> str:
|
|
return f"ListingClick #{self.pk} ({self.listing_type}, {self.traffic_type})"
|