Обновления в orders: модели заказов и элементов, миграции и удаление старых миграций

This commit is contained in:
2026-01-08 22:11:51 +03:00
parent 2d1f8b78ad
commit 8590b5907c
6 changed files with 17 additions and 158 deletions

View File

@@ -1,10 +1,8 @@
# Generated by Django 5.0.10 on 2026-01-03 23:23 # Generated by Django 5.0.10 on 2026-01-08 15:58
import django.db.models.deletion import django.db.models.deletion
import phonenumber_field.modelfields import phonenumber_field.modelfields
import simple_history.models
from decimal import Decimal from decimal import Decimal
from django.conf import settings
from django.db import migrations, models from django.db import migrations, models
@@ -13,9 +11,7 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
('customers', '0001_initial'),
('inventory', '0001_initial'), ('inventory', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
] ]
operations = [ operations = [
@@ -199,7 +195,7 @@ class Migration(migrations.Migration):
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('delivery_type', models.CharField(choices=[('courier', 'Доставка курьером'), ('pickup', 'Самовывоз')], db_index=True, default='courier', max_length=20, verbose_name='Способ доставки')), ('delivery_type', models.CharField(choices=[('courier', 'Доставка курьером'), ('pickup', 'Самовывоз')], db_index=True, default='courier', max_length=20, verbose_name='Способ доставки')),
('delivery_date', models.DateField(help_text='Дата, когда должна быть выполнена доставка', verbose_name='Дата доставки')), ('delivery_date', models.DateField(blank=True, help_text='Дата, когда должна быть выполнена доставка (обязательна для не-черновиков)', null=True, verbose_name='Дата доставки')),
('time_from', models.TimeField(blank=True, help_text='Начальное время временного интервала доставки (необязательно)', null=True, verbose_name='Время доставки от')), ('time_from', models.TimeField(blank=True, help_text='Начальное время временного интервала доставки (необязательно)', null=True, verbose_name='Время доставки от')),
('time_to', models.TimeField(blank=True, help_text='Конечное время временного интервала доставки (необязательно)', null=True, verbose_name='Время доставки до')), ('time_to', models.TimeField(blank=True, help_text='Конечное время временного интервала доставки (необязательно)', null=True, verbose_name='Время доставки до')),
('cost', models.DecimalField(decimal_places=2, default=0, help_text='Стоимость доставки в рублях. 0 для бесплатной доставки/самовывоза', max_digits=10, verbose_name='Стоимость доставки')), ('cost', models.DecimalField(decimal_places=2, default=0, help_text='Стоимость доставки в рублях. 0 для бесплатной доставки/самовывоза', max_digits=10, verbose_name='Стоимость доставки')),
@@ -214,65 +210,4 @@ class Migration(migrations.Migration):
'ordering': ['-created_at'], 'ordering': ['-created_at'],
}, },
), ),
migrations.CreateModel(
name='HistoricalOrder',
fields=[
('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
('order_number', models.PositiveIntegerField(db_index=True, editable=False, help_text='Уникальный номер заказа', verbose_name='Номер заказа')),
('is_returned', models.BooleanField(default=False, help_text='True если заказ был выполнен, но потом отменен или возвращен клиентом', verbose_name='Возвращен')),
('last_autosave_at', models.DateTimeField(blank=True, help_text='Время последнего автоматического сохранения черновика', null=True, verbose_name='Последнее автосохранение')),
('is_paid', models.BooleanField(default=False, verbose_name='Оплачен')),
('total_amount', models.DecimalField(decimal_places=2, default=0, help_text='Общая сумма заказа', max_digits=10, verbose_name='Итоговая сумма заказа')),
('amount_paid', models.DecimalField(decimal_places=2, default=0, help_text='Сумма, внесенная клиентом', max_digits=10, verbose_name='Оплачено')),
('payment_status', models.CharField(choices=[('unpaid', 'Не оплачен'), ('partial', 'Частично оплачен'), ('paid', 'Оплачен полностью')], default='unpaid', help_text='Обновляется автоматически при добавлении платежей', max_length=20, verbose_name='Статус оплаты')),
('is_anonymous', models.BooleanField(default=False, help_text='Не сообщать получателю имя отправителя', verbose_name='Анонимная доставка')),
('special_instructions', models.TextField(blank=True, help_text='Комментарии и пожелания к заказу', null=True, verbose_name='Особые пожелания')),
('needs_product_photo', models.BooleanField(default=False, help_text='Требуется фотография товара перед отправкой', verbose_name='Необходимо фото товара')),
('needs_delivery_photo', models.BooleanField(default=False, help_text='Требуется фотография процесса вручения заказа', verbose_name='Необходимо фото вручения')),
('created_at', models.DateTimeField(blank=True, editable=False, verbose_name='Дата создания')),
('updated_at', models.DateTimeField(blank=True, editable=False, verbose_name='Дата обновления')),
('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField(db_index=True)),
('history_change_reason', models.CharField(max_length=100, null=True)),
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
('customer', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='customers.customer', verbose_name='Клиент')),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
('modified_by', models.ForeignKey(blank=True, db_constraint=False, help_text='Последний пользователь, изменивший заказ', null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='Изменен пользователем')),
],
options={
'verbose_name': 'historical Заказ',
'verbose_name_plural': 'historical Заказы',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': ('history_date', 'history_id'),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
migrations.CreateModel(
name='HistoricalOrderItem',
fields=[
('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
('item_name_snapshot', models.CharField(default='', max_length=200, verbose_name='Название на момент заказа')),
('item_sku_snapshot', models.CharField(blank=True, max_length=100, verbose_name='Артикул на момент заказа')),
('quantity', models.DecimalField(decimal_places=3, default=1, help_text='Количество в единицах продажи (может быть дробным)', max_digits=10, verbose_name='Количество')),
('price', models.DecimalField(decimal_places=2, help_text='Цена на момент создания заказа (фиксируется)', max_digits=10, verbose_name='Цена за единицу')),
('is_custom_price', models.BooleanField(default=False, help_text='True если цена была изменена вручную при создании заказа', verbose_name='Цена изменена вручную')),
('is_from_showcase', models.BooleanField(default=False, help_text='True если товар продан с витрины', verbose_name='С витрины')),
('unit_name_snapshot', models.CharField(blank=True, default='', help_text='Название единицы продажи на момент заказа', max_length=100, verbose_name='Название единицы (snapshot)')),
('conversion_factor_snapshot', models.DecimalField(blank=True, decimal_places=6, help_text='Коэффициент конверсии на момент заказа', max_digits=15, null=True, verbose_name='Коэффициент конверсии (snapshot)')),
('quantity_in_base_units', models.DecimalField(blank=True, decimal_places=6, help_text='Количество в единицах хранения товара (для списания со склада)', max_digits=10, null=True, verbose_name='Количество в базовых единицах')),
('created_at', models.DateTimeField(blank=True, editable=False, verbose_name='Дата добавления')),
('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField(db_index=True)),
('history_change_reason', models.CharField(max_length=100, null=True)),
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'historical Позиция заказа',
'verbose_name_plural': 'historical Позиции заказа',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': ('history_date', 'history_id'),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
] ]

View File

@@ -1,7 +1,6 @@
# Generated by Django 5.0.10 on 2026-01-03 23:23 # Generated by Django 5.0.10 on 2026-01-08 15:58
import django.db.models.deletion import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models from django.db import migrations, models
@@ -10,34 +9,14 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
('accounts', '0001_initial'),
('customers', '0002_initial'), ('customers', '0002_initial'),
('inventory', '0002_initial'), ('inventory', '0002_initial'),
('orders', '0001_initial'), ('orders', '0001_initial'),
('products', '0001_initial'), ('products', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
] ]
operations = [ operations = [
migrations.AddField(
model_name='historicalorderitem',
name='product',
field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='products.product', verbose_name='Товар'),
),
migrations.AddField(
model_name='historicalorderitem',
name='product_kit',
field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='products.productkit', verbose_name='Комплект товаров'),
),
migrations.AddField(
model_name='historicalorderitem',
name='sales_unit',
field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='products.productsalesunit', verbose_name='Единица продажи'),
),
migrations.AddField(
model_name='historicalorderitem',
name='showcase',
field=models.ForeignKey(blank=True, db_constraint=False, help_text='Витрина, с которой был продан товар', null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='inventory.showcase', verbose_name='Витрина'),
),
migrations.AddField( migrations.AddField(
model_name='kititemsnapshot', model_name='kititemsnapshot',
name='original_product', name='original_product',
@@ -53,11 +32,6 @@ class Migration(migrations.Migration):
name='kit_snapshot', name='kit_snapshot',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to='orders.kitsnapshot', verbose_name='Снимок комплекта'), field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to='orders.kitsnapshot', verbose_name='Снимок комплекта'),
), ),
migrations.AddField(
model_name='historicalorderitem',
name='kit_snapshot',
field=models.ForeignKey(blank=True, db_constraint=False, help_text='Хранит состав комплекта на момент оформления заказа', null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='orders.kitsnapshot', verbose_name='Снимок комплекта'),
),
migrations.AddField( migrations.AddField(
model_name='order', model_name='order',
name='customer', name='customer',
@@ -66,12 +40,7 @@ class Migration(migrations.Migration):
migrations.AddField( migrations.AddField(
model_name='order', model_name='order',
name='modified_by', name='modified_by',
field=models.ForeignKey(blank=True, help_text='Последний пользователь, изменивший заказ', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='modified_orders', to=settings.AUTH_USER_MODEL, verbose_name='Изменен пользователем'), field=models.ForeignKey(blank=True, help_text='Последний пользователь, изменивший заказ', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='modified_orders', to='accounts.customuser', verbose_name='Изменен пользователем'),
),
migrations.AddField(
model_name='historicalorderitem',
name='order',
field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='orders.order', verbose_name='Заказ'),
), ),
migrations.AddField( migrations.AddField(
model_name='delivery', model_name='delivery',
@@ -111,27 +80,22 @@ class Migration(migrations.Migration):
migrations.AddField( migrations.AddField(
model_name='orderstatus', model_name='orderstatus',
name='created_by', name='created_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_order_statuses', to=settings.AUTH_USER_MODEL, verbose_name='Создано'), field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_order_statuses', to='accounts.customuser', verbose_name='Создано'),
), ),
migrations.AddField( migrations.AddField(
model_name='orderstatus', model_name='orderstatus',
name='updated_by', name='updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='updated_order_statuses', to=settings.AUTH_USER_MODEL, verbose_name='Последнее изменение'), field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='updated_order_statuses', to='accounts.customuser', verbose_name='Последнее изменение'),
), ),
migrations.AddField( migrations.AddField(
model_name='order', model_name='order',
name='status', name='status',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='orders', to='orders.orderstatus', verbose_name='Статус заказа'), field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='orders', to='orders.orderstatus', verbose_name='Статус заказа'),
), ),
migrations.AddField(
model_name='historicalorder',
name='status',
field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='orders.orderstatus', verbose_name='Статус заказа'),
),
migrations.AddField( migrations.AddField(
model_name='paymentmethod', model_name='paymentmethod',
name='created_by', name='created_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_payment_methods', to=settings.AUTH_USER_MODEL, verbose_name='Создано'), field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_payment_methods', to='accounts.customuser', verbose_name='Создано'),
), ),
migrations.AddIndex( migrations.AddIndex(
model_name='recipient', model_name='recipient',
@@ -150,15 +114,10 @@ class Migration(migrations.Migration):
name='recipient', name='recipient',
field=models.ForeignKey(blank=True, help_text='Заполняется, если покупатель не является получателем', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='orders', to='orders.recipient', verbose_name='Получатель'), field=models.ForeignKey(blank=True, help_text='Заполняется, если покупатель не является получателем', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='orders', to='orders.recipient', verbose_name='Получатель'),
), ),
migrations.AddField(
model_name='historicalorder',
name='recipient',
field=models.ForeignKey(blank=True, db_constraint=False, help_text='Заполняется, если покупатель не является получателем', null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='orders.recipient', verbose_name='Получатель'),
),
migrations.AddField( migrations.AddField(
model_name='transaction', model_name='transaction',
name='created_by', name='created_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='transactions_created', to=settings.AUTH_USER_MODEL, verbose_name='Создал'), field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='transactions_created', to='accounts.customuser', verbose_name='Создал'),
), ),
migrations.AddField( migrations.AddField(
model_name='transaction', model_name='transaction',
@@ -239,6 +198,10 @@ class Migration(migrations.Migration):
model_name='orderstatus', model_name='orderstatus',
index=models.Index(fields=['order'], name='orders_orde_order_2e2930_idx'), index=models.Index(fields=['order'], name='orders_orde_order_2e2930_idx'),
), ),
migrations.AddConstraint(
model_name='orderstatus',
constraint=models.CheckConstraint(check=models.Q(('is_positive_end', True), ('is_negative_end', True), _negated=True), name='not_both_positive_and_negative_end', violation_error_message='Статус не может быть одновременно положительным и отрицательным концом'),
),
migrations.AddIndex( migrations.AddIndex(
model_name='paymentmethod', model_name='paymentmethod',
index=models.Index(fields=['code'], name='orders_paym_code_f40d7e_idx'), index=models.Index(fields=['code'], name='orders_paym_code_f40d7e_idx'),

View File

@@ -1,18 +0,0 @@
# Generated by Django 5.0.10 on 2026-01-04 22:22
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0002_initial'),
]
operations = [
migrations.AlterField(
model_name='delivery',
name='delivery_date',
field=models.DateField(blank=True, help_text='Дата, когда должна быть выполнена доставка (обязательна для не-черновиков)', null=True, verbose_name='Дата доставки'),
),
]

View File

@@ -1,19 +0,0 @@
# Generated by Django 5.0.10 on 2026-01-05 14:00
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0003_allow_null_delivery_date_for_drafts'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AddConstraint(
model_name='orderstatus',
constraint=models.CheckConstraint(check=models.Q(('is_positive_end', True), ('is_negative_end', True), _negated=True), name='not_both_positive_and_negative_end', violation_error_message='Статус не может быть одновременно положительным и отрицательным концом'),
),
]

