718 lines
28 KiB
Python
718 lines
28 KiB
Python
# Generated by Django 5.2.4 on 2025-12-08 12:20
|
||
|
||
from decimal import Decimal
|
||
|
||
import django.core.validators
|
||
import django.db.models.deletion
|
||
from django.conf import settings
|
||
from django.db import migrations, models
|
||
|
||
|
||
class Migration(migrations.Migration):
|
||
initial = True
|
||
|
||
dependencies = [
|
||
("employees", "0034_alter_employee_telegram"),
|
||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||
]
|
||
|
||
operations = [
|
||
migrations.CreateModel(
|
||
name="Supplier",
|
||
fields=[
|
||
(
|
||
"id",
|
||
models.BigAutoField(
|
||
auto_created=True,
|
||
primary_key=True,
|
||
serialize=False,
|
||
verbose_name="ID",
|
||
),
|
||
),
|
||
("name", models.CharField(max_length=255, verbose_name="Название")),
|
||
(
|
||
"contact_person",
|
||
models.CharField(
|
||
blank=True, max_length=255, verbose_name="Контактное лицо"
|
||
),
|
||
),
|
||
(
|
||
"phone",
|
||
models.CharField(blank=True, max_length=50, verbose_name="Телефон"),
|
||
),
|
||
(
|
||
"email",
|
||
models.EmailField(blank=True, max_length=254, verbose_name="Email"),
|
||
),
|
||
("address", models.TextField(blank=True, verbose_name="Адрес")),
|
||
("website", models.URLField(blank=True, verbose_name="Веб-сайт")),
|
||
(
|
||
"inn",
|
||
models.CharField(
|
||
blank=True,
|
||
help_text="ИНН организации (10 или 12 цифр)",
|
||
max_length=12,
|
||
verbose_name="ИНН",
|
||
),
|
||
),
|
||
(
|
||
"rating",
|
||
models.DecimalField(
|
||
decimal_places=2,
|
||
default=Decimal("0.00"),
|
||
max_digits=3,
|
||
validators=[
|
||
django.core.validators.MinValueValidator(Decimal("0.00"))
|
||
],
|
||
verbose_name="Рейтинг",
|
||
),
|
||
),
|
||
(
|
||
"is_active",
|
||
models.BooleanField(default=True, verbose_name="Активен"),
|
||
),
|
||
("notes", models.TextField(blank=True, verbose_name="Примечания")),
|
||
(
|
||
"created_at",
|
||
models.DateTimeField(auto_now_add=True, verbose_name="Создано"),
|
||
),
|
||
(
|
||
"updated_at",
|
||
models.DateTimeField(auto_now=True, verbose_name="Обновлено"),
|
||
),
|
||
],
|
||
options={
|
||
"verbose_name": "Поставщик",
|
||
"verbose_name_plural": "Поставщики",
|
||
"ordering": ["name"],
|
||
},
|
||
),
|
||
migrations.CreateModel(
|
||
name="EquipmentCategory",
|
||
fields=[
|
||
(
|
||
"id",
|
||
models.BigAutoField(
|
||
auto_created=True,
|
||
primary_key=True,
|
||
serialize=False,
|
||
verbose_name="ID",
|
||
),
|
||
),
|
||
(
|
||
"name",
|
||
models.CharField(
|
||
max_length=100, unique=True, verbose_name="Название"
|
||
),
|
||
),
|
||
("description", models.TextField(blank=True, verbose_name="Описание")),
|
||
(
|
||
"icon",
|
||
models.CharField(
|
||
blank=True,
|
||
help_text="Например: bi-laptop, bi-printer",
|
||
max_length=50,
|
||
verbose_name="Иконка Bootstrap",
|
||
),
|
||
),
|
||
(
|
||
"created_at",
|
||
models.DateTimeField(auto_now_add=True, verbose_name="Создано"),
|
||
),
|
||
(
|
||
"parent",
|
||
models.ForeignKey(
|
||
blank=True,
|
||
null=True,
|
||
on_delete=django.db.models.deletion.CASCADE,
|
||
related_name="children",
|
||
to="procurement.equipmentcategory",
|
||
verbose_name="Родительская категория",
|
||
),
|
||
),
|
||
],
|
||
options={
|
||
"verbose_name": "Категория оборудования",
|
||
"verbose_name_plural": "Категории оборудования",
|
||
"ordering": ["name"],
|
||
},
|
||
),
|
||
migrations.CreateModel(
|
||
name="Equipment",
|
||
fields=[
|
||
(
|
||
"id",
|
||
models.BigAutoField(
|
||
auto_created=True,
|
||
primary_key=True,
|
||
serialize=False,
|
||
verbose_name="ID",
|
||
),
|
||
),
|
||
("name", models.CharField(max_length=255, verbose_name="Название")),
|
||
(
|
||
"inventory_number",
|
||
models.CharField(
|
||
help_text="Например: INV-2024-0001",
|
||
max_length=50,
|
||
unique=True,
|
||
verbose_name="Инвентарный номер",
|
||
),
|
||
),
|
||
(
|
||
"serial_number",
|
||
models.CharField(
|
||
blank=True,
|
||
help_text="Серийный номер производителя",
|
||
max_length=100,
|
||
verbose_name="Серийный номер",
|
||
),
|
||
),
|
||
(
|
||
"status",
|
||
models.CharField(
|
||
choices=[
|
||
("available", "Доступно"),
|
||
("in_use", "В использовании"),
|
||
("maintenance", "На обслуживании"),
|
||
("repair", "В ремонте"),
|
||
("retired", "Списано"),
|
||
("lost", "Утеряно"),
|
||
],
|
||
default="available",
|
||
max_length=20,
|
||
verbose_name="Статус",
|
||
),
|
||
),
|
||
(
|
||
"location",
|
||
models.CharField(
|
||
blank=True,
|
||
help_text="Например: Офис 3.14, Стеллаж А-5",
|
||
max_length=255,
|
||
verbose_name="Расположение",
|
||
),
|
||
),
|
||
("purchase_date", models.DateField(verbose_name="Дата покупки")),
|
||
(
|
||
"warranty_until",
|
||
models.DateField(blank=True, null=True, verbose_name="Гарантия до"),
|
||
),
|
||
(
|
||
"purchase_cost",
|
||
models.DecimalField(
|
||
decimal_places=2,
|
||
max_digits=12,
|
||
validators=[
|
||
django.core.validators.MinValueValidator(Decimal("0.01"))
|
||
],
|
||
verbose_name="Стоимость покупки",
|
||
),
|
||
),
|
||
("notes", models.TextField(blank=True, verbose_name="Примечания")),
|
||
(
|
||
"created_at",
|
||
models.DateTimeField(auto_now_add=True, verbose_name="Создано"),
|
||
),
|
||
(
|
||
"updated_at",
|
||
models.DateTimeField(auto_now=True, verbose_name="Обновлено"),
|
||
),
|
||
(
|
||
"department",
|
||
models.ForeignKey(
|
||
on_delete=django.db.models.deletion.PROTECT,
|
||
related_name="equipment",
|
||
to="employees.department",
|
||
verbose_name="Отдел",
|
||
),
|
||
),
|
||
(
|
||
"responsible_person",
|
||
models.ForeignKey(
|
||
blank=True,
|
||
null=True,
|
||
on_delete=django.db.models.deletion.SET_NULL,
|
||
related_name="responsible_equipment",
|
||
to=settings.AUTH_USER_MODEL,
|
||
verbose_name="Ответственный",
|
||
),
|
||
),
|
||
(
|
||
"category",
|
||
models.ForeignKey(
|
||
on_delete=django.db.models.deletion.PROTECT,
|
||
related_name="equipment",
|
||
to="procurement.equipmentcategory",
|
||
verbose_name="Категория",
|
||
),
|
||
),
|
||
],
|
||
options={
|
||
"verbose_name": "Оборудование",
|
||
"verbose_name_plural": "Оборудование",
|
||
"ordering": ["-created_at"],
|
||
},
|
||
),
|
||
migrations.CreateModel(
|
||
name="MaintenanceRecord",
|
||
fields=[
|
||
(
|
||
"id",
|
||
models.BigAutoField(
|
||
auto_created=True,
|
||
primary_key=True,
|
||
serialize=False,
|
||
verbose_name="ID",
|
||
),
|
||
),
|
||
("date", models.DateField(verbose_name="Дата обслуживания")),
|
||
(
|
||
"type",
|
||
models.CharField(
|
||
choices=[
|
||
("inspection", "Осмотр/проверка"),
|
||
("maintenance", "Плановое ТО"),
|
||
("repair", "Ремонт"),
|
||
("upgrade", "Модернизация"),
|
||
("cleaning", "Чистка"),
|
||
],
|
||
max_length=20,
|
||
verbose_name="Тип обслуживания",
|
||
),
|
||
),
|
||
(
|
||
"description",
|
||
models.TextField(
|
||
help_text="Что было сделано", verbose_name="Описание"
|
||
),
|
||
),
|
||
(
|
||
"cost",
|
||
models.DecimalField(
|
||
decimal_places=2,
|
||
default=Decimal("0.00"),
|
||
max_digits=10,
|
||
validators=[
|
||
django.core.validators.MinValueValidator(Decimal("0.00"))
|
||
],
|
||
verbose_name="Стоимость",
|
||
),
|
||
),
|
||
(
|
||
"next_maintenance_date",
|
||
models.DateField(
|
||
blank=True, null=True, verbose_name="Следующее ТО"
|
||
),
|
||
),
|
||
(
|
||
"created_at",
|
||
models.DateTimeField(auto_now_add=True, verbose_name="Создано"),
|
||
),
|
||
(
|
||
"equipment",
|
||
models.ForeignKey(
|
||
on_delete=django.db.models.deletion.CASCADE,
|
||
related_name="maintenance_history",
|
||
to="procurement.equipment",
|
||
verbose_name="Оборудование",
|
||
),
|
||
),
|
||
(
|
||
"performed_by",
|
||
models.ForeignKey(
|
||
on_delete=django.db.models.deletion.PROTECT,
|
||
related_name="performed_maintenance",
|
||
to=settings.AUTH_USER_MODEL,
|
||
verbose_name="Выполнил",
|
||
),
|
||
),
|
||
],
|
||
options={
|
||
"verbose_name": "Запись обслуживания",
|
||
"verbose_name_plural": "Записи обслуживания",
|
||
"ordering": ["-date"],
|
||
},
|
||
),
|
||
migrations.CreateModel(
|
||
name="ProcurementRequest",
|
||
fields=[
|
||
(
|
||
"id",
|
||
models.BigAutoField(
|
||
auto_created=True,
|
||
primary_key=True,
|
||
serialize=False,
|
||
verbose_name="ID",
|
||
),
|
||
),
|
||
(
|
||
"title",
|
||
models.CharField(
|
||
help_text="Краткое название заявки",
|
||
max_length=255,
|
||
verbose_name="Название",
|
||
),
|
||
),
|
||
(
|
||
"description",
|
||
models.TextField(
|
||
help_text="Подробное описание и обоснование необходимости закупки",
|
||
verbose_name="Описание",
|
||
),
|
||
),
|
||
(
|
||
"status",
|
||
models.CharField(
|
||
choices=[
|
||
("draft", "Черновик"),
|
||
("pending", "На согласовании"),
|
||
("approved", "Одобрено"),
|
||
("rejected", "Отклонено"),
|
||
("in_progress", "В работе"),
|
||
("completed", "Завершено"),
|
||
("cancelled", "Отменено"),
|
||
],
|
||
default="draft",
|
||
max_length=20,
|
||
verbose_name="Статус",
|
||
),
|
||
),
|
||
(
|
||
"urgency",
|
||
models.CharField(
|
||
choices=[
|
||
("low", "Низкая"),
|
||
("medium", "Средняя"),
|
||
("high", "Высокая"),
|
||
("critical", "Критическая"),
|
||
],
|
||
default="medium",
|
||
max_length=20,
|
||
verbose_name="Срочность",
|
||
),
|
||
),
|
||
(
|
||
"estimated_cost",
|
||
models.DecimalField(
|
||
decimal_places=2,
|
||
default=Decimal("0.00"),
|
||
max_digits=12,
|
||
validators=[
|
||
django.core.validators.MinValueValidator(Decimal("0.01"))
|
||
],
|
||
verbose_name="Предполагаемая стоимость",
|
||
),
|
||
),
|
||
(
|
||
"actual_cost",
|
||
models.DecimalField(
|
||
blank=True,
|
||
decimal_places=2,
|
||
max_digits=12,
|
||
null=True,
|
||
validators=[
|
||
django.core.validators.MinValueValidator(Decimal("0.01"))
|
||
],
|
||
verbose_name="Фактическая стоимость",
|
||
),
|
||
),
|
||
(
|
||
"created_at",
|
||
models.DateTimeField(auto_now_add=True, verbose_name="Создано"),
|
||
),
|
||
(
|
||
"updated_at",
|
||
models.DateTimeField(auto_now=True, verbose_name="Обновлено"),
|
||
),
|
||
(
|
||
"submitted_at",
|
||
models.DateTimeField(
|
||
blank=True, null=True, verbose_name="Отправлено на согласование"
|
||
),
|
||
),
|
||
(
|
||
"completed_at",
|
||
models.DateTimeField(
|
||
blank=True, null=True, verbose_name="Завершено"
|
||
),
|
||
),
|
||
(
|
||
"department",
|
||
models.ForeignKey(
|
||
on_delete=django.db.models.deletion.PROTECT,
|
||
related_name="procurement_requests",
|
||
to="employees.department",
|
||
verbose_name="Отдел",
|
||
),
|
||
),
|
||
(
|
||
"requestor",
|
||
models.ForeignKey(
|
||
on_delete=django.db.models.deletion.PROTECT,
|
||
related_name="procurement_requests",
|
||
to=settings.AUTH_USER_MODEL,
|
||
verbose_name="Заявитель",
|
||
),
|
||
),
|
||
],
|
||
options={
|
||
"verbose_name": "Заявка на закупку",
|
||
"verbose_name_plural": "Заявки на закупку",
|
||
"ordering": ["-created_at"],
|
||
"permissions": [
|
||
("approve_procurementrequest", "Can approve procurement requests"),
|
||
("view_all_requests", "Can view all department requests"),
|
||
("execute_procurement", "Can execute approved requests"),
|
||
],
|
||
},
|
||
),
|
||
migrations.CreateModel(
|
||
name="ProcurementItem",
|
||
fields=[
|
||
(
|
||
"id",
|
||
models.BigAutoField(
|
||
auto_created=True,
|
||
primary_key=True,
|
||
serialize=False,
|
||
verbose_name="ID",
|
||
),
|
||
),
|
||
(
|
||
"name",
|
||
models.CharField(
|
||
help_text="Название товара или услуги",
|
||
max_length=255,
|
||
verbose_name="Название",
|
||
),
|
||
),
|
||
(
|
||
"description",
|
||
models.TextField(
|
||
blank=True,
|
||
help_text="Подробное описание, технические характеристики",
|
||
verbose_name="Описание",
|
||
),
|
||
),
|
||
(
|
||
"quantity",
|
||
models.PositiveIntegerField(
|
||
default=1,
|
||
validators=[django.core.validators.MinValueValidator(1)],
|
||
verbose_name="Количество",
|
||
),
|
||
),
|
||
(
|
||
"unit",
|
||
models.CharField(
|
||
default="шт",
|
||
help_text="Например: шт, кг, л, упак, м",
|
||
max_length=50,
|
||
verbose_name="Единица измерения",
|
||
),
|
||
),
|
||
(
|
||
"estimated_unit_price",
|
||
models.DecimalField(
|
||
decimal_places=2,
|
||
max_digits=12,
|
||
validators=[
|
||
django.core.validators.MinValueValidator(Decimal("0.01"))
|
||
],
|
||
verbose_name="Цена за единицу",
|
||
),
|
||
),
|
||
(
|
||
"supplier_info",
|
||
models.TextField(
|
||
blank=True,
|
||
help_text="Ссылки на товар, контакты поставщика",
|
||
verbose_name="Информация о поставщике",
|
||
),
|
||
),
|
||
(
|
||
"created_at",
|
||
models.DateTimeField(auto_now_add=True, verbose_name="Создано"),
|
||
),
|
||
(
|
||
"equipment",
|
||
models.OneToOneField(
|
||
blank=True,
|
||
help_text="Связь с оборудованием после закупки",
|
||
null=True,
|
||
on_delete=django.db.models.deletion.SET_NULL,
|
||
related_name="procurement_item",
|
||
to="procurement.equipment",
|
||
verbose_name="Оборудование",
|
||
),
|
||
),
|
||
(
|
||
"request",
|
||
models.ForeignKey(
|
||
on_delete=django.db.models.deletion.CASCADE,
|
||
related_name="items",
|
||
to="procurement.procurementrequest",
|
||
verbose_name="Заявка",
|
||
),
|
||
),
|
||
],
|
||
options={
|
||
"verbose_name": "Позиция заявки",
|
||
"verbose_name_plural": "Позиции заявок",
|
||
"ordering": ["id"],
|
||
},
|
||
),
|
||
migrations.CreateModel(
|
||
name="Budget",
|
||
fields=[
|
||
(
|
||
"id",
|
||
models.BigAutoField(
|
||
auto_created=True,
|
||
primary_key=True,
|
||
serialize=False,
|
||
verbose_name="ID",
|
||
),
|
||
),
|
||
(
|
||
"year",
|
||
models.PositiveIntegerField(
|
||
help_text="Например: 2025", verbose_name="Год"
|
||
),
|
||
),
|
||
(
|
||
"quarter",
|
||
models.PositiveIntegerField(
|
||
choices=[
|
||
(1, "1 квартал"),
|
||
(2, "2 квартал"),
|
||
(3, "3 квартал"),
|
||
(4, "4 квартал"),
|
||
],
|
||
verbose_name="Квартал",
|
||
),
|
||
),
|
||
(
|
||
"allocated_amount",
|
||
models.DecimalField(
|
||
decimal_places=2,
|
||
max_digits=14,
|
||
validators=[
|
||
django.core.validators.MinValueValidator(Decimal("0.00"))
|
||
],
|
||
verbose_name="Выделено",
|
||
),
|
||
),
|
||
(
|
||
"spent_amount",
|
||
models.DecimalField(
|
||
decimal_places=2,
|
||
default=Decimal("0.00"),
|
||
max_digits=14,
|
||
validators=[
|
||
django.core.validators.MinValueValidator(Decimal("0.00"))
|
||
],
|
||
verbose_name="Потрачено",
|
||
),
|
||
),
|
||
(
|
||
"created_at",
|
||
models.DateTimeField(auto_now_add=True, verbose_name="Создано"),
|
||
),
|
||
(
|
||
"updated_at",
|
||
models.DateTimeField(auto_now=True, verbose_name="Обновлено"),
|
||
),
|
||
(
|
||
"department",
|
||
models.ForeignKey(
|
||
on_delete=django.db.models.deletion.CASCADE,
|
||
related_name="budgets",
|
||
to="employees.department",
|
||
verbose_name="Отдел",
|
||
),
|
||
),
|
||
],
|
||
options={
|
||
"verbose_name": "Бюджет",
|
||
"verbose_name_plural": "Бюджеты",
|
||
"ordering": ["-year", "-quarter"],
|
||
"unique_together": {("department", "year", "quarter")},
|
||
},
|
||
),
|
||
migrations.CreateModel(
|
||
name="Approval",
|
||
fields=[
|
||
(
|
||
"id",
|
||
models.BigAutoField(
|
||
auto_created=True,
|
||
primary_key=True,
|
||
serialize=False,
|
||
verbose_name="ID",
|
||
),
|
||
),
|
||
(
|
||
"role",
|
||
models.CharField(
|
||
choices=[
|
||
("department_head", "Руководитель отдела"),
|
||
("finance_manager", "Финансовый менеджер"),
|
||
("director", "Генеральный директор"),
|
||
],
|
||
help_text="Роль согласующего в процессе",
|
||
max_length=20,
|
||
verbose_name="Роль",
|
||
),
|
||
),
|
||
(
|
||
"status",
|
||
models.CharField(
|
||
choices=[
|
||
("pending", "Ожидает решения"),
|
||
("approved", "Одобрено"),
|
||
("rejected", "Отклонено"),
|
||
],
|
||
default="pending",
|
||
max_length=20,
|
||
verbose_name="Статус",
|
||
),
|
||
),
|
||
("comment", models.TextField(blank=True, verbose_name="Комментарий")),
|
||
(
|
||
"created_at",
|
||
models.DateTimeField(auto_now_add=True, verbose_name="Создано"),
|
||
),
|
||
(
|
||
"updated_at",
|
||
models.DateTimeField(auto_now=True, verbose_name="Обновлено"),
|
||
),
|
||
(
|
||
"approver",
|
||
models.ForeignKey(
|
||
on_delete=django.db.models.deletion.PROTECT,
|
||
related_name="procurement_approvals",
|
||
to=settings.AUTH_USER_MODEL,
|
||
verbose_name="Согласующий",
|
||
),
|
||
),
|
||
(
|
||
"request",
|
||
models.ForeignKey(
|
||
on_delete=django.db.models.deletion.CASCADE,
|
||
related_name="approvals",
|
||
to="procurement.procurementrequest",
|
||
verbose_name="Заявка",
|
||
),
|
||
),
|
||
],
|
||
options={
|
||
"verbose_name": "Согласование",
|
||
"verbose_name_plural": "Согласования",
|
||
"ordering": ["created_at"],
|
||
"unique_together": {("request", "role")},
|
||
},
|
||
),
|
||
]
|