* Vietnamese translation incomplete

Business Directory Models

Business Directory Models (English fallback)

Aug. 16, 2025

Posted by admin

 

from django.db import models

from django.contrib.auth.models import User

from django.urls import reverse

from django.core.validators import MaxValueValidator, MinValueValidator

 

 

Listing

class BusinessListing(models.Model):

    """Business listing model"""

    SUBSCRIPTION_CHOICES = [

        ('free', 'Free Listing'),

        ('basic', 'Basic Listing'),

        ('premium', 'Premium Listing'),

        ('featured', 'Featured Listing'),

    ]

   

    STATUS_CHOICES = [

        ('draft', 'Draft'),

        ('pending', 'Pending Approval'),

        ('approved', 'Approved'),

        ('rejected', 'Rejected'),

        ('suspended', 'Suspended'),

    ]

   

    TRANSLATION_STATUS_CHOICES = [

        ('pending', 'Pending Translation'),

        ('translated', 'Translated'),

        ('reviewed', 'Reviewed'),

    ]

   

    # Basic Information

    business_name = models.CharField(max_length=200)

    business_name_vi = models.CharField(max_length=200, blank=True, verbose_name="Vietnamese Business Name")

    slug = models.SlugField(max_length=200, unique=True)

    category = models.ForeignKey(BusinessCategory, on_delete=models.CASCADE, related_name='businesses')

    owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='businesses')

   

    # Description

    description = models.TextField()

    description_vi = models.TextField(blank=True, verbose_name="Vietnamese Description")

    short_description = models.CharField(max_length=300, help_text="Brief description for listings")

    short_description_vi = models.CharField(max_length=300, blank=True, verbose_name="Vietnamese Short Description")

   

    # Contact Information

    phone = models.CharField(max_length=20)

    email = models.EmailField()

    website = models.URLField(blank=True)

   

    # Address

    street_address = models.CharField(max_length=200)

    city = models.CharField(max_length=100)

    state = models.CharField(max_length=100)

    postal_code = models.CharField(max_length=20)

    country = models.CharField(max_length=100, default='Vietnam')

    latitude = models.DecimalField(max_digits=10, decimal_places=8, null=True, blank=True)

    longitude = models.DecimalField(max_digits=11, decimal_places=8, null=True, blank=True)

   

    # Business Hours

    monday_hours = models.CharField(max_length=50, blank=True, help_text="e.g., 9:00 AM - 5:00 PM")

    tuesday_hours = models.CharField(max_length=50, blank=True)

    wednesday_hours = models.CharField(max_length=50, blank=True)

    thursday_hours = models.CharField(max_length=50, blank=True)

    friday_hours = models.CharField(max_length=50, blank=True)

    saturday_hours = models.CharField(max_length=50, blank=True)

    sunday_hours = models.CharField(max_length=50, blank=True)

   

    # Social Media

    facebook_url = models.URLField(blank=True)

    twitter_url = models.URLField(blank=True)

    instagram_url = models.URLField(blank=True)

    linkedin_url = models.URLField(blank=True)

   

    # Features/Amenities

    accepts_credit_cards = models.BooleanField(default=False)

    parking_available = models.BooleanField(default=False)

    wheelchair_accessible = models.BooleanField(default=False)

    wifi_available = models.BooleanField(default=False)

    outdoor_seating = models.BooleanField(default=False)

    delivery_available = models.BooleanField(default=False)

   

    # Subscription & Status

    subscription_type = models.CharField(max_length=20, choices=SUBSCRIPTION_CHOICES, default='free')

    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='draft')

    is_verified = models.BooleanField(default=False)

    is_featured = models.BooleanField(default=False)

   

    # SEO Fields

    meta_title = models.CharField(max_length=60, blank=True)

    meta_description = models.CharField(max_length=160, blank=True)

    keywords = models.CharField(max_length=200, blank=True, help_text="Comma-separated keywords")

   

    # Analytics

    views_count = models.PositiveIntegerField(default=0)

    phone_clicks = models.PositiveIntegerField(default=0)

    website_clicks = models.PositiveIntegerField(default=0)

   

    # Timestamps

    created_at = models.DateTimeField(auto_now_add=True)

    updated_at = models.DateTimeField(auto_now=True)

    featured_until = models.DateTimeField(null=True, blank=True)

    subscription_expires = models.DateTimeField(null=True, blank=True)

   

    # Vietnamese translation fields

    translation_status = models.CharField(

        max_length=20,

        choices=TRANSLATION_STATUS_CHOICES,

        default='pending',

        help_text="Status of Vietnamese translation"

    )

    translated_by = models.CharField(max_length=100, blank=True, help_text="Name of translator")

    translated_at = models.DateTimeField(null=True, blank=True, help_text="When translation was completed")

   

    class Meta:

        ordering = ['-is_featured', '-created_at']

   

    def __str__(self):

        return self.business_name

   

    def get_display_name(self, language='en'):

        """Get business name in specified language"""

        if language == 'vi' and self.business_name_vi:

            return self.business_name_vi

        return self.business_name

   

    def get_display_description(self, language='en'):

        """Get business description in specified language"""

        if language == 'vi' and self.description_vi:

            return self.description_vi

        return self.description

   

    def get_display_short_description(self, language='en'):

        """Get business short description in specified language"""

        if language == 'vi' and self.short_description_vi:

            return self.short_description_vi

        return self.short_description

   

    def is_translated(self):

        """Check if business has Vietnamese translation"""

        return bool(self.business_name_vi and self.description_vi and self.short_description_vi)

   

    def get_absolute_url(self):

        return reverse('business_directory:detail', kwargs={'slug': self.slug})

   

    def get_full_address(self):

        """Get formatted full address"""

        parts = [self.street_address, self.city, self.state, self.postal_code, self.country]

        return ', '.join(filter(None, parts))

 

 

