Corp/backend/guests/migrations/0001_initial.py
2026-09-07 19:43:48 +03:00

488 lines
19 KiB
Python
Raw Permalink 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.

import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
GUEST_ID_START = 900_000_000_000_001
GUEST_ID_MAX = 999_999_999_999_999
def create_guest_id_sequence(apps, schema_editor):
if schema_editor.connection.vendor != "postgresql":
return
with schema_editor.connection.cursor() as cursor:
cursor.execute(
"""
CREATE SEQUENCE IF NOT EXISTS guests_guest_id_seq
START WITH 900000000000001
INCREMENT BY 1
MINVALUE 900000000000001
MAXVALUE 999999999999999
NO CYCLE
"""
)
def drop_guest_id_sequence(apps, schema_editor):
if schema_editor.connection.vendor != "postgresql":
return
with schema_editor.connection.cursor() as cursor:
cursor.execute("DROP SEQUENCE IF EXISTS guests_guest_id_seq")
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("documents", "0015_delete_documentcomment"),
("employees", "0053_cleanup_department_role_permissions"),
]
operations = [
migrations.RunPython(create_guest_id_sequence, drop_guest_id_sequence),
migrations.CreateModel(
name="Guest",
fields=[
(
"id",
models.BigIntegerField(
editable=False, primary_key=True, serialize=False
),
),
("last_name", models.CharField(max_length=150, verbose_name="Фамилия")),
("first_name", models.CharField(max_length=150, verbose_name="Имя")),
(
"patronymic",
models.CharField(
blank=True, max_length=150, verbose_name="Отчество"
),
),
(
"birth_date",
models.DateField(
blank=True, null=True, verbose_name="Дата рождения"
),
),
(
"phone",
models.CharField(blank=True, max_length=64, verbose_name="Телефон"),
),
(
"email",
models.EmailField(blank=True, max_length=254, verbose_name="Email"),
),
(
"organization",
models.CharField(
blank=True, max_length=255, verbose_name="Организация"
),
),
(
"position",
models.CharField(
blank=True, max_length=255, verbose_name="Должность"
),
),
("comment", models.TextField(blank=True, verbose_name="Комментарий")),
(
"is_active",
models.BooleanField(default=True, verbose_name="Активен"),
),
(
"ldap_enabled",
models.BooleanField(default=False, verbose_name="LDAP в Active OU"),
),
(
"ldap_username",
models.CharField(
blank=True, max_length=150, verbose_name="LDAP username"
),
),
(
"ldap_upn",
models.CharField(
blank=True, max_length=255, verbose_name="LDAP UPN"
),
),
(
"ldap_last_synced_at",
models.DateTimeField(
blank=True,
null=True,
verbose_name="Последняя LDAP синхронизация",
),
),
(
"ldap_last_error",
models.TextField(blank=True, verbose_name="Последняя LDAP ошибка"),
),
(
"created_at",
models.DateTimeField(auto_now_add=True, verbose_name="Создано"),
),
(
"updated_at",
models.DateTimeField(auto_now=True, verbose_name="Обновлено"),
),
(
"created_by",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="created_guests",
to=settings.AUTH_USER_MODEL,
verbose_name="Создал",
),
),
],
options={
"verbose_name": "Гость",
"verbose_name_plural": "Гости",
"ordering": ["last_name", "first_name", "id"],
},
),
migrations.CreateModel(
name="GuestVisit",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"inviter_snapshot_name",
models.CharField(
blank=True,
max_length=255,
verbose_name="ФИО приглашающего на момент создания",
),
),
(
"inviter_snapshot_email",
models.EmailField(
blank=True,
max_length=254,
verbose_name="Email приглашающего на момент создания",
),
),
("purpose", models.TextField(verbose_name="Цель приглашения")),
(
"visit_comment",
models.TextField(blank=True, verbose_name="Комментарий заявителя"),
),
(
"admin_comment",
models.TextField(
blank=True, verbose_name="Комментарий администратора"
),
),
(
"status",
models.CharField(
choices=[
("draft", "Черновик"),
("pending", "На рассмотрении"),
("needs_info", "Требуется информация"),
("approved", "Одобрено"),
("rejected", "Отклонено"),
("cancelled", "Отменено"),
("expired", "Истекло"),
("revoked", "Отозвано"),
],
db_index=True,
default="draft",
max_length=24,
verbose_name="Статус",
),
),
(
"access_starts_at",
models.DateTimeField(
blank=True, null=True, verbose_name="Начало доступа"
),
),
(
"access_expires_at",
models.DateTimeField(
blank=True, null=True, verbose_name="Окончание доступа"
),
),
(
"all_day",
models.BooleanField(default=True, verbose_name="Полные сутки"),
),
(
"unlimited",
models.BooleanField(default=False, verbose_name="Бессрочно"),
),
(
"submitted_at",
models.DateTimeField(
blank=True, null=True, verbose_name="Отправлено на рассмотрение"
),
),
(
"decided_at",
models.DateTimeField(
blank=True, null=True, verbose_name="Решение принято"
),
),
(
"decision_comment",
models.TextField(blank=True, verbose_name="Комментарий к решению"),
),
("cancelled_at", models.DateTimeField(blank=True, null=True)),
("cancel_reason", models.TextField(blank=True)),
("revoked_at", models.DateTimeField(blank=True, null=True)),
("revoke_reason", models.TextField(blank=True)),
("expired_at", models.DateTimeField(blank=True, null=True)),
("inviter_inactive", models.BooleanField(db_index=True, default=False)),
(
"created_at",
models.DateTimeField(auto_now_add=True, verbose_name="Создано"),
),
(
"updated_at",
models.DateTimeField(auto_now=True, verbose_name="Обновлено"),
),
(
"cancelled_by",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="cancelled_guest_visits",
to=settings.AUTH_USER_MODEL,
),
),
(
"decided_by",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="decided_guest_visits",
to=settings.AUTH_USER_MODEL,
verbose_name="Решение принял",
),
),
(
"documents",
models.ManyToManyField(
blank=True,
related_name="guest_visits",
to="documents.document",
verbose_name="Документы",
),
),
(
"guest",
models.ForeignKey(
on_delete=django.db.models.deletion.PROTECT,
related_name="visits",
to="guests.guest",
verbose_name="Гость",
),
),
(
"host_department",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="guest_visits",
to="employees.department",
verbose_name="Отдел приглашающего",
),
),
(
"inviter",
models.ForeignKey(
on_delete=django.db.models.deletion.PROTECT,
related_name="guest_visits",
to=settings.AUTH_USER_MODEL,
verbose_name="Приглашающий",
),
),
(
"revoked_by",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="revoked_guest_visits",
to=settings.AUTH_USER_MODEL,
),
),
],
options={
"verbose_name": "Гостевой визит",
"verbose_name_plural": "Гостевые визиты",
"ordering": ["-created_at"],
"permissions": [
("view_all_guestvisit", "Может просматривать все гостевые визиты"),
(
"decide_guestvisit",
"Может принимать решения по гостевым визитам",
),
("manage_guestaccount", "Может управлять гостевыми учетками"),
],
},
),
migrations.CreateModel(
name="GuestVisitEvent",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"event_type",
models.CharField(
choices=[
("created", "Создано"),
("submitted", "Отправлено"),
("needs_info_requested", "Запрошена информация"),
("info_provided", "Информация предоставлена"),
("approved", "Одобрено"),
("rejected", "Отклонено"),
("decision_changed", "Решение изменено"),
("cancelled", "Отменено"),
("revoked", "Отозвано"),
("expired", "Истекло"),
("ldap_created", "LDAP создан"),
("ldap_updated", "LDAP обновлен"),
("ldap_enabled", "LDAP перемещен в Active OU"),
("ldap_disabled", "LDAP перемещен в Deactivated OU"),
("ldap_failed", "Ошибка LDAP"),
("ldap_skipped", "LDAP пропущен"),
("document_attached", "Документ прикреплен"),
("document_removed", "Документ удален"),
("inviter_inactive_detected", "Приглашающий неактивен"),
],
db_index=True,
max_length=48,
verbose_name="Тип события",
),
),
("from_status", models.CharField(blank=True, max_length=24)),
("to_status", models.CharField(blank=True, max_length=24)),
("comment", models.TextField(blank=True)),
("metadata", models.JSONField(blank=True, default=dict)),
("created_at", models.DateTimeField(auto_now_add=True)),
(
"actor",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="guest_visit_events",
to=settings.AUTH_USER_MODEL,
verbose_name="Автор события",
),
),
(
"visit",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="events",
to="guests.guestvisit",
verbose_name="Визит",
),
),
],
options={
"verbose_name": "Событие гостевого визита",
"verbose_name_plural": "События гостевых визитов",
"ordering": ["-created_at", "-id"],
},
),
migrations.AddIndex(
model_name="guest",
index=models.Index(
fields=["last_name", "first_name"], name="guest_name_idx"
),
),
migrations.AddIndex(
model_name="guest",
index=models.Index(fields=["email"], name="guest_email_idx"),
),
migrations.AddIndex(
model_name="guest",
index=models.Index(fields=["phone"], name="guest_phone_idx"),
),
migrations.AddIndex(
model_name="guest",
index=models.Index(fields=["ldap_enabled"], name="guest_ldap_enabled_idx"),
),
migrations.AddConstraint(
model_name="guest",
constraint=models.CheckConstraint(
condition=models.Q(
("id__gte", GUEST_ID_START), ("id__lte", GUEST_ID_MAX)
),
name="guest_id_in_guest_range",
),
),
migrations.AddIndex(
model_name="guestvisit",
index=models.Index(
fields=["status", "created_at"], name="guestvisit_status_created_idx"
),
),
migrations.AddIndex(
model_name="guestvisit",
index=models.Index(
fields=["inviter", "created_at"], name="guestvisit_inviter_created_idx"
),
),
migrations.AddIndex(
model_name="guestvisit",
index=models.Index(
fields=["access_starts_at", "access_expires_at"],
name="guestvisit_access_idx",
),
),
migrations.AddIndex(
model_name="guestvisit",
index=models.Index(
fields=["guest", "status"], name="guestvisit_guest_status_idx"
),
),
migrations.AddConstraint(
model_name="guestvisit",
constraint=models.CheckConstraint(
condition=models.Q(
("unlimited", True),
("access_expires_at__isnull", True),
("access_starts_at__isnull", True),
("access_starts_at__lt", models.F("access_expires_at")),
_connector="OR",
),
name="guest_visit_access_range_valid",
),
),
migrations.AddIndex(
model_name="guestvisitevent",
index=models.Index(
fields=["visit", "-created_at"], name="guestevent_visit_created_idx"
),
),
migrations.AddIndex(
model_name="guestvisitevent",
index=models.Index(
fields=["event_type", "-created_at"], name="guestevent_type_created_idx"
),
),
]