Files
MES_Core/exempl/warehouse/models.py
ackFromRedmi e88b861f68
All checks were successful
Deploy MES Core / deploy (push) Successful in 11s
Огромная замена логики
2026-04-06 08:06:37 +03:00

104 lines
5.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from django.db import models
from django.contrib.auth.models import User
class MaterialCategory(models.Model):
"""Категория сырья (Лист, Труба, Круг)."""
name = models.CharField("Название категории", max_length=100, unique=True)
gost_standard = models.CharField("ГОСТ", max_length=255, blank=True)
class Meta:
verbose_name = "Категория материала"
verbose_name_plural = "Категории материалов"
def __str__(self): return self.name
class SteelGrade(models.Model):
"""Марка стали."""
name = models.CharField("Марка стали", max_length=100, unique=True)
gost_standard = models.CharField("ГОСТ/ТУ", max_length=255, blank=True)
class Meta:
verbose_name = "Марка стали"; verbose_name_plural = "Марки стали"
def __str__(self): return self.name
class Material(models.Model):
"""
Справочник закупаемого сырья (Номенклатура).
Логика: Это только "идея" материала, а не физический объект на полке.
Для листа заполняем thickness, для трубы width (сечение), для всех length (стандартная длина).
"""
category = models.ForeignKey(MaterialCategory, on_delete=models.PROTECT, verbose_name="Категория")
steel_grade = models.ForeignKey(SteelGrade, on_delete=models.PROTECT, null=True, blank=True)
name = models.CharField("Наименование", max_length=255)
thickness = models.FloatField("Толщина (S), мм", null=True, blank=True)
width = models.FloatField("Ширина/Сечение (B), мм", null=True, blank=True)
length = models.FloatField("Длина (L), мм", null=True, blank=True)
class Meta:
verbose_name = "Номенклатура (Сырье)"; verbose_name_plural = "Номенклатура (Сырье)"
def __str__(self): return f"{self.category.name} {self.name} {self.steel_grade.name if self.steel_grade else ''}"
class Location(models.Model):
"""Склады и участки (Центральный, Лазер, Сварка, СГП)."""
name = models.CharField("Место хранения", max_length=100, unique=True)
is_production_area = models.BooleanField("Это производственный участок", default=False)
class Meta:
verbose_name = "Склад/Участок"; verbose_name_plural = "Склады и участки"
def __str__(self): return self.name
class StockItem(models.Model):
"""
Универсальная физическая единица на складе.
Логика Вьюх:
1. Если это сырье: заполнен material, пусто entity.
2. Если это готовая деталь: заполнен entity, пусто material.
3. Если is_remnant=True, то current_length/width показывают реальный размер куска.
При списании в CuttingSession количество здесь уменьшается. Если 0 - можно удалять или скрывать.
"""
material = models.ForeignKey(Material, on_delete=models.PROTECT, null=True, blank=True, verbose_name="Сырье")
entity = models.ForeignKey('manufacturing.ProductEntity', on_delete=models.PROTECT, null=True, blank=True, verbose_name="Произведенная сущность")
location = models.ForeignKey(Location, on_delete=models.PROTECT, verbose_name="Где находится")
quantity = models.FloatField("Количество (шт/м/кг)")
# Для деловых остатков
is_remnant = models.BooleanField("Деловой остаток", default=False)
current_length = models.FloatField("Текущая длина, мм", null=True, blank=True)
current_width = models.FloatField("Текущая ширина, мм", null=True, blank=True)
unique_id = models.CharField("ID/Маркировка (для ДО)", max_length=50, unique=True, null=True, blank=True)
class Meta:
verbose_name = "Единица на складе"; verbose_name_plural = "Остатки на складах"
def __str__(self):
obj = self.entity if self.entity else self.material
return f"{obj} | {self.quantity} ед. | {self.location}"
class TransferRecord(models.Model):
"""
Документ перемещения (Вариант Б: строгий учет).
Логика Вьюх:
Создается "Отправителем" (статус sent).
"Получатель" видит его в своем интерфейсе и жмет "Принять" (статус received).
В этот момент у связанных StockItem меняется location на to_location.
"""
STATUS_CHOICES = [('sent', 'В пути'), ('received', 'Принято'), ('discrepancy', 'Расхождение')]
items = models.ManyToManyField(StockItem, verbose_name="Перемещаемые объекты")
from_location = models.ForeignKey(Location, related_name='outgoing', on_delete=models.PROTECT)
to_location = models.ForeignKey(Location, related_name='incoming', on_delete=models.PROTECT)
sender = models.ForeignKey(User, related_name='sent_transfers', on_delete=models.PROTECT)
receiver = models.ForeignKey(User, related_name='received_transfers', on_delete=models.PROTECT, null=True, blank=True)
status = models.CharField("Статус", max_length=20, choices=STATUS_CHOICES, default='sent')
created_at = models.DateTimeField(auto_now_add=True)
received_at = models.DateTimeField(null=True, blank=True)
class Meta:
verbose_name = "Перемещение"; verbose_name_plural = "Перемещения"