Конкретно пересмотрел логику работы. Легаси вынесена в архив
All checks were successful
Deploy MES Core / deploy (push) Successful in 13s

This commit is contained in:
2026-04-13 07:36:57 +03:00
parent 86215c9fa8
commit 28537447f8
80 changed files with 10246 additions and 684 deletions

View File

@@ -1,14 +1,30 @@
from django.db import models
class RouteStub(models.Model):
"""Маршрут (пока заглушка под техпроцессы)."""
class Operation(models.Model):
"""Операция техпроцесса.
name = models.CharField("Маршрут", max_length=200, unique=True)
Комментарий: справочник расширяется без изменений кода.
"""
name = models.CharField('Операция', max_length=200, unique=True)
code = models.SlugField(
'Код',
max_length=64,
unique=True,
help_text='Стабильный идентификатор (например welding, painting, laser_cutting).',
)
workshop = models.ForeignKey(
'shiftflow.Workshop',
on_delete=models.PROTECT,
null=True,
blank=True,
verbose_name='Цех по умолчанию',
)
class Meta:
verbose_name = "Маршрут"
verbose_name_plural = "Маршруты"
verbose_name = 'Операция'
verbose_name_plural = 'Операции'
def __str__(self):
return self.name
@@ -48,13 +64,6 @@ class ProductEntity(models.Model):
blank=True,
verbose_name="Заложенный материал",
)
route = models.ForeignKey(
RouteStub,
on_delete=models.SET_NULL,
null=True,
blank=True,
verbose_name="Маршрут",
)
blank_area_m2 = models.FloatField("Норма: площадь заготовки (м²/шт)", null=True, blank=True)
blank_length_mm = models.FloatField("Норма: длина заготовки (мм/шт)", null=True, blank=True)
@@ -74,6 +83,23 @@ class ProductEntity(models.Model):
return base if base else self.name
class EntityOperation(models.Model):
"""Операции техпроцесса для конкретной сущности (деталь/сборка/изделие)."""
entity = models.ForeignKey(ProductEntity, on_delete=models.CASCADE, related_name='operations', verbose_name='Сущность')
operation = models.ForeignKey(Operation, on_delete=models.PROTECT, verbose_name='Операция')
seq = models.PositiveSmallIntegerField('Порядок', default=1)
class Meta:
verbose_name = 'Операция сущности'
verbose_name_plural = 'Операции сущностей'
ordering = ('entity', 'seq', 'id')
unique_together = ('entity', 'seq')
def __str__(self):
return f"{self.entity}: {self.seq}. {self.operation}"
class BOM(models.Model):
"""Спецификация (BOM): parent состоит из child в количестве quantity."""
@@ -103,6 +129,9 @@ class BOM(models.Model):
class AssemblyPassport(models.Model):
entity = models.OneToOneField(ProductEntity, on_delete=models.CASCADE, related_name='assembly_passport')
requires_welding = models.BooleanField('Требуется сварка', default=False)
requires_painting = models.BooleanField('Требуется покраска', default=False)
weight_kg = models.FloatField('Масса, кг', null=True, blank=True)
coating = models.CharField('Покрытие', max_length=200, blank=True, default='')
coating_color = models.CharField('Цвет', max_length=100, blank=True, default='')