Files
octopus/myproject/inventory/models.py

62 lines
2.6 KiB
Python

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})"