Django 6 + DRF resource server against the Gooyal accounts OAuth2 service, matching the Winsoo ecosystem's conventions. Covers locations, stores, catalog, cart, checkout/orders (with the multi-store-cart split and the status stepper), reviews, and notifications, plus a demo-data seed command. Payment integration (wallet debits, online gateway, seller payouts) is intentionally left out here — see feature/payment. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
72 lines
2.6 KiB
Python
72 lines
2.6 KiB
Python
from django.conf import settings
|
|
from django.contrib.gis.db import models as gis_models
|
|
from django.db import models
|
|
|
|
from utils.models import BaseModel
|
|
|
|
|
|
class City(BaseModel):
|
|
name = models.CharField(max_length=100, unique=True)
|
|
slug = models.SlugField(max_length=100, unique=True)
|
|
is_active = models.BooleanField(default=True)
|
|
|
|
class Meta:
|
|
ordering = ['name']
|
|
verbose_name = 'شهر'
|
|
verbose_name_plural = 'شهرها'
|
|
|
|
def __str__(self):
|
|
return self.name
|
|
|
|
|
|
class Neighborhood(BaseModel):
|
|
city = models.ForeignKey(City, on_delete=models.CASCADE, related_name='neighborhoods')
|
|
name = models.CharField(max_length=100)
|
|
slug = models.SlugField(max_length=100)
|
|
center = gis_models.PointField(geography=True, null=True, blank=True)
|
|
is_active = models.BooleanField(default=True)
|
|
|
|
class Meta:
|
|
ordering = ['name']
|
|
unique_together = ('city', 'slug')
|
|
verbose_name = 'محله'
|
|
verbose_name_plural = 'محلهها'
|
|
|
|
def __str__(self):
|
|
return f'{self.name} ({self.city.name})'
|
|
|
|
|
|
class Address(BaseModel):
|
|
class Label(models.TextChoices):
|
|
HOME = 'home', 'خانه'
|
|
WORK = 'work', 'محل کار'
|
|
OTHER = 'other', 'سایر'
|
|
|
|
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='addresses')
|
|
city = models.ForeignKey(City, on_delete=models.PROTECT, related_name='addresses')
|
|
neighborhood = models.ForeignKey(
|
|
Neighborhood, on_delete=models.PROTECT, related_name='addresses', null=True, blank=True,
|
|
)
|
|
label = models.CharField(max_length=10, choices=Label.choices, default=Label.HOME)
|
|
title = models.CharField(max_length=100, blank=True)
|
|
full_address = models.TextField()
|
|
plaque = models.CharField(max_length=20, blank=True)
|
|
floor = models.CharField(max_length=20, blank=True)
|
|
unit = models.CharField(max_length=20, blank=True)
|
|
recipient_name = models.CharField(max_length=150)
|
|
recipient_phone = models.CharField(max_length=20)
|
|
location = gis_models.PointField(geography=True, null=True, blank=True)
|
|
is_default = models.BooleanField(default=False)
|
|
|
|
class Meta:
|
|
ordering = ['-is_default', '-created_at']
|
|
verbose_name = 'آدرس'
|
|
verbose_name_plural = 'آدرسها'
|
|
|
|
def __str__(self):
|
|
return f'{self.get_label_display()} - {self.full_address[:30]}'
|
|
|
|
def save(self, *args, **kwargs):
|
|
if self.is_default:
|
|
Address.objects.filter(user=self.user).exclude(pk=self.pk).update(is_default=False)
|
|
super().save(*args, **kwargs)
|