All checks were successful
Deploy Beta (NATIVE) / deploy (push) Successful in 29s
95 lines
3.9 KiB
Python
95 lines
3.9 KiB
Python
import uuid
|
|
from django.db import models
|
|
|
|
|
|
class VendorConfig(models.Model):
|
|
"""
|
|
Dynamic configuration for verification vendors stored in database.
|
|
Allows toggling active state, priority adjustments, and credential updates via Django admin.
|
|
"""
|
|
name = models.CharField(max_length=50, unique=True, help_text="Unique vendor identifier, e.g. codeplus")
|
|
display_name = models.CharField(max_length=100, help_text="Human-readable name")
|
|
is_active = models.BooleanField(default=True)
|
|
priority = models.PositiveIntegerField(
|
|
default=10,
|
|
help_text="Waterfall execution order (lower numbers execute first)",
|
|
)
|
|
supported_documents = models.JSONField(
|
|
default=list,
|
|
help_text="List of supported doc types: ['pan', 'aadhaar', 'driving_license', 'voter_id', ...]",
|
|
)
|
|
base_url = models.CharField(max_length=255, blank=True, null=True)
|
|
api_key = models.CharField(max_length=255, blank=True, null=True)
|
|
extra_credentials = models.JSONField(default=dict, blank=True)
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|
updated_at = models.DateTimeField(auto_now=True)
|
|
|
|
class Meta:
|
|
ordering = ["priority", "name"]
|
|
verbose_name = "Vendor Configuration"
|
|
verbose_name_plural = "Vendor Configurations"
|
|
|
|
def __str__(self):
|
|
return f"{self.display_name} ({self.name}) - Priority: {self.priority} - {'Active' if self.is_active else 'Disabled'}"
|
|
|
|
|
|
class VerificationTransaction(models.Model):
|
|
"""
|
|
Master record of every document verification request processed by the engine.
|
|
"""
|
|
STATUS_CHOICES = (
|
|
("PENDING", "Pending"),
|
|
("SUCCESS", "Success"),
|
|
("FAILED", "Failed"),
|
|
("ERROR", "Error"),
|
|
)
|
|
|
|
reference_id = models.UUIDField(default=uuid.uuid4, unique=True, editable=False, db_index=True)
|
|
document_type = models.CharField(max_length=50, db_index=True)
|
|
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default="PENDING", db_index=True)
|
|
successful_vendor = models.CharField(max_length=50, blank=True, null=True)
|
|
input_payload = models.JSONField(default=dict, blank=True)
|
|
final_data = models.JSONField(default=dict, blank=True)
|
|
response_payload = models.JSONField(default=dict, blank=True)
|
|
attempts_count = models.PositiveIntegerField(default=0)
|
|
total_latency_ms = models.FloatField(default=0.0)
|
|
created_at = models.DateTimeField(auto_now_add=True, db_index=True)
|
|
updated_at = models.DateTimeField(auto_now=True)
|
|
|
|
class Meta:
|
|
ordering = ["-created_at"]
|
|
verbose_name = "Verification Transaction"
|
|
verbose_name_plural = "Verification Transactions"
|
|
|
|
def __str__(self):
|
|
return f"[{self.status}] {self.document_type} - {self.reference_id} ({self.successful_vendor or 'none'})"
|
|
|
|
|
|
class VendorAttemptLog(models.Model):
|
|
"""
|
|
Audit log of each individual vendor attempt in the waterfall cascade.
|
|
Allows inspection of which vendor failed, why, latency, and full payload details.
|
|
"""
|
|
transaction = models.ForeignKey(
|
|
VerificationTransaction,
|
|
related_name="attempts",
|
|
on_delete=models.CASCADE,
|
|
)
|
|
attempt_number = models.PositiveIntegerField()
|
|
vendor_name = models.CharField(max_length=50, db_index=True)
|
|
status = models.CharField(max_length=20)
|
|
is_success = models.BooleanField(default=False)
|
|
data = models.JSONField(default=dict, blank=True)
|
|
raw_response = models.JSONField(null=True, blank=True)
|
|
error_code = models.CharField(max_length=100, blank=True, null=True)
|
|
error_message = models.TextField(blank=True, null=True)
|
|
latency_ms = models.FloatField(default=0.0)
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|
|
|
class Meta:
|
|
ordering = ["attempt_number"]
|
|
verbose_name = "Vendor Attempt Log"
|
|
verbose_name_plural = "Vendor Attempt Logs"
|
|
|
|
def __str__(self):
|
|
return f"Tx: {self.transaction.reference_id} | #{self.attempt_number} {self.vendor_name} -> {self.status}"
|