from django.db import models from products.models import Product class Stock(models.Model): """ Остатки по каждому товару. """ product = models.OneToOneField(Product, on_delete=models.CASCADE, related_name='stock', verbose_name="Товар") quantity_available = models.DecimalField(max_digits=10, decimal_places=3, default=0, verbose_name="Доступное количество") quantity_reserved = models.DecimalField(max_digits=10, decimal_places=3, default=0, verbose_name="Зарезервированное количество") updated_at = models.DateTimeField(auto_now=True, verbose_name="Дата обновления") class Meta: verbose_name = "Остаток на складе" verbose_name_plural = "Остатки на складе" indexes = [ models.Index(fields=['product']), ] def __str__(self): return f"{self.product.name} - {self.quantity_available}" @property def quantity_free(self): """Свободное количество (доступное минус зарезервированное)""" return self.quantity_available - self.quantity_reserved class StockMovement(models.Model): """ Журнал всех складских операций (приход, списание, коррекция). """ REASON_CHOICES = [ ('purchase', 'Закупка'), ('sale', 'Продажа'), ('write_off', 'Списание'), ('adjustment', 'Корректировка'), ] product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='movements', verbose_name="Товар") change = models.DecimalField(max_digits=10, decimal_places=3, verbose_name="Изменение") reason = models.CharField(max_length=20, choices=REASON_CHOICES, verbose_name="Причина") order = models.ForeignKey('orders.Order', on_delete=models.SET_NULL, null=True, blank=True, related_name='stock_movements', verbose_name="Заказ") created_at = models.DateTimeField(auto_now_add=True, verbose_name="Дата создания") class Meta: verbose_name = "Движение товара" verbose_name_plural = "Движения товаров" indexes = [ models.Index(fields=['product']), models.Index(fields=['created_at']), ] def __str__(self): return f"{self.product.name}: {self.change} ({self.reason})"