You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

193 lines
8.6 KiB

from django.db import models
from django.contrib.auth.models import AbstractUser, Permission, Group
from product_directory.models import Product
21 hours ago
from warehouse.models import Warehouse
# todo: нужно перенести уникальные поля в новую модель
# Справочник товаров
# class Product(models.Model):
# name = models.CharField(max_length=255, verbose_name="Наименование товара")
# manufacturer_name = models.CharField(max_length=255, verbose_name="Производитель")
# manufacturer_country = models.CharField(max_length=255, verbose_name="Страна производителя")
# manufacturer_code = models.CharField(max_length=50, verbose_name="Код производителя", blank=True, null=True)
# dimensions = models.CharField(max_length=255, verbose_name="Размеры", blank=True, null=True)
# unit_of_measure = models.CharField(max_length=50, verbose_name="Единица измерения")
# shelf_life_days = models.IntegerField(verbose_name="Срок годности (дни)")
# barcode = models.CharField(max_length=50, unique=True, verbose_name="Штрихкод")
#
# def __str__(self):
# return self.name
# Справочник должностей
class Position(models.Model):
name = models.CharField(max_length=255, verbose_name="Наименование должности")
hourly_rate = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Ставка в час")
monthly_hours = models.IntegerField(verbose_name="Часы в месяц")
def __str__(self):
return self.name
# Справочник сотрудников
class Employee(AbstractUser):
position = models.ForeignKey(Position, on_delete=models.SET_NULL, null=True, verbose_name="Должность")
department = models.CharField(max_length=255, verbose_name="Подразделение")
work_phone = models.CharField(max_length=20, blank=True, null=True, verbose_name="Рабочий телефон")
personal_phone = models.CharField(max_length=20, blank=True, null=True, verbose_name="Личный телефон")
email = models.EmailField(unique=True, verbose_name="Электронная почта")
groups = models.ManyToManyField(
Group,
related_name='employee_groups',
blank=True,
verbose_name='Группы'
)
user_permissions = models.ManyToManyField(
Permission,
related_name='employee_permissions',
blank=True,
verbose_name='Разрешения'
)
def __str__(self):
return self.get_full_name()
# Справочник мест хранения
class StorageLocation(models.Model):
TYPE_CHOICES = [
('Store', 'Магазин'),
('Distribution Center', 'Распределительный центр'),
('Office', 'Офис'),
]
name = models.CharField(max_length=255, verbose_name="Наименование")
type = models.CharField(max_length=50, choices=TYPE_CHOICES, verbose_name="Тип места хранения")
def __str__(self):
return self.name
# Справочник контрагентов и договоров
class Contractor(models.Model):
name = models.CharField(max_length=255, verbose_name="Наименование контрагента")
address = models.TextField(verbose_name="Адрес")
phone = models.CharField(max_length=20, verbose_name="Телефон")
email = models.EmailField(verbose_name="Электронная почта")
def __str__(self):
return self.name
class SupplyContract(models.Model):
contractor = models.ForeignKey(Contractor, on_delete=models.CASCADE, verbose_name="Контрагент")
description = models.TextField(verbose_name="Описание")
start_date = models.DateField(verbose_name="Дата начала")
end_date = models.DateField(verbose_name="Дата окончания", blank=True, null=True)
def __str__(self):
return f"Договор с {self.contractor.name}"
# Справочник грузовиков
class Truck(models.Model):
plate_number = models.CharField(max_length=20, verbose_name="Номерной знак")
model = models.CharField(max_length=50, verbose_name="Модель")
capacity = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Грузоподъемность (тонны)")
def __str__(self):
return self.plate_number
class StockOperation(models.Model):
OPERATION_TYPE_CHOICES = [
('Incoming', 'Приход'),
('Outgoing', 'Расход'),
('Transfer', 'Перемещение'),
]
product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name="Товар")
location = models.ForeignKey(StorageLocation, on_delete=models.CASCADE, verbose_name="Место хранения")
operation_type = models.CharField(max_length=50, choices=OPERATION_TYPE_CHOICES, verbose_name="Тип операции")
quantity = models.IntegerField(verbose_name="Количество")
operation_date = models.DateTimeField(auto_now_add=True, verbose_name="Дата операции")
expiration_date = models.DateField(blank=True, null=True, verbose_name="Срок годности")
def __str__(self):
return f"{self.operation_type} - {self.product.name}"
class PriceList(models.Model):
PRICE_TYPE_CHOICES = [
('Regular', 'Регулярная'),
('Discount', 'Скидочная'),
('Promotional', 'Акционная'),
]
product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name="Товар")
price_type = models.CharField(max_length=50, choices=PRICE_TYPE_CHOICES, verbose_name="Тип цены")
entry_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Входная цена")
final_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Итоговая цена")
date_effective = models.DateField(verbose_name="Дата вступления в силу")
constraint_percent_limit = models.DecimalField(max_digits=5, decimal_places=2, default=1000, verbose_name="Лимит на наценку (%)")
constraint_price_change = models.DecimalField(max_digits=5, decimal_places=2, default=90, verbose_name="Лимит на изменение цены (%)")
def __str__(self):
return f"{self.price_type} - {self.product.name}"
class Inventory(models.Model):
21 hours ago
warehouse = models.ForeignKey(
Warehouse,
on_delete=models.CASCADE,
verbose_name="Склад",
null=True,
blank=True # Разрешить null и пустое значение
)
storage_location = models.ForeignKey(
StorageLocation,
on_delete=models.CASCADE,
verbose_name="Место хранения",
null=True,
blank=True # Разрешить null и пустое значение
)
product = models.ForeignKey(
Product,
on_delete=models.CASCADE,
verbose_name="Товар",
null=True,
blank=True # Разрешить null и пустое значение
)
actual_quantity = models.PositiveIntegerField(
null=True,
blank=True, # Разрешить null и пустое значение
verbose_name="Фактическое количество"
)
recorded_quantity = models.PositiveIntegerField(
null=True,
blank=True, # Разрешить null и пустое значение
verbose_name="Учтенное количество"
)
difference = models.IntegerField(
null=True,
blank=True, # Разрешить null и пустое значение
verbose_name="Разница",
default=0
)
inventory_date = models.DateTimeField(
auto_now_add=True,
verbose_name="Дата инвентаризации",
null=True,
blank=True # Разрешить null и пустое значение
)
class Meta:
verbose_name = "Инвентаризация"
verbose_name_plural = "Инвентаризации"
def save(self, *args, **kwargs):
if self.actual_quantity is not None and self.recorded_quantity is not None:
self.difference = self.actual_quantity - self.recorded_quantity
else:
self.difference = 0
super().save(*args, **kwargs)
def __str__(self):
21 hours ago
return f"{self.product.name if self.product else 'No Product'} ({self.warehouse.name if self.warehouse else 'No Warehouse'}) - {self.difference}"