from django.db import models from django.contrib.auth.models import AbstractUser class User(AbstractUser): full_name = models.CharField(max_length=100) email = models.EmailField(unique=True) user_age = models.PositiveIntegerField(null=True, blank=True) GENDER_CHOICES = [ ('Male', 'Male'), ('Female', 'Female'), ('Other', 'Other'), ('Prefer not to say', 'Prefer not to say'), ] user_gender = models.CharField( max_length=20, choices=GENDER_CHOICES, default='Prefer not to say' ) created_at = models.DateTimeField(auto_now_add=True) USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['username'] class Address(models.Model): user = models.ForeignKey( User, on_delete=models.CASCADE, related_name='addresses' ) line1 = models.CharField(max_length=255) line2 = models.CharField(max_length=255, blank=True) city = models.CharField(max_length=100) state = models.CharField(max_length=100) country = models.CharField(max_length=100) pincode = models.CharField(max_length=20) is_default = models.BooleanField(default=False) created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return f"{self.line1}, {self.city}" class Product(models.Model): product_name = models.CharField(max_length=255, db_index=True) base_price = models.DecimalField( max_digits=10, decimal_places=2, db_index=True ) stock_quantity = models.PositiveIntegerField(default=0) class Meta: ordering = ['id'] def __str__(self): return self.product_name class Order(models.Model): PAYMENT_CHOICES = [ ('Credit Card', 'Credit Card'), ('Debit Card', 'Debit Card'), ('PayPal', 'PayPal'), ('Gift Card', 'Gift Card'), ] SHIPPING_CHOICES = [ ('Standard', 'Standard'), ('Express', 'Express'), ('Next-Day', 'Next-Day'), ] user = models.ForeignKey( User, on_delete=models.CASCADE, related_name='orders' ) shipping_address = models.ForeignKey( Address, on_delete=models.PROTECT, related_name='orders' ) order_date = models.DateTimeField(auto_now_add=True, db_index=True) payment_method = models.CharField( max_length=20, choices=PAYMENT_CHOICES ) shipping_method = models.CharField( max_length=20, choices=SHIPPING_CHOICES ) def __str__(self): return f"Order {self.id}" class OrderDetail(models.Model): RETURN_STATUS = [ ('Not Returned', 'Not Returned'), ('Return Initiated', 'Return Initiated'), ('Returned', 'Returned'), ] order = models.ForeignKey( Order, on_delete=models.CASCADE, related_name='items' ) product = models.ForeignKey( Product, on_delete=models.PROTECT ) order_quantity = models.PositiveIntegerField() product_price = models.DecimalField( max_digits=10, decimal_places=2 ) discount_applied = models.DecimalField( max_digits=5, decimal_places=2, default=0 ) return_status = models.CharField( max_length=20, choices=RETURN_STATUS, default='Not Returned', db_index=True ) return_date = models.DateTimeField(null=True, blank=True) return_reason = models.CharField(max_length=255, blank=True) days_to_return = models.PositiveIntegerField(default=0) # NEW FIELDS is_exchanged = models.BooleanField(default=False) exchange_order = models.ForeignKey( Order, on_delete=models.SET_NULL, null=True, blank=True, related_name='exchange_items' ) def __str__(self): return f"{self.product} in Order {self.order.id}" class ExchangeLog(models.Model): exchange_id = models.AutoField(primary_key=True) order = models.ForeignKey( 'Order', on_delete=models.CASCADE, related_name='exchange_logs' ) pickup_date = models.DateField(null=True, blank=True) pickup_time = models.TimeField(null=True, blank=True) inference_status = models.CharField( max_length=20, choices=[('scrap', 'Scrap'), ('refurb', 'Refurbish'), ('resale', 'Resale')], default='refurb' ) created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return f"Exchange {self.exchange_id} for Order {self.order.id}" class ReturnLog(models.Model): return_id = models.AutoField(primary_key=True) order = models.ForeignKey( 'Order', on_delete=models.CASCADE, related_name='return_logs' ) refund_id = models.CharField(max_length=100) pickup_date = models.DateField(null=True, blank=True) pickup_time = models.TimeField(null=True, blank=True) created_at = models.DateTimeField(auto_now_add=True) refund_amount = models.DecimalField(max_digits=10, decimal_places=2, null = True) def __str__(self): return f"Return {self.return_id} for Order {self.order.id}" class VoiceSession(models.Model): """One record per voice-bot conversation session.""" session_id = models.CharField(max_length=100, unique=True, db_index=True) user = models.ForeignKey( User, on_delete=models.SET_NULL, null=True, blank=True, related_name='voice_sessions', ) started_at = models.DateTimeField(auto_now_add=True) ended_at = models.DateTimeField(null=True, blank=True) # Final outcome STATUS_CHOICES = [ ('in_progress', 'In Progress'), ('completed', 'Completed'), ('abandoned', 'Abandoned'), ] status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='in_progress') request_type = models.CharField(max_length=20, blank=True) # exchange / return order_id = models.CharField(max_length=50, blank=True) reason = models.TextField(blank=True) exchange_preference = models.TextField(blank=True) tracking_number = models.CharField(max_length=100, blank=True) # Snapshot of all collected session data as JSON session_data_json = models.JSONField(default=dict, blank=True) def __str__(self): return f"VoiceSession {self.session_id[:8]} ({self.status})" class VoiceMessage(models.Model): """One record per turn (user utterance + bot reply) inside a session.""" session = models.ForeignKey( VoiceSession, on_delete=models.CASCADE, related_name='messages', ) turn_number = models.PositiveIntegerField() step = models.CharField(max_length=50) # greeting, ask_order_id … next_step = models.CharField(max_length=50, blank=True) user_text = models.TextField(blank=True) # what the user said bot_text = models.TextField(blank=True) # what the bot replied llm_input = models.TextField(blank=True) # prompt sent to LLM llm_output = models.TextField(blank=True) # raw LLM response extracted_value = models.CharField(max_length=255, blank=True) # parsed value session_data_snapshot = models.JSONField(default=dict, blank=True) created_at = models.DateTimeField(auto_now_add=True) class Meta: ordering = ['session', 'turn_number'] def __str__(self): return f"Turn {self.turn_number} ({self.step}) in {self.session.session_id[:8]}"