Listing Category

class BusinessCategory(models.Model):

    """Categories for business listings"""

    TRANSLATION_STATUS_CHOICES = [

        ('pending', 'Pending Translation'),

        ('translated', 'Translated'),

        ('reviewed', 'Reviewed'),

    ]

   

    name = models.CharField(max_length=100, unique=True)

    name_vi = models.CharField(max_length=100, blank=True, verbose_name="Vietnamese Name")

    slug = models.SlugField(max_length=100, unique=True)

    description = models.TextField(blank=True)

    description_vi = models.TextField(blank=True, verbose_name="Vietnamese Description")

    icon = models.CharField(max_length=50, default='fas fa-building')

    parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='subcategories')

    is_active = models.BooleanField(default=True)

    sort_order = models.PositiveIntegerField(default=0)

    created_at = models.DateTimeField(auto_now_add=True)

   

    # Vietnamese translation fields

    translation_status = models.CharField(

        max_length=20,

        choices=TRANSLATION_STATUS_CHOICES,

        default='pending',

        help_text="Status of Vietnamese translation"

    )

    translated_by = models.CharField(max_length=100, blank=True, help_text="Name of translator")

    translated_at = models.DateTimeField(null=True, blank=True, help_text="When translation was completed")

 

    class Meta:

        verbose_name_plural = "Business Categories"

        ordering = ['sort_order', 'name']

 

    def __str__(self):

        return self.name

   

    def get_display_name(self, language='en'):

        """Get category name in specified language"""

        if language == 'vi' and self.name_vi:

            return self.name_vi

        return self.name

   

    def get_display_description(self, language='en'):

        """Get category description in specified language"""

        if language == 'vi' and self.description_vi:

            return self.description_vi

        return self.description

   

    def is_translated(self):

        """Check if category has Vietnamese translation"""

        return bool(self.name_vi and self.description_vi)

 

    def get_absolute_url(self):

        return reverse('business_directory:category', kwargs={'slug': self.slug})

 

    def get_business_count(self):

        """Get count of approved businesses in this category"""

        return self.businesses.filter(status='approved').count()

 

 

Listing Image

class BusinessImage(models.Model):

    """Images for business listings"""

    business = models.ForeignKey(BusinessListing, on_delete=models.CASCADE, related_name='images')

    image = models.ImageField(upload_to='business_images/')

    caption = models.CharField(max_length=200, blank=True)

    is_primary = models.BooleanField(default=False)

    sort_order = models.PositiveIntegerField(default=0)

    uploaded_at = models.DateTimeField(auto_now_add=True)

   

    class Meta:

        ordering = ['sort_order', 'uploaded_at']

   

    def __str__(self):

        return f"Image for {self.business.business_name}"

 

