from django.db import models class OutboundEndpoint(models.Model): name = models.CharField(max_length=255) url = models.URLField(max_length=1000) secret = models.CharField(max_length=500) is_active = models.BooleanField(default=True) retry_policy = models.JSONField(default=dict, blank=True) headers = models.JSONField(default=dict, blank=True) timeout_seconds = models.PositiveIntegerField(default=30) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: db_table = "webhooks_outbound_endpoint" def __str__(self): return self.name class OutboundSubscription(models.Model): endpoint = models.ForeignKey(OutboundEndpoint, on_delete=models.CASCADE, related_name="subscriptions") event_name = models.CharField(max_length=255, db_index=True) is_active = models.BooleanField(default=True) payload_template = models.TextField(blank=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: db_table = "webhooks_outbound_subscription" unique_together = [("endpoint", "event_name")] def __str__(self): return f"{self.endpoint.name} / {self.event_name}" class OutboundDelivery(models.Model): class Status(models.TextChoices): SUCCESS = "success", "Success" FAILED = "failed", "Failed" RETRYING = "retrying", "Retrying" subscription = models.ForeignKey(OutboundSubscription, on_delete=models.CASCADE, related_name="deliveries") payload = models.JSONField() response_status = models.PositiveSmallIntegerField(null=True, blank=True) response_body = models.TextField(blank=True) attempt = models.PositiveIntegerField(default=0) status = models.CharField(max_length=20, choices=Status.choices, default=Status.RETRYING) next_retry_at = models.DateTimeField(null=True, blank=True) created_at = models.DateTimeField(auto_now_add=True) completed_at = models.DateTimeField(null=True, blank=True) class Meta: db_table = "webhooks_outbound_delivery" def __str__(self): return f"Delivery {self.id} — {self.status}" class InboundEndpoint(models.Model): class Source(models.TextChoices): STRIPE = "stripe", "Stripe" GITHUB = "github", "GitHub" MERCADOPAGO = "mercadopago", "Mercado Pago" CUSTOM = "custom", "Custom" name = models.CharField(max_length=255) slug = models.SlugField(unique=True) source = models.CharField(max_length=50, choices=Source.choices) secret = models.CharField(max_length=500) handler = models.CharField(max_length=500) is_active = models.BooleanField(default=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: db_table = "webhooks_inbound_endpoint" def __str__(self): return self.name class InboundEvent(models.Model): endpoint = models.ForeignKey(InboundEndpoint, on_delete=models.CASCADE, related_name="events") event_type = models.CharField(max_length=255) raw_payload = models.JSONField() is_verified = models.BooleanField(default=False) is_processed = models.BooleanField(default=False) error = models.TextField(blank=True) received_at = models.DateTimeField(auto_now_add=True) processed_at = models.DateTimeField(null=True, blank=True) class Meta: db_table = "webhooks_inbound_event" def __str__(self): return f"{self.endpoint.slug} / {self.event_type}"