winofy-backend/apps/catalog/models.py
Ali Asadi 52adc732fa Initial Winofy backend: marketplace core (no payment integration)
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>
2026-08-10 14:03:15 +03:30

60 lines
2 KiB
Python

from django.db import models
from apps.stores.models import Store
from utils.models import BaseModel
class ProductCategory(BaseModel):
name = models.CharField(max_length=100)
parent = models.ForeignKey(
'self', on_delete=models.CASCADE, related_name='children', null=True, blank=True,
)
icon = models.ImageField(upload_to='product_categories/', null=True, blank=True)
order = models.PositiveSmallIntegerField(default=0)
class Meta:
ordering = ['order', 'name']
verbose_name = 'دسته‌بندی محصول'
verbose_name_plural = 'دسته‌بندی‌های محصول'
def __str__(self):
return self.name
class Product(BaseModel):
class UnitType(models.TextChoices):
GRAM = 'gram', 'گرم'
MILLILITER = 'ml', 'میلی‌لیتر'
PIECE = 'piece', 'عدد'
store = models.ForeignKey(Store, on_delete=models.CASCADE, related_name='products')
category = models.ForeignKey(ProductCategory, on_delete=models.PROTECT, related_name='products')
name = models.CharField(max_length=200)
description = models.TextField(blank=True)
image = models.ImageField(upload_to='products/', null=True, blank=True)
price = models.PositiveBigIntegerField()
unit_type = models.CharField(max_length=10, choices=UnitType.choices, default=UnitType.PIECE)
unit_value = models.PositiveIntegerField(null=True, blank=True)
stock_quantity = models.PositiveIntegerField(default=0)
low_stock_threshold = models.PositiveIntegerField(default=5)
is_active = models.BooleanField(default=True)
sold_count = models.PositiveIntegerField(default=0)
class Meta:
ordering = ['-created_at']
verbose_name = 'محصول'
verbose_name_plural = 'محصولات'
def __str__(self):
return f'{self.name} - {self.store.name}'
@property
def is_out_of_stock(self):
return self.stock_quantity <= 0
@property
def is_low_stock(self):
return 0 < self.stock_quantity <= self.low_stock_threshold