Listing Review

class BusinessReview(models.Model):

    """Reviews for business listings"""

    business = models.ForeignKey(BusinessListing, on_delete=models.CASCADE, related_name='reviews')

    reviewer = models.ForeignKey(User, on_delete=models.CASCADE, related_name='business_reviews')

    rating = models.PositiveIntegerField(

        validators=[MinValueValidator(1), MaxValueValidator(5)],

        help_text="Rating from 1 to 5 stars"

    )

    title = models.CharField(max_length=200)

    review_text = models.TextField()

    is_verified = models.BooleanField(default=False)

    created_at = models.DateTimeField(auto_now_add=True)

    updated_at = models.DateTimeField(auto_now=True)

   

    class Meta:

        unique_together = ['business', 'reviewer']

        ordering = ['-created_at']

   

    def __str__(self):

        return f"{self.title} - {self.rating} stars"

 

Liting Claim

class BusinessClaim(models.Model):

    """Business claim requests"""

    business = models.ForeignKey(BusinessListing, on_delete=models.CASCADE, related_name='claims')

    claimant = models.ForeignKey(User, on_delete=models.CASCADE, related_name='business_claims')

    claim_reason = models.TextField(help_text="Reason for claiming this business")

    verification_document = models.FileField(upload_to='claim_documents/', blank=True)

    status = models.CharField(max_length=20, choices=[

        ('pending', 'Pending Review'),

        ('approved', 'Approved'),

        ('rejected', 'Rejected'),

    ], default='pending')

    created_at = models.DateTimeField(auto_now_add=True)

    reviewed_at = models.DateTimeField(null=True, blank=True)

   

    class Meta:

        ordering = ['-created_at']

   

    def __str__(self):

        return f"Claim for {self.business.business_name} by {self.claimant.username}"

 

Vietnamese translation is not available for this article. Showing English content:

 

from django.db import models

from django.contrib.auth.models import User

from django.urls import reverse

from django.core.validators import MaxValueValidator, MinValueValidator

 

 

Listing

