feat: MVP-скелет площадки (Django + MySQL/SQLite, модели по ТЗ §4, базовые страницы)
This commit is contained in:
1 parent
e5f312a00f
commit
8218a568ce
67 files changed
+1929
No files matched your search
@@ -0,0 +1,133 @@
|
||||
# Generated by Django 5.1.15 on 2026-09-23 13:44
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Brand',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=200, verbose_name='Название бренда')),
|
||||
('slug', models.SlugField(blank=True, max_length=220, unique=True, verbose_name='Slug')),
|
||||
('logo', models.ImageField(blank=True, null=True, upload_to='brands/logos/', verbose_name='Логотип')),
|
||||
('cover', models.ImageField(blank=True, null=True, upload_to='brands/covers/', verbose_name='Обложка')),
|
||||
('story', models.TextField(blank=True, max_length=3000, verbose_name='История бренда')),
|
||||
('legal_status', models.CharField(choices=[('self_employed', 'Самозанятый'), ('ip', 'ИП'), ('legal', 'Юрлицо')], default='self_employed', max_length=20, verbose_name='Правовой статус')),
|
||||
('inn', models.CharField(blank=True, max_length=12, verbose_name='ИНН')),
|
||||
('region', models.CharField(blank=True, max_length=120, verbose_name='Регион')),
|
||||
('city', models.CharField(blank=True, max_length=120, verbose_name='Город')),
|
||||
('socials', models.JSONField(blank=True, default=dict, verbose_name='Соцсети')),
|
||||
('verification_status', models.CharField(choices=[('pending', 'На проверке'), ('approved', 'Одобрен'), ('revision', 'На доработке'), ('rejected', 'Отклонён')], default='pending', max_length=20, verbose_name='Статус верификации')),
|
||||
('badges', models.JSONField(blank=True, default=list, verbose_name='Знаки')),
|
||||
('rating', models.DecimalField(decimal_places=2, default=0, max_digits=3, verbose_name='Рейтинг')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')),
|
||||
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='brand', to=settings.AUTH_USER_MODEL, verbose_name='Владелец')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Бренд',
|
||||
'verbose_name_plural': 'Бренды',
|
||||
'ordering': ('name',),
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Category',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=200, verbose_name='Название')),
|
||||
('slug', models.SlugField(blank=True, max_length=220, unique=True, verbose_name='Slug')),
|
||||
('type', models.CharField(choices=[('product', 'Товар'), ('service', 'Услуга')], default='product', max_length=10, verbose_name='Тип')),
|
||||
('sort_order', models.PositiveIntegerField(default=0, verbose_name='Порядок сортировки')),
|
||||
('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='catalog.category', verbose_name='Родитель')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Категория',
|
||||
'verbose_name_plural': 'Категории',
|
||||
'ordering': ('sort_order', 'name'),
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Product',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=255, verbose_name='Название')),
|
||||
('slug', models.SlugField(blank=True, max_length=280, unique=True, verbose_name='Slug')),
|
||||
('description', models.TextField(blank=True, verbose_name='Описание')),
|
||||
('price', models.DecimalField(decimal_places=2, max_digits=12, verbose_name='Цена')),
|
||||
('attributes', models.JSONField(blank=True, default=dict, verbose_name='Характеристики')),
|
||||
('stock', models.PositiveIntegerField(default=0, verbose_name='Остаток')),
|
||||
('lead_time_days', models.PositiveIntegerField(default=0, verbose_name='Срок изготовления, дней')),
|
||||
('moderation_status', models.CharField(choices=[('draft', 'Черновик'), ('pending', 'На модерации'), ('published', 'Опубликовано'), ('rejected', 'Отклонено')], default='draft', max_length=20, verbose_name='Статус модерации')),
|
||||
('is_active', models.BooleanField(default=True, verbose_name='Активен')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')),
|
||||
('brand', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='products', to='catalog.brand', verbose_name='Бренд')),
|
||||
('category', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='products', to='catalog.category', verbose_name='Категория')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Товар',
|
||||
'verbose_name_plural': 'Товары',
|
||||
'ordering': ('-created_at',),
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ProductImage',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('image', models.ImageField(upload_to='products/', verbose_name='Изображение')),
|
||||
('sort_order', models.PositiveIntegerField(default=0, verbose_name='Порядок')),
|
||||
('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='images', to='catalog.product', verbose_name='Товар')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Изображение товара',
|
||||
'verbose_name_plural': 'Изображения товаров',
|
||||
'ordering': ('sort_order', 'id'),
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Service',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=255, verbose_name='Название')),
|
||||
('slug', models.SlugField(blank=True, max_length=280, unique=True, verbose_name='Slug')),
|
||||
('description', models.TextField(blank=True, verbose_name='Описание')),
|
||||
('format', models.CharField(choices=[('online', 'Онлайн'), ('offline', 'Офлайн')], default='offline', max_length=10, verbose_name='Формат')),
|
||||
('duration_minutes', models.PositiveIntegerField(default=60, verbose_name='Длительность, мин')),
|
||||
('price', models.DecimalField(decimal_places=2, max_digits=12, verbose_name='Цена')),
|
||||
('moderation_status', models.CharField(choices=[('draft', 'Черновик'), ('pending', 'На модерации'), ('published', 'Опубликовано'), ('rejected', 'Отклонено')], default='draft', max_length=20, verbose_name='Статус модерации')),
|
||||
('is_active', models.BooleanField(default=True, verbose_name='Активна')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')),
|
||||
('brand', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='services', to='catalog.brand', verbose_name='Бренд')),
|
||||
('category', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='services', to='catalog.category', verbose_name='Категория')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Услуга',
|
||||
'verbose_name_plural': 'Услуги',
|
||||
'ordering': ('-created_at',),
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='TimeSlot',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('start', models.DateTimeField(verbose_name='Начало')),
|
||||
('end', models.DateTimeField(verbose_name='Окончание')),
|
||||
('is_booked', models.BooleanField(default=False, verbose_name='Занят')),
|
||||
('service', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='slots', to='catalog.service', verbose_name='Услуга')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Слот записи',
|
||||
'verbose_name_plural': 'Слоты записи',
|
||||
'ordering': ('start',),
|
||||
},
|
||||
),
|
||||
]
|
||||
Whitespace-only changes.
Reference in new issue
Block a user