Обновил модели: добавил Компании и Габариты
All checks were successful
Deploy MES Core / deploy (push) Successful in 9s
All checks were successful
Deploy MES Core / deploy (push) Successful in 9s
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
# Generated by Django 6.0.3 on 2026-03-28 08:48
|
||||
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('shiftflow', '0001_initial'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Company',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=255, unique=True, verbose_name='Название компании')),
|
||||
('description', models.TextField(blank=True, verbose_name='Краткое описание / Примечание')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Компания',
|
||||
'verbose_name_plural': 'Компании',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Material',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=255, unique=True, verbose_name='Наименование')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Материал',
|
||||
'verbose_name_plural': 'Материалы',
|
||||
},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='item',
|
||||
options={'ordering': ['-date', 'deal'], 'verbose_name': 'Позиция', 'verbose_name_plural': 'Сменное задание'},
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='item',
|
||||
name='dim_value',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='item',
|
||||
name='priority',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='item',
|
||||
name='drawing_file',
|
||||
field=models.FileField(blank=True, null=True, upload_to='drawings/%Y/%m/', verbose_name='Исходник (DXF/STEP)'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='item',
|
||||
name='extra_drawing',
|
||||
field=models.FileField(blank=True, null=True, upload_to='extra_drawings/%Y/%m/', verbose_name='Доп. чертеж (PDF)'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='item',
|
||||
name='is_bend',
|
||||
field=models.BooleanField(default=False, verbose_name='Гибка'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='item',
|
||||
name='is_synced_1c',
|
||||
field=models.BooleanField(default=False, verbose_name='Учтено в 1С'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='item',
|
||||
name='material_taken',
|
||||
field=models.TextField(blank=True, help_text='Напр: 3 трубы по 12м', verbose_name='Взятый материал'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='item',
|
||||
name='operator',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='Исполнитель'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='item',
|
||||
name='scrap_weight',
|
||||
field=models.FloatField(default=0.0, verbose_name='Лом (кг)'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='item',
|
||||
name='size_value',
|
||||
field=models.FloatField(default=0, help_text='Длина (мм) или Толщина (мм)', verbose_name='Размер детали'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='item',
|
||||
name='usable_waste',
|
||||
field=models.TextField(blank=True, help_text='Напр: кусок 1500мм', verbose_name='Деловой отход'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='item',
|
||||
name='date',
|
||||
field=models.DateField(default=django.utils.timezone.now, verbose_name='Дата задания'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='item',
|
||||
name='drawing_name',
|
||||
field=models.CharField(blank=True, default='Б/ч', max_length=255, verbose_name='Название детали'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='item',
|
||||
name='status',
|
||||
field=models.CharField(choices=[('work', 'В работе'), ('done', 'Выполнено'), ('partial', 'Частично'), ('leftover', 'Недодел')], default='work', max_length=10, verbose_name='Статус'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='machine',
|
||||
name='name',
|
||||
field=models.CharField(max_length=100, verbose_name='Название станка'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Deal',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('number', models.CharField(max_length=100, unique=True, verbose_name='№ Сделки')),
|
||||
('description', models.TextField(blank=True, help_text='Общая информация по заказу', verbose_name='Описание сделки')),
|
||||
('company', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='shiftflow.company', verbose_name='Заказчик')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Сделка',
|
||||
'verbose_name_plural': 'Сделки',
|
||||
},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='item',
|
||||
name='deal',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='shiftflow.deal', verbose_name='Сделка'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='item',
|
||||
name='material',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='shiftflow.material', verbose_name='Материал'),
|
||||
),
|
||||
]
|
||||
@@ -1,40 +1,97 @@
|
||||
from django.db import models
|
||||
|
||||
# Create your models here.
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
class Company(models.Model):
|
||||
"""
|
||||
Справочник контрагентов/заказчиков.
|
||||
Позволяет группировать сделки по компаниям и избегать дублей в названиях.
|
||||
"""
|
||||
name = models.CharField("Название компании", max_length=255, unique=True)
|
||||
description = models.TextField("Краткое описание / Примечание", blank=True)
|
||||
|
||||
def __str__(self): return self.name
|
||||
class Meta:
|
||||
verbose_name = "Компания"; verbose_name_plural = "Компании"
|
||||
|
||||
class Machine(models.Model):
|
||||
name = models.CharField("Станок", max_length=100) # Лентопил, Труборез, Лазер
|
||||
"""
|
||||
Список производственных участков (станков).
|
||||
Используется для фильтрации сменных заданий для конкретных операторов.
|
||||
"""
|
||||
name = models.CharField("Название станка", max_length=100)
|
||||
|
||||
def __str__(self): return self.name
|
||||
class Meta:
|
||||
verbose_name = "Станок"; verbose_name_plural = "Станки"
|
||||
|
||||
class Deal(models.Model):
|
||||
"""
|
||||
Заказ или проект. Номер парсится из пути к файлам.
|
||||
Служит контейнером для группы деталей (позиций).
|
||||
"""
|
||||
number = models.CharField("№ Сделки", max_length=100, unique=True)
|
||||
company = models.ForeignKey(Company, on_delete=models.PROTECT, verbose_name="Заказчик", null=True, blank=True)
|
||||
description = models.TextField("Описание сделки", blank=True, help_text="Общая информация по заказу")
|
||||
|
||||
def __str__(self): return f"Сделка №{self.number} ({self.company})"
|
||||
class Meta:
|
||||
verbose_name = "Сделка"; verbose_name_plural = "Сделки"
|
||||
|
||||
class Material(models.Model):
|
||||
"""
|
||||
Справочник ТМЦ (Трубы, листы, профили).
|
||||
Необходим для точного списания остатков и синхронизации с 1С.
|
||||
"""
|
||||
name = models.CharField("Наименование", max_length=255, unique=True)
|
||||
|
||||
def __str__(self): return self.name
|
||||
class Meta:
|
||||
verbose_name = "Материал"; verbose_name_plural = "Материалы"
|
||||
|
||||
class Item(models.Model):
|
||||
"""
|
||||
Единица сменного задания. Основная рабочая сущность.
|
||||
Статус по умолчанию 'work' (В работе).
|
||||
"""
|
||||
STATUS_CHOICES = [
|
||||
('new', 'В задании'),
|
||||
('work', 'В работе'),
|
||||
('done', 'Выполнено'),
|
||||
('partial', 'Частично'),
|
||||
('leftover', 'Недодел'),
|
||||
]
|
||||
|
||||
date = models.DateField("Дата", default=timezone.now)
|
||||
# --- База (заполняет начальник) ---
|
||||
date = models.DateField("Дата задания", default=timezone.now)
|
||||
machine = models.ForeignKey(Machine, on_delete=models.PROTECT, verbose_name="Станок")
|
||||
deal = models.CharField("№ Сделки", max_length=100) # Твои "Переходники" или заказы
|
||||
drawing_name = models.CharField("Чертеж / Деталь", max_length=255)
|
||||
deal = models.ForeignKey(Deal, on_delete=models.CASCADE, verbose_name="Сделка")
|
||||
|
||||
# Характеристики из твоих файлов
|
||||
material = models.CharField("Материал", max_length=255) # Труба 180х32, MS 12.00mm и т.д.
|
||||
dim_value = models.FloatField("Размер (мм)", help_text="Длина реза или толщина листа")
|
||||
drawing_name = models.CharField("Название детали", max_length=255, blank=True, default="Б/ч")
|
||||
size_value = models.FloatField("Размер детали", help_text="Длина (мм) или Толщина (мм)")
|
||||
|
||||
drawing_file = models.FileField("Исходник (DXF/STEP)", upload_to="drawings/%Y/%m/", blank=True, null=True)
|
||||
extra_drawing = models.FileField("Доп. чертеж (PDF)", upload_to="extra_drawings/%Y/%m/", blank=True, null=True)
|
||||
|
||||
material = models.ForeignKey(Material, on_delete=models.PROTECT, verbose_name="Материал")
|
||||
quantity_plan = models.PositiveIntegerField("План, шт")
|
||||
is_bend = models.BooleanField("Гибка", default=False)
|
||||
|
||||
# --- Исполнение (заполняет оператор/мастер) ---
|
||||
operator = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, verbose_name="Исполнитель")
|
||||
quantity_fact = models.PositiveIntegerField("Факт, шт", default=0)
|
||||
|
||||
priority = models.PositiveIntegerField("Приоритет", default=10)
|
||||
status = models.CharField("Статус", max_length=10, choices=STATUS_CHOICES, default='new')
|
||||
material_taken = models.TextField("Взятый материал", blank=True, help_text="Напр: 3 трубы по 12м")
|
||||
usable_waste = models.TextField("Деловой отход", blank=True, help_text="Напр: кусок 1500мм")
|
||||
scrap_weight = models.FloatField("Лом (кг)", default=0.0)
|
||||
|
||||
# --- Статусы и учет ---
|
||||
status = models.CharField("Статус", max_length=10, choices=STATUS_CHOICES, default='work')
|
||||
is_synced_1c = models.BooleanField("Учтено в 1С", default=False)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Позиция"; verbose_name_plural = "Сменное задание"
|
||||
ordering = ['-date', 'priority']
|
||||
ordering = ['-date', 'deal']
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.drawing_name} ({self.deal})"
|
||||
return f"{self.drawing_name} ({self.quantity_plan} шт.)"
|
||||
|
||||
Reference in New Issue
Block a user