class BusinessListing(models.Model):

    """Business listing model"""

    SUBSCRIPTION_CHOICES = [

        ('free', 'Free Listing'),

        ('basic', 'Basic Listing'),

        ('premium', 'Premium Listing'),

        ('featured', 'Featured Listing'),

    ]

   

    STATUS_CHOICES = [

        ('draft', 'Draft'),

        ('pending', 'Pending Approval'),

        ('approved', 'Approved'),

        ('rejected', 'Rejected'),

        ('suspended', 'Suspended'),

    ]

   

    TRANSLATION_STATUS_CHOICES = [

        ('pending', 'Pending Translation'),

        ('translated', 'Translated'),

        ('reviewed', 'Reviewed'),

    ]

   

    # Basic Information

    business_name = models.CharField(max_length=200)

    business_name_vi = models.CharField(max_length=200, blank=True, verbose_name="Vietnamese Business Name")

    slug = models.SlugField(max_length=200, unique=True)

    category = models.ForeignKey(BusinessCategory, on_delete=models.CASCADE, related_name='businesses')

    owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='businesses')

   

    # Description

    description = models.TextField()

    description_vi = models.TextField(blank=True, verbose_name="Vietnamese Description")

    short_description = models.CharField(max_length=300, help_text="Brief description for listings")

    short_description_vi = models.CharField(max_length=300, blank=True, verbose_name="Vietnamese Short Description")

   

    # Contact Information

    phone = models.CharField(max_length=20)

    email = models.EmailField()

    website = models.URLField(blank=True)

   

    # Address

    street_address = models.CharField(max_length=200)

    city = models.CharField(max_length=100)

    state = models.CharField(max_length=100)

    postal_code = models.CharField(max_length=20)

    country = models.CharField(max_length=100, default='Vietnam')

    latitude = models.DecimalField(max_digits=10, decimal_places=8, null=True, blank=True)

    longitude = models.DecimalField(max_digits=11, decimal_places=8, null=True, blank=True)

   

    # Business Hours

    monday_hours = models.CharField(max_length=50, blank=True, help_text="e.g., 9:00 AM - 5:00 PM")

    tuesday_hours = models.CharField(max_length=50, blank=True)

    wednesday_hours = models.CharField(max_length=50, blank=True)

    thursday_hours = models.CharField(max_length=50, blank=True)

    friday_hours = models.CharField(max_length=50, blank=True)

    saturday_hours = models.CharField(max_length=50, blank=True)

    sunday_hours = models.CharField(max_length=50, blank=True)

   

    # Social Media

    facebook_url = models.URLField(blank=True)

    twitter_url = models.URLField(blank=True)

    instagram_url = models.URLField(blank=True)

    linkedin_url = models.URLField(blank=True)

   

    # Features/Amenities

    accepts_credit_cards = models.BooleanField(default=False)

    parking_available = models.BooleanField(default=False)

    wheelchair_accessible = models.BooleanField(default=False)

    wifi_available = models.BooleanField(default=False)

    outdoor_seating = models.BooleanField(default=False)

    delivery_available = models.BooleanField(default=False)

   

    # Subscription & Status

    subscription_type = models.CharField(max_length=20, choices=SUBSCRIPTION_CHOICES, default='free')

    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='draft')

    is_verified = models.BooleanField(default=False)

    is_featured = models.BooleanField(default=False)

   

    # SEO Fields

    meta_title = models.CharField(max_length=60, blank=True)

    meta_description = models.CharField(max_length=160, blank=True)

    keywords = models.CharField(max_length=200, blank=True, help_text="Comma-separated keywords")

   

    # Analytics

    views_count = models.PositiveIntegerField(default=0)

    phone_clicks = models.PositiveIntegerField(default=0)

    website_clicks = models.PositiveIntegerField(default=0)

   

    # Timestamps

    created_at = models.DateTimeField(auto_now_add=True)

    updated_at = models.DateTimeField(auto_now=True)

    featured_until = models.DateTimeField(null=True, blank=True)

    subscription_expires = models.DateTimeField(null=True, blank=True)

   

    # Vietnamese translation fields

    translation_status = models.CharField(

        max_length=20,

        choices=TRANSLATION_STATUS_CHOICES,

        default='pending',

        help_text="Status of Vietnamese translation"

    )

    translated_by = models.CharField(max_length=100, blank=True, help_text="Name of translator")

    translated_at = models.DateTimeField(null=True, blank=True, help_text="When translation was completed")

   

    class Meta:

        ordering = ['-is_featured', '-created_at']

   

    def __str__(self):

        return self.business_name

   

    def get_display_name(self, language='en'):

        """Get business name in specified language"""

        if language == 'vi' and self.business_name_vi:

            return self.business_name_vi

        return self.business_name

   

    def get_display_description(self, language='en'):

        """Get business description in specified language"""

        if language == 'vi' and self.description_vi:

            return self.description_vi

        return self.description

   

    def get_display_short_description(self, language='en'):

        """Get business short description in specified language"""

        if language == 'vi' and self.short_description_vi:

            return self.short_description_vi

        return self.short_description

   

    def is_translated(self):

        """Check if business has Vietnamese translation"""

        return bool(self.business_name_vi and self.description_vi and self.short_description_vi)

   

    def get_absolute_url(self):

        return reverse('business_directory:detail', kwargs={'slug': self.slug})

   

    def get_full_address(self):

        """Get formatted full address"""

        parts = [self.street_address, self.city, self.state, self.postal_code, self.country]

        return ', '.join(filter(None, parts))

 

 

Listing Category

