diff --git a/bom_manager/admin.py b/bom_manager/admin.py index ca7607a..f3fabef 100644 --- a/bom_manager/admin.py +++ b/bom_manager/admin.py @@ -1,118 +1,159 @@ from django.contrib import admin -from mptt.admin import MPTTModelAdmin, DraggableMPTTAdmin -from .models import Item, BOMNode, EntityType, RoutingStep, WorkCenter +from mptt.admin import DraggableMPTTAdmin +from polymorphic.admin import ( + PolymorphicChildModelAdmin, + PolymorphicParentModelAdmin, + PolymorphicChildModelFilter, + PolymorphicInlineSupportMixin, + StackedPolymorphicInline +) +from .models import ( + Item, BOMNode, EntityType, WorkCenter, + BaseOperation, LaserCutSheet, LaserCutTube, + Turning, Weld, Paint, Coating +) +from django import forms -# Register your models here. +# создаем форму с фильтром для dxf и dwg файлов +class LaserCutSheetForm(forms.ModelForm): + class Meta: + model = LaserCutSheet + fields = '__all__' + widgets = { + 'dxf_file': forms.FileInput(attrs={'accept': '.dxf,.DXF'}), + } -# Создаем инлайн для отображения RoutingStep в Item -class RoutingStepInline(admin.TabularInline): - model = RoutingStep - extra = 1 - # Поле tech_params в стандартной админке — это просто текстовое поле. - # Позже его можно будет "причесать" с помощью JS, чтобы оно выглядело красиво. - fields = ('order', 'operation_type', 'work_center', 'drawing_file', 'tech_params') +# создаем форму с фильтром для iges и igs файлов +class LaserCutTubeForm(forms.ModelForm): + class Meta: + model = LaserCutTube + fields = '__all__' + widgets = { + 'iges_file': forms.FileInput(attrs={'accept': '.iges,.IGS'}), + } -# Создаем инлайн для отображения BOMNode в Item +# --- 1. ИНЛАЙНЫ ДЛЯ ОПЕРАЦИЙ (ДЛЯ КАРТОЧКИ ITEM) --- + +class LaserCutSheetInline(StackedPolymorphicInline.Child): + model = LaserCutSheet + form = LaserCutSheetForm + +class LaserCutTubeInline(StackedPolymorphicInline.Child): + model = LaserCutTube + form = LaserCutTubeForm + +class TurningInline(StackedPolymorphicInline.Child): + model = Turning + +class WeldInline(StackedPolymorphicInline.Child): + model = Weld + +class PaintInline(StackedPolymorphicInline.Child): + model = Paint + +class BaseOperationInline(StackedPolymorphicInline): + model = BaseOperation + child_inlines = ( + LaserCutSheetInline, + LaserCutTubeInline, + TurningInline, + WeldInline, + PaintInline, + ) + +# --- 2. ДОЧЕРНИЕ АДМИНКИ (НУЖНЫ ДЛЯ РАБОТЫ ПОЛИМОРФИЗМА) --- + +@admin.register(LaserCutSheet) +class LaserCutSheetAdmin(PolymorphicChildModelAdmin): + base_model = BaseOperation + form = LaserCutSheetForm + +@admin.register(LaserCutTube) +class LaserCutTubeAdmin(PolymorphicChildModelAdmin): + base_model = BaseOperation + form = LaserCutTubeForm + +@admin.register(Turning) +class TurningAdmin(PolymorphicChildModelAdmin): + base_model = BaseOperation + +@admin.register(Weld) +class WeldAdmin(PolymorphicChildModelAdmin): + base_model = BaseOperation + +@admin.register(Paint) +class PaintAdmin(PolymorphicChildModelAdmin): + base_model = BaseOperation + +# --- 3. РОДИТЕЛЬСКАЯ АДМИНКА ОПЕРАЦИЙ --- + +@admin.register(BaseOperation) +class BaseOperationParentAdmin(PolymorphicParentModelAdmin): + base_model = BaseOperation + # Здесь указываем именно МОДЕЛИ, а не классы админок + child_models = (LaserCutSheet, LaserCutTube, Turning, Weld, Paint) + list_filter = (PolymorphicChildModelFilter,) + list_display = ('item', 'order', 'polymorphic_ctype') + +# --- 4. ИНЛАЙН ДЛЯ BOM (СОСТАВ ИЗДЕЛИЯ) --- + class BOMNodeInline(admin.TabularInline): model = BOMNode - - # Указываем fk_key т - fk_name = 'parent' - - # Указываем поля для отображения в инлайне + # fk_name = 'parent' fields = ('item', 'quantity') - - # Колличество пустых строк в инлайне - extra = 3 - - # добавим автокомплит для удобства + extra = 1 autocomplete_fields = ['item'] def formfield_for_foreignkey(self, db_field, request, **kwargs): if db_field.name == "parent": - # Родителями в инлайне могут быть только Сборки/Изделия/Комплексы kwargs["queryset"] = BOMNode.objects.filter( item__entity_type__in=[EntityType.UNIT, EntityType.ASSEMBLY, EntityType.COMPLEX] ) return super().formfield_for_foreignkey(db_field, request, **kwargs) +# --- 5. ОСНОВНАЯ АДМИНКА КОМПОНЕНТА (ITEM) --- + @admin.register(Item) -class ItemAdmin(admin.ModelAdmin): +class ItemAdmin(PolymorphicInlineSupportMixin, admin.ModelAdmin): list_display = ('get_full_name', 'entity_type', 'drawing') list_filter = ('entity_type', 'is_assembly') - # Поиск по номеру и названию search_fields = ['designation', 'title'] @admin.display(description='Наименование') def get_full_name(self, obj): - return f"{obj.designation or ''} {obj.title}" + return f"{obj.designation or ''} {obj.title}".strip() - inlines = [RoutingStepInline] - # def get_queryset(self, request): - # qs = super().get_queryset(request) - # return qs.filter(entity_type=EntityType.ASSEMBLY) + # Добавляем оба инлайна: и состав, и техпроцесс + inlines = [BOMNodeInline, BaseOperationInline] + +# --- 6. АДМИНКА ДЛЯ ДЕРЕВА BOM --- @admin.register(BOMNode) class BOMNodeAdmin(DraggableMPTTAdmin): - # Настройки отображения древовидной структуры - mptt_level_indent = 40 # отступ в пикселях - - # Поля для отображения в админке + mptt_level_indent = 40 fields = ('parent', 'item', 'quantity') - -# Чтобы в списке было видно не только название связи, но и данные из Item list_display = ('tree_actions', 'indented_title', 'get_designation', 'quantity') list_display_links = ('indented_title',) - # Отображаем инлайн. - inlines = [BOMNodeInline] - - # Метод для отображения децимального номера из связанной модели Item def get_designation(self, obj): return obj.item.designation get_designation.short_description = 'Децимальный номер' - # Оптимизация запросов (чтобы админка не тормозила) def get_queryset(self, request): - qs = super().get_queryset(request) - return qs.select_related('item', 'parent') + return super().get_queryset(request).select_related('item', 'parent') - # def formfield_for_foreignkey(self, db_field, request, **kwargs): - # if db_field.name == "parent": - # # Фильтруем: родителями могут быть только узлы, - # # где связанный Item является сборкой или изделием - # kwargs["queryset"] = BOMNode.objects.filter( - # item__entity_type__in=[EntityType.UNIT, EntityType.ASSEMBLY] - # ) - # return super().formfield_for_foreignkey(db_field, request, **kwargs) - - - # переопределим метод get_inlines в BOMNodeAdmin. - # Если узел привязан к «Детали» или «Стандартному изделию», таблица внизу просто не появится. def get_inlines(self, request, obj=None): - # Если мы создаем новый узел (obj is None), инлайн можно показать - if obj is None: - return [] - - # Разрешенные типы (те, в которые МОЖНО вкладывать) - allowed_types = [EntityType.UNIT, EntityType.ASSEMBLY, EntityType.COMPLEX] - - # Если тип изделия связанного узла в списке разрешенных — показываем инлайн - if obj.item.entity_type in allowed_types: + if obj and obj.item.entity_type in [EntityType.UNIT, EntityType.ASSEMBLY, EntityType.COMPLEX]: return [BOMNodeInline] - - # Для остальных (детали, стандартные) возвращаем пустой список return [] -@admin.register(RoutingStep) -class RoutingStepAdmin(admin.ModelAdmin): - # Поля для отображения в админке - list_display = ('item', 'operation_type', 'work_center', 'order') - list_filter = ('operation_type', 'work_center') - search_fields = ['item__title'] +# --- 7. ПРОЧИЕ СПРАВОЧНИКИ --- @admin.register(WorkCenter) class WorkCenterAdmin(admin.ModelAdmin): list_display = ('name', 'rate_per_hour') - search_fields = ['name'] + +@admin.register(Coating) +class CoatingAdmin(admin.ModelAdmin): + list_display = ('name', 'consumption') \ No newline at end of file diff --git a/bom_manager/migrations/0006_baseoperation_coating_lasercutsheet_lasercuttube_and_more.py b/bom_manager/migrations/0006_baseoperation_coating_lasercutsheet_lasercuttube_and_more.py new file mode 100644 index 0000000..9b7dc12 --- /dev/null +++ b/bom_manager/migrations/0006_baseoperation_coating_lasercutsheet_lasercuttube_and_more.py @@ -0,0 +1,115 @@ +# Generated by Django 6.0.2 on 2026-02-14 10:18 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('bom_manager', '0005_workcenter_routingstep'), + ('contenttypes', '0002_remove_content_type_name'), + ] + + operations = [ + migrations.CreateModel( + name='BaseOperation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('order', models.PositiveIntegerField(default=10, help_text='Например: 10, 20, 30...', verbose_name='Номер операции')), + ('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='operations', to='bom_manager.item', verbose_name='Компонент')), + ('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')), + ('work_center', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='operations', to='bom_manager.workcenter', verbose_name='Станок/Участок')), + ], + options={ + 'verbose_name': 'Операция', + 'verbose_name_plural': 'Операции', + 'ordering': ['order'], + }, + ), + migrations.CreateModel( + name='Coating', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100, verbose_name='Название покрытия')), + ('consumption', models.DecimalField(decimal_places=2, default=0, max_digits=10, verbose_name='Расход покрытия, м2/л')), + ], + options={ + 'verbose_name': 'Покрытие', + 'verbose_name_plural': 'Покрытия', + }, + ), + migrations.CreateModel( + name='LaserCutSheet', + fields=[ + ('baseoperation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='bom_manager.baseoperation')), + ('thickness', models.IntegerField(default=3, verbose_name='Толщина листа, мм')), + ('cut_length', models.IntegerField(default=0, verbose_name='Длина реза, мм')), + ('pierces', models.IntegerField(default=1, verbose_name='Количество проколов')), + ('dxf_file', models.FileField(blank=True, null=True, upload_to='dxf_files/%Y/%m', verbose_name='DXF файл')), + ], + options={ + 'verbose_name': 'Лазерная резка листа', + 'verbose_name_plural': 'ЛРЛ', + }, + bases=('bom_manager.baseoperation',), + ), + migrations.CreateModel( + name='LaserCutTube', + fields=[ + ('baseoperation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='bom_manager.baseoperation')), + ('thinckness', models.IntegerField(default=3, verbose_name='Толщина трубы, мм')), + ('cut_length', models.IntegerField(default=0, verbose_name='Длина реза, мм')), + ('pierces', models.IntegerField(default=1, verbose_name='Количество проколов')), + ('iges_file', models.FileField(blank=True, null=True, upload_to='iges_files/%Y/%m', verbose_name='IGES файл')), + ], + options={ + 'verbose_name': 'Лазерная резка трубы', + 'verbose_name_plural': 'ЛРТ', + }, + bases=('bom_manager.baseoperation',), + ), + migrations.CreateModel( + name='Paint', + fields=[ + ('baseoperation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='bom_manager.baseoperation')), + ('area', models.DecimalField(decimal_places=2, default=0, max_digits=10, verbose_name='Площадь покраски, м2')), + ('color', models.CharField(blank=True, max_length=100, null=True, verbose_name='Код RAL')), + ('number_of_layers', models.IntegerField(default=1, verbose_name='Число слоев')), + ('coating', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='paints', to='bom_manager.coating', verbose_name='Покрытие')), + ], + options={ + 'verbose_name': 'Покраска', + 'verbose_name_plural': 'Покраски', + }, + bases=('bom_manager.baseoperation',), + ), + migrations.CreateModel( + name='Turning', + fields=[ + ('baseoperation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='bom_manager.baseoperation')), + ('work_time', models.IntegerField(default=0, verbose_name='Время работы, мин')), + ], + options={ + 'verbose_name': 'Токарная обработка', + 'verbose_name_plural': 'ТО', + }, + bases=('bom_manager.baseoperation',), + ), + migrations.CreateModel( + name='Weld', + fields=[ + ('baseoperation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='bom_manager.baseoperation')), + ('total_weld_length', models.IntegerField(default=0, verbose_name='Общая длина сварки, мм')), + ('avg_leg', models.IntegerField(default=0, verbose_name='Средний катет, мм')), + ], + options={ + 'verbose_name': 'Сварка', + 'verbose_name_plural': 'Сварки', + }, + bases=('bom_manager.baseoperation',), + ), + migrations.DeleteModel( + name='RoutingStep', + ), + ] diff --git a/bom_manager/models.py b/bom_manager/models.py index adeb517..ba10eac 100644 --- a/bom_manager/models.py +++ b/bom_manager/models.py @@ -1,8 +1,162 @@ from django.db import models from django.urls import reverse from mptt.models import MPTTModel, TreeForeignKey +from polymorphic.models import PolymorphicModel +from django.core.exceptions import ValidationError # Create your models here. +# Базовая модель операции +class BaseOperation(PolymorphicModel): + item = models.ForeignKey('Item', on_delete=models.CASCADE, related_name='operations', verbose_name="Компонент") + order = models.PositiveIntegerField("Номер операции", default=10, help_text="Например: 10, 20, 30...") + work_center = models.ForeignKey('WorkCenter', on_delete=models.CASCADE, related_name='operations', verbose_name="Станок/Участок") + + class Meta: + ordering = ['order'] + verbose_name = "Операция" + verbose_name_plural = "Операции" + + def __str__(self): + return f"{self.order}. {self._meta.verbose_name}" + + def get_absolute_url(self): + return reverse("operation_detail", kwargs={"pk": self.pk}) + + def clean(self): + if self.order < 1: + raise ValidationError("Номер операции должен быть больше 0!") + if self.work_center is None: + raise ValidationError("Станок/Участок не может быть пустым!") + +# Операция лазерной резки листа +class LaserCutSheet(BaseOperation): + thickness = models.IntegerField("Толщина листа, мм", default=3) + cut_length = models.IntegerField("Длина реза, мм", default=0) + pierces = models.IntegerField("Количество проколов", default=1) + dxf_file = models.FileField("DXF файл", upload_to='dxf_files/%Y/%m', null=True, blank=True) + + def clean(self): + if self.cut_length < 1: + raise ValidationError("Длина реза должна быть больше 0!") + if self.pierces < 1: + raise ValidationError("Количество проколов должно быть больше 0!") + if self.item.entity_type != EntityType.PART: + raise ValidationError("Компонент должен быть деталью!") + + def get_absolute_url(self): + return reverse("lrl_detail", kwargs={"pk": self.pk}) + + class Meta: + verbose_name = "Лазерная резка листа" + verbose_name_plural = "ЛРЛ" + + def __str__(self): + return f"{self.order}. {self._meta.verbose_name}" + +# Операция лазерной резки трубы +class LaserCutTube(BaseOperation): + thinckness = models.IntegerField("Толщина трубы, мм", default=3) + cut_length = models.IntegerField("Длина реза, мм", default=0) + pierces = models.IntegerField("Количество проколов", default=1) + iges_file = models.FileField("IGES файл", upload_to='iges_files/%Y/%m', null=True, blank=True) + + def clean(self): + if self.cut_length < 1: + raise ValidationError("Длина реза должна быть больше 0!") + if self.pierces < 1: + raise ValidationError("Количество проколов должно быть больше 0!") + if self.item.entity_type != EntityType.PART: + raise ValidationError("Компонент должен быть деталью!") + + + def get_absolute_url(self): + return reverse("lrt_detail", kwargs={"pk": self.pk}) + + class Meta: + verbose_name = "Лазерная резка трубы" + verbose_name_plural = "ЛРТ" + + def __str__(self): + return f"{self.order}. {self._meta.verbose_name}" + +# Операция токарной обработки +class Turning(BaseOperation): + work_time = models.IntegerField("Время работы, мин", default=0) + + def clean(self): + if self.work_time < 1: + raise ValidationError("Время работы должно быть больше 0!") + + def get_absolute_url(self): + return reverse("turning_detail", kwargs={"pk": self.pk}) + + class Meta: + verbose_name = "Токарная обработка" + verbose_name_plural = "ТО" + + def __str__(self): + return f"{self.order}. {self._meta.verbose_name}" + +# Операция сварки +class Weld(BaseOperation): + total_weld_length = models.IntegerField("Общая длина сварки, мм", default=0) + avg_leg = models.IntegerField("Средний катет, мм", default=0) + # todo: добавить реализацию швов с разными катетами + + def clean(self): + if self.total_weld_length < 1: + raise ValidationError("Общая длина сварки должна быть больше 0!") + if self.avg_leg < 1: + raise ValidationError("Средний катет должен быть больше 0!") + if self.item.entity_type not in [EntityType.ASSEMBLY, EntityType.COMPLEX, EntityType.UNIT]: + raise ValidationError("Компонент должен быть составным изделием!") + + def get_absolute_url(self): + return reverse("weld_detail", kwargs={"pk": self.pk}) + + class Meta: + verbose_name = "Сварка" + verbose_name_plural = "Сварки" + + def __str__(self): + return f"{self.order}. {self._meta.verbose_name}" + +# Операция покраски +class Paint(BaseOperation): + """Покраска""" + # площадь покраски + area = models.DecimalField("Площадь покраски, м2", max_digits=10, decimal_places=2, default=0) + # цвет по RAL + color = models.CharField("Код RAL", max_length=100, blank=True, null=True) + # число слоев + number_of_layers = models.IntegerField("Число слоев", default=1) + # покрытие из другой таблицы + coating = models.ForeignKey('Coating', on_delete=models.CASCADE, related_name='paints', verbose_name="Покрытие") + + class Meta: + verbose_name = "Покраска" + verbose_name_plural = "Покраски" + + def __str__(self): + return f"{self.order}. {self._meta.verbose_name}" + +class Coating(models.Model): + """Покрытие""" + # наименование краски/грунта + name = models.CharField("Название покрытия", max_length=100) + # расход покрытия + consumption = models.DecimalField("Расход покрытия, м2/л", max_digits=10, decimal_places=2, default=0) + + class Meta: + verbose_name = "Покрытие" + verbose_name_plural = "Покрытия" + + def __str__(self): + return self.name + +# todo: добавить операции гибки, зачистки, перемещения и лентопильного станка + + class EntityType(models.TextChoices): """Тип изделия""" UNIT = 'UNIT', 'Изделие' @@ -12,17 +166,17 @@ class EntityType(models.TextChoices): COMPLEX = 'CPLX', 'Комплекс' -class OperationType(models.TextChoices): - """Тип операции""" - LRL = 'LRL', 'Лазерная резка листа (ЛРЛ)' - LRT = 'LRT', 'Лазерная резка трубы (ЛРТ)' - TO = 'TO', 'Токарная обработка (ТО)' - WELD = 'WELD', 'Сварка' - PAINT = 'PAINT', 'Покраска' - BEND = 'BEND', 'Гибка' - CLEAN = 'CLEAN', 'Зачистка' - BANDSAW = 'BANDSAW', 'Лентопильный станок' - MOVE = 'MOVE', 'Перемещение' +# class OperationType(models.TextChoices): +# """Тип операции""" +# LRL = 'LRL', 'Лазерная резка листа (ЛРЛ)' # todo: add LRL +# LRT = 'LRT', 'Лазерная резка трубы (ЛРТ)' # todo: add LRT +# TO = 'TO', 'Токарная обработка (ТО)' +# WELD = 'WELD', 'Сварка' +# PAINT = 'PAINT', 'Покраска' +# BEND = 'BEND', 'Гибка' +# CLEAN = 'CLEAN', 'Зачистка' +# BANDSAW = 'BANDSAW', 'Лентопильный станок' +# MOVE = 'MOVE', 'Перемещение' class WorkCenter(models.Model): """Справочник станков или участков""" @@ -105,43 +259,43 @@ class BOMNode(MPTTModel): def get_absolute_url(self): return reverse("bom_node_detail", kwargs={"pk": self.pk}) -class RoutingStep(models.Model): - """Технологическая операция""" - # Связь с компонентом - item = models.ForeignKey('Item', on_delete=models.CASCADE, related_name='routing_steps', verbose_name="Деталь/Сборка") - # Тип операции - operation_type = models.CharField("Тип операции", max_length=10, choices=OperationType.choices) - # Связь с станком - work_center = models.ForeignKey(WorkCenter, on_delete=models.SET_NULL, null=True, verbose_name="Станок/Участок") - # Номер операции - order = models.PositiveIntegerField("Номер операции", default=10, help_text="Например: 10, 20, 30...") +# class RoutingStep(models.Model): +# """Технологическая операция""" +# # Связь с компонентом +# item = models.ForeignKey('Item', on_delete=models.CASCADE, related_name='routing_steps', verbose_name="Деталь/Сборка") +# # Тип операции +# operation_type = models.CharField("Тип операции", max_length=10, choices=OperationType.choices) +# # Связь с станком +# work_center = models.ForeignKey(WorkCenter, on_delete=models.SET_NULL, null=True, verbose_name="Станок/Участок") +# # Номер операции +# order = models.PositiveIntegerField("Номер операции", default=10, help_text="Например: 10, 20, 30...") - # Файлы - drawing_file = models.FileField("Тех. файл (DXF/IGES)", upload_to='tech_files/%Y/%m', null=True, blank=True) +# # Файлы +# drawing_file = models.FileField("Тех. файл (DXF/IGES)", upload_to='tech_files/%Y/%m', null=True, blank=True) - # Гибкие данные (JSON) - # Сюда будем писать: {"cut_length": 1500, "pierces": 20} или {"welds": [{"leg": 5, "length": 100}]} - tech_params = models.JSONField("Технологические параметры", default=dict, blank=True) +# # Гибкие данные (JSON) +# # Сюда будем писать: {"cut_length": 1500, "pierces": 20} или {"welds": [{"leg": 5, "length": 100}]} +# tech_params = models.JSONField("Технологические параметры", default=dict, blank=True) - # Общие поля для всех операций - setup_time = models.DurationField("Время наладки", null=True, blank=True) - cycle_time = models.DurationField("Время цикла (на 1 шт)", null=True, blank=True) +# # Общие поля для всех операций +# setup_time = models.DurationField("Время наладки", null=True, blank=True) +# cycle_time = models.DurationField("Время цикла (на 1 шт)", null=True, blank=True) - def clean(self): - if self.operation_type == OperationType.LRL: - if 'cut_length' not in self.tech_params: - raise ValidationError("Для ЛРЛ обязательно укажите 'cut_length' в параметрах!") - if 'pierces' not in self.tech_params: - raise ValidationError("Для ЛРЛ обязательно укажите 'pierces' в параметрах!") - if self.operation_type == OperationType.LRT: - if 'cut_length' not in self.tech_params: - raise ValidationError("Для ЛРТ обязательно укажите 'cut_length' в параметрах!") +# def clean(self): +# if self.operation_type == OperationType.LRL: +# if 'cut_length' not in self.tech_params: +# raise ValidationError("Для ЛРЛ обязательно укажите 'cut_length' в параметрах!") +# if 'pierces' not in self.tech_params: +# raise ValidationError("Для ЛРЛ обязательно укажите 'pierces' в параметрах!") +# if self.operation_type == OperationType.LRT: +# if 'cut_length' not in self.tech_params: +# raise ValidationError("Для ЛРТ обязательно укажите 'cut_length' в параметрах!") - class Meta: - ordering = ['order'] - verbose_name = "Технологическая операция" - verbose_name_plural = "Технологический маршрут" +# class Meta: +# ordering = ['order'] +# verbose_name = "Технологическая операция" +# verbose_name_plural = "Технологический маршрут" - def __str__(self): - return f"{self.order}. {self.get_operation_type_display()}" \ No newline at end of file +# def __str__(self): +# return f"{self.order}. {self.get_operation_type_display()}" \ No newline at end of file diff --git a/core/settings.py b/core/settings.py index 62a39bc..2609491 100644 --- a/core/settings.py +++ b/core/settings.py @@ -37,6 +37,7 @@ INSTALLED_APPS = [ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'polymorphic', # added app Polymorphic 'mptt', # added app MPTT 'bom_manager', # added app Bom Manager ] diff --git a/dxf_files/2026/02/ИИ_0093.000.02-100_Фланец_опоры.DXF b/dxf_files/2026/02/ИИ_0093.000.02-100_Фланец_опоры.DXF new file mode 100644 index 0000000..b009866 --- /dev/null +++ b/dxf_files/2026/02/ИИ_0093.000.02-100_Фланец_опоры.DXF @@ -0,0 +1,3254 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1015 + 9 +$ACADMAINTVER + 70 + 6 + 9 +$DWGCODEPAGE + 3 +ANSI_1251 + 9 +$INSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$EXTMIN + 10 +-160.0 + 20 +-160.0 + 30 +0.0 + 9 +$EXTMAX + 10 +160.0 + 20 +160.0 + 30 +0.0 + 9 +$LIMMIN + 10 +0.0 + 20 +0.0 + 9 +$LIMMAX + 10 +420.0 + 20 +297.0 + 9 +$ORTHOMODE + 70 + 0 + 9 +$REGENMODE + 70 + 1 + 9 +$FILLMODE + 70 + 1 + 9 +$QTEXTMODE + 70 + 0 + 9 +$MIRRTEXT + 70 + 1 + 9 +$LTSCALE + 40 +1.0 + 9 +$ATTMODE + 70 + 1 + 9 +$TEXTSIZE + 40 +4.0 + 9 +$TRACEWID + 40 +1.0 + 9 +$TEXTSTYLE + 7 +Standard + 9 +$CLAYER + 8 +0 + 9 +$CELTYPE + 6 +ByLayer + 9 +$CECOLOR + 62 + 256 + 9 +$CELTSCALE + 40 +1.0 + 9 +$DISPSILH + 70 + 0 + 9 +$DIMSCALE + 40 +1.0 + 9 +$DIMASZ + 40 +6.0 + 9 +$DIMEXO + 40 +0.0 + 9 +$DIMDLI + 40 +3.75 + 9 +$DIMRND + 40 +0.0 + 9 +$DIMDLE + 40 +0.0 + 9 +$DIMEXE + 40 +1.0 + 9 +$DIMTP + 40 +0.0 + 9 +$DIMTM + 40 +0.0 + 9 +$DIMTXT + 40 +4.0 + 9 +$DIMCEN + 40 +2.5 + 9 +$DIMTSZ + 40 +0.0 + 9 +$DIMTOL + 70 + 0 + 9 +$DIMLIM + 70 + 0 + 9 +$DIMTIH + 70 + 1 + 9 +$DIMTOH + 70 + 1 + 9 +$DIMSE1 + 70 + 0 + 9 +$DIMSE2 + 70 + 0 + 9 +$DIMTAD + 70 + 1 + 9 +$DIMZIN + 70 + 0 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 + 1 + 9 +$DIMSHO + 70 + 1 + 9 +$DIMPOST + 1 + + 9 +$DIMAPOST + 1 + + 9 +$DIMALT + 70 + 0 + 9 +$DIMALTD + 70 + 3 + 9 +$DIMALTF + 40 +0.0393700787 + 9 +$DIMLFAC + 40 +1.0 + 9 +$DIMTOFL + 70 + 1 + 9 +$DIMTVP + 40 +0.0 + 9 +$DIMTIX + 70 + 0 + 9 +$DIMSOXD + 70 + 0 + 9 +$DIMSAH + 70 + 0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +ISO-25 + 9 +$DIMCLRD + 70 + 0 + 9 +$DIMCLRE + 70 + 0 + 9 +$DIMCLRT + 70 + 0 + 9 +$DIMTFAC + 40 +1.0 + 9 +$DIMGAP + 40 +3.0 + 9 +$DIMJUST + 70 + 0 + 9 +$DIMSD1 + 70 + 0 + 9 +$DIMSD2 + 70 + 0 + 9 +$DIMTOLJ + 70 + 0 + 9 +$DIMTZIN + 70 + 0 + 9 +$DIMALTZ + 70 + 0 + 9 +$DIMALTTZ + 70 + 0 + 9 +$DIMUPT + 70 + 0 + 9 +$DIMDEC + 70 + 2 + 9 +$DIMTDEC + 70 + 4 + 9 +$DIMALTU + 70 + 2 + 9 +$DIMALTTD + 70 + 3 + 9 +$DIMTXSTY + 7 +Standard + 9 +$DIMAUNIT + 70 + 0 + 9 +$DIMADEC + 70 + 2 + 9 +$DIMALTRND + 40 +0.0 + 9 +$DIMAZIN + 70 + 0 + 9 +$DIMDSEP + 70 + 44 + 9 +$DIMATFIT + 70 + 3 + 9 +$DIMFRAC + 70 + 0 + 9 +$DIMLDRBLK + 1 + + 9 +$DIMLUNIT + 70 + 2 + 9 +$DIMLWD + 70 + -2 + 9 +$DIMLWE + 70 + -2 + 9 +$DIMTMOVE + 70 + 0 + 9 +$LUNITS + 70 + 2 + 9 +$LUPREC + 70 + 2 + 9 +$SKETCHINC + 40 +1.0 + 9 +$FILLETRAD + 40 +0.0 + 9 +$AUNITS + 70 + 0 + 9 +$AUPREC + 70 + 2 + 9 +$MENU + 1 +. + 9 +$ELEVATION + 40 +0.0 + 9 +$PELEVATION + 40 +0.0 + 9 +$THICKNESS + 40 +0.0 + 9 +$LIMCHECK + 70 + 0 + 9 +$CHAMFERA + 40 +0.0 + 9 +$CHAMFERB + 40 +0.0 + 9 +$CHAMFERC + 40 +0.0 + 9 +$CHAMFERD + 40 +0.0 + 9 +$SKPOLY + 70 + 0 + 9 +$TDCREATE + 40 +2461055.614086123 + 9 +$TDUCREATE + 40 +2461055.489086123 + 9 +$TDUPDATE + 40 +2461055.61411456 + 9 +$TDUUPDATE + 40 +2461055.48911456 + 9 +$TDINDWG + 40 +0.0000000116 + 9 +$TDUSRTIMER + 40 +0.0000000116 + 9 +$USRTIMER + 70 + 1 + 9 +$ANGBASE + 50 +0.0 + 9 +$ANGDIR + 70 + 0 + 9 +$PDMODE + 70 + 0 + 9 +$PDSIZE + 40 +-1.0 + 9 +$PLINEWID + 40 +0.0 + 9 +$SPLFRAME + 70 + 0 + 9 +$SPLINETYPE + 70 + 6 + 9 +$SPLINESEGS + 70 + 8 + 9 +$HANDSEED + 5 +70 + 9 +$SURFTAB1 + 70 + 6 + 9 +$SURFTAB2 + 70 + 6 + 9 +$SURFTYPE + 70 + 6 + 9 +$SURFU + 70 + 6 + 9 +$SURFV + 70 + 6 + 9 +$UCSBASE + 2 + + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$UCSORTHOREF + 2 + + 9 +$UCSORTHOVIEW + 70 + 0 + 9 +$UCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSBASE + 2 + + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$PUCSORTHOREF + 2 + + 9 +$PUCSORTHOVIEW + 70 + 0 + 9 +$PUCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$USERI1 + 70 + 0 + 9 +$USERI2 + 70 + 0 + 9 +$USERI3 + 70 + 0 + 9 +$USERI4 + 70 + 0 + 9 +$USERI5 + 70 + 0 + 9 +$USERR1 + 40 +0.0 + 9 +$USERR2 + 40 +0.0 + 9 +$USERR3 + 40 +0.0 + 9 +$USERR4 + 40 +0.0 + 9 +$USERR5 + 40 +0.0 + 9 +$WORLDVIEW + 70 + 1 + 9 +$SHADEDGE + 70 + 3 + 9 +$SHADEDIF + 70 + 70 + 9 +$TILEMODE + 70 + 1 + 9 +$MAXACTVP + 70 + 64 + 9 +$PINSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PLIMCHECK + 70 + 0 + 9 +$PEXTMIN + 10 +1.0000000000E+20 + 20 +1.0000000000E+20 + 30 +1.0000000000E+20 + 9 +$PEXTMAX + 10 +-1.0000000000E+20 + 20 +-1.0000000000E+20 + 30 +-1.0000000000E+20 + 9 +$PLIMMIN + 10 +0.0 + 20 +0.0 + 9 +$PLIMMAX + 10 +420.0 + 20 +297.0 + 9 +$UNITMODE + 70 + 0 + 9 +$VISRETAIN + 70 + 1 + 9 +$PLINEGEN + 70 + 0 + 9 +$PSLTSCALE + 70 + 1 + 9 +$TREEDEPTH + 70 + 3020 + 9 +$CMLSTYLE + 2 +Standard + 9 +$CMLJUST + 70 + 0 + 9 +$CMLSCALE + 40 +20.0 + 9 +$PROXYGRAPHICS + 70 + 1 + 9 +$MEASUREMENT + 70 + 1 + 9 +$CELWEIGHT +370 + -1 + 9 +$ENDCAPS +280 + 0 + 9 +$JOINSTYLE +280 + 0 + 9 +$LWDISPLAY +290 + 1 + 9 +$INSUNITS + 70 + 4 + 9 +$HYPERLINKBASE + 1 + + 9 +$STYLESHEET + 1 + + 9 +$XEDIT +290 + 1 + 9 +$CEPSNTYPE +380 + 0 + 9 +$PSTYLEMODE +290 + 1 + 9 +$FINGERPRINTGUID + 2 +{5f4d6ab6-4188-4900-8b1c-4d7fcd9ba3e9} + 9 +$VERSIONGUID + 2 +{FAEB1C32-E019-11D5-929B-00C0DF256EC4} + 9 +$EXTNAMES +290 + 1 + 9 +$PSVPSCALE + 40 +0.0 + 9 +$OLESTARTUP +290 + 0 + 0 +ENDSEC + 0 +SECTION + 2 +CLASSES + 0 +CLASS + 1 +ACDBDICTIONARYWDFLT + 2 +AcDbDictionaryWithDefault + 3 +ObjectDBX Classes + 90 + 0 +280 + 0 +281 + 0 + 0 +CLASS + 1 +VISUALSTYLE + 2 +AcDbVisualStyle + 3 +ObjectDBX Classes + 90 + 4095 +280 + 0 +281 + 0 + 0 +CLASS + 1 +MATERIAL + 2 +AcDbMaterial + 3 +ObjectDBX Classes + 90 + 1153 +280 + 0 +281 + 0 + 0 +CLASS + 1 +SCALE + 2 +AcDbScale + 3 +ObjectDBX Classes + 90 + 1153 +280 + 0 +281 + 0 + 0 +CLASS + 1 +TABLESTYLE + 2 +AcDbTableStyle + 3 +ObjectDBX Classes + 90 + 4095 +280 + 0 +281 + 0 + 0 +CLASS + 1 +MLEADERSTYLE + 2 +AcDbMLeaderStyle + 3 +ACDB_MLEADERSTYLE_CLASS + 90 + 4095 +280 + 0 +281 + 0 + 0 +CLASS + 1 +SUN + 2 +AcDbSun + 3 +SCENEOE + 90 + 1153 +280 + 0 +281 + 0 + 0 +CLASS + 1 +ACDBPLACEHOLDER + 2 +AcDbPlaceHolder + 3 +ObjectDBX Classes + 90 + 0 +280 + 0 +281 + 0 + 0 +CLASS + 1 +LAYOUT + 2 +AcDbLayout + 3 +ObjectDBX Classes + 90 + 0 +280 + 0 +281 + 0 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +VPORT + 5 +29 +330 +8 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*Active + 70 + 0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +0.0 + 22 +0.0 + 13 +0.0 + 23 +0.0 + 14 +10.0 + 24 +10.0 + 15 +10.0 + 25 +10.0 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +326.4 + 41 +1.0 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 + 0 + 72 + 100 + 73 + 1 + 74 + 3 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 0 +281 + 0 + 65 + 1 +110 +0.0 +120 +0.0 +130 +0.0 +111 +1.0 +121 +0.0 +131 +0.0 +112 +0.0 +122 +1.0 +132 +0.0 + 79 + 0 +146 +0.0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 + 6 + 0 +LTYPE + 5 +14 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByBlock + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +15 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByLayer + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +16 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Continuous + 70 + 0 + 3 +Solid line + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +5E +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +HIDDEN + 70 + 0 + 3 +Hidden __ __ __ __ __ __ __ __ __ __ __ __ __ __ + 72 + 65 + 73 + 2 + 40 +1.905 + 49 +1.27 + 74 + 0 + 49 +-0.635 + 74 + 0 + 0 +LTYPE + 5 +5F +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOM + 70 + 0 + 3 +Phantom ______ __ __ ______ __ __ ______ + 72 + 65 + 73 + 6 + 40 +12.7 + 49 +6.35 + 74 + 0 + 49 +-1.27 + 74 + 0 + 49 +1.27 + 74 + 0 + 49 +-1.27 + 74 + 0 + 49 +1.27 + 74 + 0 + 49 +-1.27 + 74 + 0 + 0 +LTYPE + 5 +60 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER + 70 + 0 + 3 +Center ____ _ ____ _ ____ _ ____ _ ____ _ ____ + 72 + 65 + 73 + 4 + 40 +10.16 + 49 +6.35 + 74 + 0 + 49 +-1.27 + 74 + 0 + 49 +1.27 + 74 + 0 + 49 +-1.27 + 74 + 0 + 0 +LTYPE + 5 +61 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTERX2 + 70 + 0 + 3 +Center (2x) ________ __ ________ __ _____ + 72 + 65 + 73 + 4 + 40 +20.32 + 49 +12.7 + 74 + 0 + 49 +-2.54 + 74 + 0 + 49 +2.54 + 74 + 0 + 49 +-2.54 + 74 + 0 + 0 +LTYPE + 5 +62 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT2 + 70 + 0 + 3 +Dot (.5x) ........................................ + 72 + 65 + 73 + 2 + 40 +0.635 + 49 +0.0 + 74 + 0 + 49 +-0.635 + 74 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +2 +330 +0 +100 +AcDbSymbolTable + 70 + 4 + 0 +LAYER + 5 +10 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 + 0 + 62 + 7 + 6 +Continuous +370 + -3 +390 +F + 0 +LAYER + 5 +63 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +CUT + 70 + 0 + 62 + 7 + 6 +Continuous +370 + 25 +390 +F + 0 +LAYER + 5 +64 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +MARK + 70 + 0 + 62 + 6 + 6 +PHANTOM +370 + 35 +390 +F + 0 +LAYER + 5 +65 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +MARK2 + 70 + 0 + 62 + 5 + 6 +HIDDEN +370 + -3 +390 +F + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +STYLE + 5 +11 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +Standard + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +4.0 + 3 +txt + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +APPID + 5 +12 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +A +330 +0 +100 +AcDbSymbolTable + 70 + 1 +100 +AcDbDimStyleTable + 0 +DIMSTYLE +105 +27 +330 +A +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +ISO-25 + 70 + 0 + 41 +2.5 + 42 +0.625 + 43 +3.75 + 44 +1.25 + 73 + 0 + 74 + 0 + 77 + 1 + 78 + 8 +140 +2.5 +141 +2.5 +143 +0.0393700787 +147 +0.625 +171 + 3 +172 + 1 +178 + 0 +271 + 2 +272 + 2 +274 + 3 +278 + 44 +283 + 0 +284 + 8 +340 +11 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +BLOCK_RECORD + 5 +1F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Model_Space +340 +22 + 0 +BLOCK_RECORD + 5 +1B +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space +340 +1E + 0 +BLOCK_RECORD + 5 +23 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space0 +340 +26 + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +20 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Model_Space + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Model_Space + 1 + + 0 +ENDBLK + 5 +21 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Paper_Space + 1 + + 0 +ENDBLK + 5 +1D +330 +1B +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +24 +330 +23 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space0 + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Paper_Space0 + 1 + + 0 +ENDBLK + 5 +25 +330 +23 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +LINE + 5 +66 +330 +1F +100 +AcDbEntity + 8 +CUT + 6 +Continuous +370 + 25 +100 +AcDbLine + 10 +160.0 + 20 +-160.0 + 30 +0.0 + 11 +160.0 + 21 +160.0 + 31 +0.0 + 0 +LINE + 5 +67 +330 +1F +100 +AcDbEntity + 8 +CUT + 6 +Continuous +370 + 25 +100 +AcDbLine + 10 +160.0 + 20 +160.0 + 30 +0.0 + 11 +-160.0 + 21 +160.0 + 31 +0.0 + 0 +LINE + 5 +68 +330 +1F +100 +AcDbEntity + 8 +CUT + 6 +Continuous +370 + 25 +100 +AcDbLine + 10 +-160.0 + 20 +160.0 + 30 +0.0 + 11 +-160.0 + 21 +-160.0 + 31 +0.0 + 0 +LINE + 5 +69 +330 +1F +100 +AcDbEntity + 8 +CUT + 6 +Continuous +370 + 25 +100 +AcDbLine + 10 +-160.0 + 20 +-160.0 + 30 +0.0 + 11 +160.0 + 21 +-160.0 + 31 +0.0 + 0 +CIRCLE + 5 +6A +330 +1F +100 +AcDbEntity + 8 +CUT + 6 +Continuous +370 + 25 +100 +AcDbCircle + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +111.0 + 0 +CIRCLE + 5 +6B +330 +1F +100 +AcDbEntity + 8 +CUT + 6 +Continuous +370 + 25 +100 +AcDbCircle + 10 +115.0 + 20 +115.0 + 30 +0.0 + 40 +12.00000000000001 + 0 +CIRCLE + 5 +6C +330 +1F +100 +AcDbEntity + 8 +CUT + 6 +Continuous +370 + 25 +100 +AcDbCircle + 10 +-115.0 + 20 +115.0 + 30 +0.0 + 40 +12.0 + 0 +CIRCLE + 5 +6D +330 +1F +100 +AcDbEntity + 8 +CUT + 6 +Continuous +370 + 25 +100 +AcDbCircle + 10 +-115.0 + 20 +-115.0 + 30 +0.0 + 40 +12.0 + 0 +CIRCLE + 5 +6E +330 +1F +100 +AcDbEntity + 8 +CUT + 6 +Continuous +370 + 25 +100 +AcDbCircle + 10 +115.0 + 20 +-115.0 + 30 +0.0 + 40 +12.0 + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +C +330 +0 +100 +AcDbDictionary +281 + 1 + 3 +ACAD_GROUP +350 +D + 3 +ACAD_LAYOUT +350 +1A + 3 +ACAD_MLINESTYLE +350 +17 + 3 +ACAD_PLOTSETTINGS +350 +19 + 3 +ACAD_PLOTSTYLENAME +350 +E + 3 +ACAD_SCALELIST +350 +47 + 3 +DWGPROPS +350 +6F + 0 +DICTIONARY + 5 +D +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 0 +DICTIONARY + 5 +1A +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 3 +Layout1 +350 +1E + 3 +Layout2 +350 +26 + 3 +Model +350 +22 + 0 +DICTIONARY + 5 +17 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 3 +Standard +350 +18 + 0 +DICTIONARY + 5 +19 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 0 +ACDBDICTIONARYWDFLT + 5 +E +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 3 +Normal +350 +F +100 +AcDbDictionaryWithDefault +340 +F + 0 +DICTIONARY + 5 +47 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 3 +A0 +350 +48 + 3 +A1 +350 +49 + 3 +A2 +350 +4A + 3 +A3 +350 +4B + 3 +A4 +350 +4C + 3 +A5 +350 +4D + 3 +A6 +350 +4E + 3 +A7 +350 +4F + 3 +A8 +350 +50 + 3 +A9 +350 +51 + 3 +B0 +350 +52 + 3 +B1 +350 +53 + 3 +B2 +350 +54 + 3 +B3 +350 +55 + 3 +B4 +350 +56 + 3 +B5 +350 +57 + 3 +B6 +350 +58 + 0 +XRECORD + 5 +6F +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbXrecord +280 + 1 + 1 +DWGPROPS COOKIE + 2 + + 3 + + 4 + + 6 + + 7 + + 8 +user + 9 + +300 += +301 += +302 += +303 += +304 += +305 += +306 += +307 += +308 += +309 += + 40 +0.0 + 41 +2461055.489086123 + 42 +2461055.48911456 + 1 + + 90 + 0 + 0 +LAYOUT + 5 +1E +102 +{ACAD_REACTORS +330 +1A +102 +} +330 +1A +100 +AcDbPlotSettings + 1 + + 2 +none_device + 4 + + 6 + + 40 +0.0 + 41 +0.0 + 42 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 + 688 + 72 + 1 + 73 + 0 + 74 + 5 + 7 + + 75 + 16 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Layout1 + 70 + 1 + 71 + 1 + 10 +0.0 + 20 +0.0 + 11 +420.0 + 21 +297.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +1.0000000000E+20 + 24 +1.0000000000E+20 + 34 +1.0000000000E+20 + 15 +-1.0000000000E+20 + 25 +-1.0000000000E+20 + 35 +-1.0000000000E+20 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 + 0 +330 +1B + 0 +LAYOUT + 5 +26 +102 +{ACAD_REACTORS +330 +1A +102 +} +330 +1A +100 +AcDbPlotSettings + 1 + + 2 +none_device + 4 + + 6 + + 40 +0.0 + 41 +0.0 + 42 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 + 688 + 72 + 1 + 73 + 0 + 74 + 5 + 7 + + 75 + 16 +147 +1.0 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Layout2 + 70 + 1 + 71 + 2 + 10 +0.0 + 20 +0.0 + 11 +0.0 + 21 +0.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +0.0 + 24 +0.0 + 34 +0.0 + 15 +0.0 + 25 +0.0 + 35 +0.0 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 + 0 +330 +23 + 0 +LAYOUT + 5 +22 +102 +{ACAD_REACTORS +330 +1A +102 +} +330 +1A +100 +AcDbPlotSettings + 1 + + 2 +none_device + 4 +ANSI_A_(11.00_x_8.50_Inches) + 6 + + 40 +6.35 + 41 +19.05 + 42 +6.35000508 + 43 +19.05000254 + 44 +279.4 + 45 +215.9 + 46 +133.34999746 + 47 +88.89999873 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +0.026296875 +143 +1.0 + 70 + 1696 + 72 + 0 + 73 + 0 + 74 + 0 + 7 + + 75 + 0 +147 +0.0179189148 +148 +-1300.4909072572 +149 +0.0 +100 +AcDbLayout + 1 +Model + 70 + 1 + 71 + 0 + 10 +0.0 + 20 +0.0 + 11 +420.0 + 21 +297.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +-160.0 + 24 +-160.0 + 34 +0.0 + 15 +160.0 + 25 +160.0 + 35 +0.0 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 + 0 +330 +1F +331 +29 + 0 +MLINESTYLE + 5 +18 +102 +{ACAD_REACTORS +330 +17 +102 +} +330 +17 +100 +AcDbMlineStyle + 2 +Standard + 70 + 0 + 3 + + 62 + 256 + 51 +90.0 + 52 +90.0 + 71 + 2 + 49 +0.5 + 62 + 256 + 6 +BYLAYER + 49 +-0.5 + 62 + 256 + 6 +BYLAYER + 0 +ACDBPLACEHOLDER + 5 +F +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E + 0 +SCALE + 5 +48 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbScale + 70 + 0 +300 +1:1 +140 +1.0 +141 +1.0 +290 + 1 + 0 +SCALE + 5 +49 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbScale + 70 + 0 +300 +1:2 +140 +1.0 +141 +2.0 +290 + 0 + 0 +SCALE + 5 +4A +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbScale + 70 + 0 +300 +1:4 +140 +1.0 +141 +4.0 +290 + 0 + 0 +SCALE + 5 +4B +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbScale + 70 + 0 +300 +1:5 +140 +1.0 +141 +5.0 +290 + 0 + 0 +SCALE + 5 +4C +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbScale + 70 + 0 +300 +1:8 +140 +1.0 +141 +8.0 +290 + 0 + 0 +SCALE + 5 +4D +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbScale + 70 + 0 +300 +1:10 +140 +1.0 +141 +10.0 +290 + 0 + 0 +SCALE + 5 +4E +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbScale + 70 + 0 +300 +1:16 +140 +1.0 +141 +16.0 +290 + 0 + 0 +SCALE + 5 +4F +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbScale + 70 + 0 +300 +1:20 +140 +1.0 +141 +20.0 +290 + 0 + 0 +SCALE + 5 +50 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbScale + 70 + 0 +300 +1:30 +140 +1.0 +141 +30.0 +290 + 0 + 0 +SCALE + 5 +51 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbScale + 70 + 0 +300 +1:40 +140 +1.0 +141 +40.0 +290 + 0 + 0 +SCALE + 5 +52 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbScale + 70 + 0 +300 +1:50 +140 +1.0 +141 +50.0 +290 + 0 + 0 +SCALE + 5 +53 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbScale + 70 + 0 +300 +1:100 +140 +1.0 +141 +100.0 +290 + 0 + 0 +SCALE + 5 +54 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbScale + 70 + 0 +300 +2:1 +140 +2.0 +141 +1.0 +290 + 0 + 0 +SCALE + 5 +55 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbScale + 70 + 0 +300 +4:1 +140 +4.0 +141 +1.0 +290 + 0 + 0 +SCALE + 5 +56 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbScale + 70 + 0 +300 +8:1 +140 +8.0 +141 +1.0 +290 + 0 + 0 +SCALE + 5 +57 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbScale + 70 + 0 +300 +10:1 +140 +10.0 +141 +1.0 +290 + 0 + 0 +SCALE + 5 +58 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbScale + 70 + 0 +300 +100:1 +140 +100.0 +141 +1.0 +290 + 0 + 0 +ENDSEC + 0 +EOF