from django.conf import settings from django.core.validators import MinValueValidator from django.db import models from items.models import Item class Cart(models.Model): user = models.OneToOneField( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="cart", verbose_name="Пользователь", ) created_at = models.DateTimeField(auto_now_add=True, verbose_name="Дата создания") updated_at = models.DateTimeField(auto_now=True, verbose_name="Дата обновления") class Meta: verbose_name = "Корзина" verbose_name_plural = "Корзины" def __str__(self): return f"Корзина пользователя {self.user}" class CartItem(models.Model): cart = models.ForeignKey( Cart, on_delete=models.CASCADE, related_name="items", verbose_name="Корзина", ) item = models.ForeignKey( Item, on_delete=models.CASCADE, related_name="cart_entries", verbose_name="Товар", ) quantity = models.PositiveIntegerField( validators=[MinValueValidator(1)], verbose_name="Количество", ) created_at = models.DateTimeField(auto_now_add=True, verbose_name="Дата создания") updated_at = models.DateTimeField(auto_now=True, verbose_name="Дата обновления") class Meta: ordering = ("created_at", "id") constraints = [ models.UniqueConstraint(fields=("cart", "item"), name="unique_cart_item_per_cart"), ] verbose_name = "Позиция корзины" verbose_name_plural = "Позиции корзины" def __str__(self): return f"{self.item} x {self.quantity}" @property def subtotal(self): return self.item.price * self.quantity class Order(models.Model): class DeliveryMethod(models.TextChoices): COURIER = "courier", "Курьерская доставка" PICKUP = "pickup", "Самовывоз" class PaymentMethod(models.TextChoices): CARD = "card", "Банковская карта" CREDIT = "credit", "Кредит" INSTALLMENT = "installment", "Рассрочка" class Status(models.TextChoices): PAID = "paid", "Оплачен" user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="orders", verbose_name="Пользователь", ) customer_name = models.CharField(max_length=255, verbose_name="ФИО") phone = models.CharField(max_length=32, verbose_name="Телефон") email = models.EmailField(verbose_name="E-mail") delivery_method = models.CharField( max_length=16, choices=DeliveryMethod.choices, default=DeliveryMethod.COURIER, verbose_name="Способ доставки", ) region = models.CharField(max_length=255, blank=True, verbose_name="Регион") address = models.CharField(max_length=512, blank=True, verbose_name="Адрес") payment_method = models.CharField( max_length=16, choices=PaymentMethod.choices, default=PaymentMethod.CARD, verbose_name="Способ оплаты", ) promo_code = models.CharField(max_length=64, blank=True, verbose_name="Промокод") products_total = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Сумма товаров") discount_total = models.DecimalField(max_digits=10, decimal_places=2, default=0, verbose_name="Скидка") delivery_total = models.DecimalField(max_digits=10, decimal_places=2, default=0, verbose_name="Доставка") floor_lift_total = models.DecimalField(max_digits=10, decimal_places=2, default=0, verbose_name="Подъём на этаж") total = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Итого к оплате") status = models.CharField( max_length=16, choices=Status.choices, default=Status.PAID, verbose_name="Статус", ) created_at = models.DateTimeField(auto_now_add=True, verbose_name="Дата создания") class Meta: ordering = ("-created_at", "-id") verbose_name = "Заказ" verbose_name_plural = "Заказы" def __str__(self): return f"Заказ №{self.pk}" class OrderItem(models.Model): order = models.ForeignKey( Order, on_delete=models.CASCADE, related_name="items", verbose_name="Заказ", ) item = models.ForeignKey( Item, on_delete=models.SET_NULL, null=True, blank=True, related_name="order_entries", verbose_name="Товар", ) item_name = models.CharField(max_length=255, verbose_name="Название товара") item_slug = models.SlugField(blank=True, verbose_name="URL товара") item_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Цена товара") quantity = models.PositiveIntegerField(validators=[MinValueValidator(1)], verbose_name="Количество") line_total = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Сумма строки") class Meta: ordering = ("id",) verbose_name = "Позиция заказа" verbose_name_plural = "Позиции заказа" def __str__(self): return f"{self.item_name} x {self.quantity}"