from django.db import models from django.contrib.auth.models import User class Category(models.Model): name = models.CharField(max_length=100, unique=True) def __str__(self): return self.name class SupplierProfile(models.Model): STATUS_CHOICES = [ ('unverified', 'Unverified'), ('phone_verified', 'Phone Verified'), ('email_verified', 'Email Verified'), ('documents_submitted', 'Documents Submitted'), ('pending_approval', 'Pending Approval'), ('approved', 'Approved'), ('rejected', 'Rejected'), ('suspended', 'Suspended'), ] BUSINESS_TYPE_CHOICES = [ ('registered_company', 'Registered Company'), ('self_help_group', 'Self Help Group'), ('individual_maker', 'Individual Maker'), ] user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile') phone = models.CharField(max_length=20, blank=True, null=True) phone_verified = models.BooleanField(default=False) email_verified = models.BooleanField(default=False) gstin = models.CharField(max_length=15, blank=True, null=True) is_gstin_verified = models.BooleanField(default=False) business_type = models.CharField(max_length=50, choices=BUSINESS_TYPE_CHOICES, blank=True, null=True) store_slug = models.SlugField(max_length=255, unique=True, blank=True, null=True) categories = models.ManyToManyField(Category, blank=True, related_name='suppliers') aadhar_file = models.CharField(max_length=255, blank=True, null=True) # retaining old files or S3 keys pan_file = models.CharField(max_length=255, blank=True, null=True) aadhar_s3_key = models.CharField(max_length=255, blank=True, null=True) pan_s3_key = models.CharField(max_length=255, blank=True, null=True) store_name = models.CharField(max_length=255, blank=True, null=True) store_logo = models.TextField(blank=True, null=True) logo_s3_key = models.CharField(max_length=255, blank=True, null=True) business_bio = models.TextField(blank=True, null=True) street = models.CharField(max_length=255, blank=True, null=True) city = models.CharField(max_length=100, blank=True, null=True) state = models.CharField(max_length=100, blank=True, null=True) pincode = models.CharField(max_length=20, blank=True, null=True) latitude = models.FloatField(default=12.9716) longitude = models.FloatField(default=77.5946) status = models.CharField(max_length=50, choices=STATUS_CHOICES, default='unverified') submitted_at = models.DateTimeField(blank=True, null=True) approved_at = models.DateTimeField(blank=True, null=True) approved_by = models.CharField(max_length=150, blank=True, null=True) rejected_reason = models.TextField(blank=True, null=True) is_profile_complete = models.BooleanField(default=False) def __block__(self): return def __str__(self): return f"{self.user.username}'s Profile" class SellerKYC(models.Model): supplier = models.OneToOneField(User, on_delete=models.CASCADE, related_name='kyc') aadhaar_number = models.CharField(max_length=20, blank=True, null=True) name = models.CharField(max_length=255, blank=True, null=True) dob = models.CharField(max_length=50, blank=True, null=True) gender = models.CharField(max_length=10, blank=True, null=True) address = models.TextField(blank=True, null=True) face_base64 = models.TextField(blank=True, null=True) verification_response = models.JSONField(default=dict, blank=True, null=True) pan_number = models.CharField(max_length=20, blank=True, null=True) pan_full_name = models.CharField(max_length=255, blank=True, null=True) pan_dob = models.CharField(max_length=50, blank=True, null=True) pan_status = models.CharField(max_length=50, blank=True, null=True) pan_aadhaar_linked = models.BooleanField(default=False) pan_verification_response = models.JSONField(default=dict, blank=True, null=True) created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return f"{self.supplier.username} - KYC" class OTPRecord(models.Model): TYPE_CHOICES = [ ('phone', 'Phone'), ('email', 'Email'), ('password_reset', 'Password Reset'), ] user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='otp_records') type = models.CharField(max_length=20, choices=TYPE_CHOICES) otp_hash = models.CharField(max_length=64) # SHA-256 hash expires_at = models.DateTimeField() attempts = models.IntegerField(default=0) used = models.BooleanField(default=False) created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return f"{self.user.username} - {self.type} OTP" class BulkUploadLog(models.Model): STATUS_CHOICES = [ ('parsing', 'Parsing'), ('validating', 'Validating'), ('completed', 'Completed'), ('failed', 'Failed'), ] supplier = models.ForeignKey(User, on_delete=models.CASCADE, related_name='bulk_upload_logs', db_constraint=False) log_id = models.CharField(max_length=50, unique=True) s3_key = models.CharField(max_length=255) total_rows = models.IntegerField(default=0) rows_created = models.IntegerField(default=0) rows_updated = models.IntegerField(default=0) rows_skipped = models.IntegerField(default=0) status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='parsing') error_summary = models.TextField(blank=True, null=True) # JSON stored as string uploaded_at = models.DateTimeField(auto_now_add=True) completed_at = models.DateTimeField(blank=True, null=True) def __str__(self): return self.log_id class Product(models.Model): supplier = models.ForeignKey(User, on_delete=models.CASCADE, related_name='products', db_constraint=False) title = models.CharField(max_length=255) category = models.CharField(max_length=100) price = models.DecimalField(max_digits=10, decimal_places=2) stock = models.IntegerField(default=0) sku = models.CharField(max_length=100, unique=True) image = models.TextField(blank=True, null=True) # Can store URL or base64 status = models.CharField(max_length=50, default='pending') is_active = models.BooleanField(default=True) # New heritage fields from UI designs description = models.TextField(blank=True, null=True) is_gi_tagged = models.BooleanField(default=False) additional_images = models.JSONField(default=list, blank=True, null=True) video_url = models.URLField(blank=True, null=True) view_360_url = models.URLField(blank=True, null=True) compare_at_price = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True) track_inventory = models.BooleanField(default=True) shipping_profile = models.CharField(max_length=100, default='Standard Fragile') processing_days = models.IntegerField(default=3) package_weight = models.FloatField(default=1.0) def __str__(self): return self.title class Order(models.Model): STATUS_CHOICES = [ ('Pending Acceptance', 'Pending Acceptance'), ('Ready to Ship', 'Ready to Ship'), ('Shipped', 'Shipped'), ('Delivered', 'Delivered'), ('Cancelled', 'Cancelled'), ('Rejected', 'Rejected'), ] supplier = models.ForeignKey(User, on_delete=models.CASCADE, related_name='orders', db_constraint=False) order_id = models.CharField(max_length=50, unique=True) date = models.DateField() item = models.CharField(max_length=255) quantity = models.IntegerField(default=1) customer = models.CharField(max_length=255) total = models.DecimalField(max_digits=10, decimal_places=2) status = models.CharField(max_length=50, choices=STATUS_CHOICES, default='Pending Acceptance') carrier = models.CharField(max_length=100, default='Pending') tracking = models.CharField(max_length=100, default='Pending') eta = models.CharField(max_length=50, default='N/A') def __str__(self): return self.order_id class ReturnRequest(models.Model): STATUS_CHOICES = [ ('Pending Approval', 'Pending Approval'), ('Approved', 'Approved'), ('Rejected', 'Rejected'), ('In Transit', 'In Transit'), ] supplier = models.ForeignKey(User, on_delete=models.CASCADE, related_name='returns', db_constraint=False) return_id = models.CharField(max_length=50, unique=True) order_id = models.CharField(max_length=50) customer = models.CharField(max_length=255) item = models.CharField(max_length=255) reason = models.TextField() status = models.CharField(max_length=50, choices=STATUS_CHOICES, default='Pending Approval') image = models.TextField(blank=True, null=True) returning_tracking = models.CharField(max_length=100, blank=True, null=True) def __str__(self): return self.return_id class Wallet(models.Model): supplier = models.OneToOneField(User, on_delete=models.CASCADE, related_name='wallet', db_constraint=False) outstanding = models.DecimalField(max_digits=12, decimal_places=2, default=0.00) withdrawn = models.DecimalField(max_digits=12, decimal_places=2, default=0.00) def __str__(self): return f"{self.supplier.username}'s Wallet" class WalletTransaction(models.Model): STATUS_CHOICES = [ ('Transferred', 'Transferred'), ('Pending', 'Pending'), ] wallet = models.ForeignKey(Wallet, on_delete=models.CASCADE, related_name='transactions') tx_id = models.CharField(max_length=50, unique=True) date = models.DateField() amount = models.DecimalField(max_digits=12, decimal_places=2) status = models.CharField(max_length=50, choices=STATUS_CHOICES, default='Transferred') def __str__(self): return self.tx_id