View File

@@ -1,7 +1,6 @@
from django.db import models from django.db import models
from accounts.models import CustomUser from accounts.models import CustomUser
from customers.models import Customer from customers.models import Customer
from simple_history.models import HistoricalRecords
from .status import OrderStatus from .status import OrderStatus
from .recipient import Recipient from .recipient import Recipient
@@ -152,8 +151,8 @@ class Order(models.Model):
help_text="Последний пользователь, изменивший заказ" help_text="Последний пользователь, изменивший заказ"
) )
# История изменений # TODO: История изменений (simple_history) - вернуть позже
history = HistoricalRecords() # history = HistoricalRecords()
class Meta: class Meta:
verbose_name = "Заказ" verbose_name = "Заказ"

View File

@@ -2,7 +2,6 @@ from decimal import Decimal
from django.db import models from django.db import models
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from products.models import Product, ProductKit from products.models import Product, ProductKit
from simple_history.models import HistoricalRecords
from .order import Order from .order import Order
from .kit_snapshot import KitSnapshot from .kit_snapshot import KitSnapshot
@@ -139,8 +138,8 @@ class OrderItem(models.Model):
verbose_name="Дата добавления" verbose_name="Дата добавления"
) )
# История изменений # TODO: История изменений (simple_history) - вернуть позже
history = HistoricalRecords() # history = HistoricalRecords()
class Meta: class Meta:
verbose_name = "Позиция заказа" verbose_name = "Позиция заказа"