class BusinessCategory(models.Model):

    """Categories for business listings"""

    TRANSLATION_STATUS_CHOICES = [

        ('pending', 'Pending Translation'),

        ('translated', 'Translated'),

        ('reviewed', 'Reviewed'),

    ]

   

    name = models.CharField(max_length=100, unique=True)

    name_vi = models.CharField(max_length=100, blank=True, verbose_name="Vietnamese Name")

    slug = models.SlugField(max_length=100, unique=True)

    description = models.TextField(blank=True)

    description_vi = models.TextField(blank=True, verbose_name="Vietnamese Description")

    icon = models.CharField(max_length=50, default='fas fa-building')

    parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='subcategories')

    is_active = models.BooleanField(default=True)

    sort_order = models.PositiveIntegerField(default=0)

    created_at = models.DateTimeField(auto_now_add=True)

   

    # Vietnamese translation fields

    translation_status = models.CharField(

        max_length=20,

        choices=TRANSLATION_STATUS_CHOICES,

        default='pending',

        help_text="Status of Vietnamese translation"

    )

    translated_by = models.CharField(max_length=100, blank=True, help_text="Name of translator")

    translated_at = models.DateTimeField(null=True, blank=True, help_text="When translation was completed")

 

    class Meta:

        verbose_name_plural = "Business Categories"

        ordering = ['sort_order', 'name']

 

    def __str__(self):

        return self.name

   

    def get_display_name(self, language='en'):

        """Get category name in specified language"""

        if language == 'vi' and self.name_vi:

            return self.name_vi

        return self.name

   

    def get_display_description(self, language='en'):

        """Get category description in specified language"""

        if language == 'vi' and self.description_vi:

            return self.description_vi

        return self.description

   

    def is_translated(self):

        """Check if category has Vietnamese translation"""

        return bool(self.name_vi and self.description_vi)

 

    def get_absolute_url(self):

        return reverse('business_directory:category', kwargs={'slug': self.slug})

 

    def get_business_count(self):

        """Get count of approved businesses in this category"""

        return self.businesses.filter(status='approved').count()

 

 

Listing Image

class BusinessImage(models.Model):

    """Images for business listings"""

    business = models.ForeignKey(BusinessListing, on_delete=models.CASCADE, related_name='images')

    image = models.ImageField(upload_to='business_images/')

    caption = models.CharField(max_length=200, blank=True)

    is_primary = models.BooleanField(default=False)

    sort_order = models.PositiveIntegerField(default=0)

    uploaded_at = models.DateTimeField(auto_now_add=True)

   

    class Meta:

        ordering = ['sort_order', 'uploaded_at']

   

    def __str__(self):

        return f"Image for {self.business.business_name}"

 

Listing Review

class BusinessReview(models.Model):

    """Reviews for business listings"""

    business = models.ForeignKey(BusinessListing, on_delete=models.CASCADE, related_name='reviews')

    reviewer = models.ForeignKey(User, on_delete=models.CASCADE, related_name='business_reviews')

    rating = models.PositiveIntegerField(

        validators=[MinValueValidator(1), MaxValueValidator(5)],

        help_text="Rating from 1 to 5 stars"

    )

    title = models.CharField(max_length=200)

    review_text = models.TextField()

    is_verified = models.BooleanField(default=False)

    created_at = models.DateTimeField(auto_now_add=True)

    updated_at = models.DateTimeField(auto_now=True)

   

    class Meta:

        unique_together = ['business', 'reviewer']

        ordering = ['-created_at']

   

    def __str__(self):

        return f"{self.title} - {self.rating} stars"

 

Liting Claim

class BusinessClaim(models.Model):

    """Business claim requests"""

    business = models.ForeignKey(BusinessListing, on_delete=models.CASCADE, related_name='claims')

    claimant = models.ForeignKey(User, on_delete=models.CASCADE, related_name='business_claims')

    claim_reason = models.TextField(help_text="Reason for claiming this business")

    verification_document = models.FileField(upload_to='claim_documents/', blank=True)

    status = models.CharField(max_length=20, choices=[

        ('pending', 'Pending Review'),

        ('approved', 'Approved'),

        ('rejected', 'Rejected'),

    ], default='pending')

    created_at = models.DateTimeField(auto_now_add=True)

    reviewed_at = models.DateTimeField(null=True, blank=True)

   

    class Meta:

        ordering = ['-created_at']

   

    def __str__(self):

        return f"Claim for {self.business.business_name} by {self.claimant.username}"

 

Attached Files

0 files found.

You are viewing this article in public mode. Some features may be limited.