""" Management команда для создания демо-заказов на разные даты ВАЖНО: Создает заказы через Django ORM, что автоматически активирует сигналы резервирования товаров! """ from django.core.management.base import BaseCommand from django.utils import timezone from django.db import connection from datetime import datetime, timedelta import random from decimal import Decimal from orders.models import Order, OrderItem, Address, Recipient from customers.models import Customer from inventory.models import Warehouse from products.models import Product class Command(BaseCommand): help = 'Создает демо-заказы через ORM (с автоматическим резервированием товаров)' def add_arguments(self, parser): parser.add_argument( '--count', type=int, default=25, help='Количество заказов для создания (по умолчанию: 25)' ) parser.add_argument( '--schema', type=str, default='grach', help='Схема базы данных (tenant) для создания заказов' ) def handle(self, *args, **options): count = options['count'] schema_name = options['schema'] # Устанавливаем схему для работы с tenant with connection.cursor() as cursor: cursor.execute(f'SET search_path TO {schema_name}') self.stdout.write(f'[НАЧАЛО] Создание {count} демо-заказов в схеме {schema_name}...') self.stdout.write('[INFO] Заказы создаются через ORM - резервы товаров будут созданы автоматически!') # Проверяем наличие необходимых данных customers = list(Customer.objects.all()) if not customers: self.stdout.write(self.style.ERROR('Нет клиентов в базе! Создайте хотя бы одного клиента.')) return products = list(Product.objects.all()) if not products: self.stdout.write(self.style.ERROR('Нет товаров в базе! Создайте хотя бы один товар.')) return addresses = list(Address.objects.all()) warehouses = list(Warehouse.objects.filter(is_pickup_point=True)) if not addresses and not warehouses: self.stdout.write(self.style.ERROR('Нет ни адресов, ни складов для самовывоза! Создайте хотя бы что-то одно.')) return # Статусы и их вероятности statuses = [ ('new', 0.15), ('confirmed', 0.25), ('in_assembly', 0.20), ('in_delivery', 0.15), ('delivered', 0.20), ('cancelled', 0.05), ] payment_statuses = [ ('unpaid', 0.30), ('partial', 0.20), ('paid', 0.50), ] payment_methods = [ 'cash_to_courier', 'card_to_courier', 'online', 'bank_transfer', ] # Генерируем даты в диапазоне ±15 дней от сегодня today = datetime.now().date() created_count = 0 for i in range(count): try: # Случайная дата доставки days_offset = random.randint(-15, 15) delivery_date = today + timedelta(days=days_offset) # Выбираем клиента customer = random.choice(customers) # Выбираем тип доставки is_delivery = random.choice([True, False]) if addresses and shops else bool(addresses) # Создаем заказ order = Order() order.customer = customer order.is_delivery = is_delivery # Устанавливаем адрес или магазин if is_delivery and addresses: # Для доставки выбираем случайный адрес (адреса теперь привязаны к заказам) order.delivery_address = random.choice(addresses) order.delivery_cost = Decimal(random.randint(200, 500)) elif warehouses: order.pickup_warehouse = random.choice(warehouses) order.delivery_cost = Decimal(0) # Дата и время order.delivery_date = delivery_date if random.random() > 0.3: # 70% заказов с указанным временем start_hour = random.randint(9, 18) order.delivery_time_start = f"{start_hour:02d}:00:00" order.delivery_time_end = f"{start_hour + 2:02d}:00:00" # Статус status_choices = [s[0] for s in statuses] status_weights = [s[1] for s in statuses] order.status = random.choices(status_choices, weights=status_weights)[0] # Способ оплаты order.payment_method = random.choice(payment_methods) # Дополнительная информация if random.random() > 0.7: # 30% - подарок другому человеку # Создаем получателя recipient_name = f"Получатель {i+1}" recipient_phone = f"+7{random.randint(9000000000, 9999999999)}" recipient, created = Recipient.objects.get_or_create( name=recipient_name, phone=recipient_phone ) order.recipient = recipient if random.random() > 0.8: # 20% анонимных order.is_anonymous = True if random.random() > 0.5: # 50% с комментариями comments = [ "Позвонить за час до доставки", "Доставить точно в указанное время", "Не звонить в дверь, только по телефону", "Упаковать покрасивее", "Приложить открытку", ] order.special_instructions = random.choice(comments) # Сохраняем заказ (чтобы получить ID) order.save() # Добавляем товары в заказ items_count = random.randint(1, 4) order_products = random.sample(products, min(items_count, len(products))) items_total = Decimal(0) for product in order_products: item = OrderItem() item.order = order item.product = product item.quantity = random.randint(1, 3) item.price = product.price item.save() items_total += item.get_total_price() # Рассчитываем итоговую сумму order.total_amount = items_total + order.delivery_cost # Скидка (20% заказов) if random.random() > 0.8: order.discount_amount = Decimal(random.randint(100, 500)) order.total_amount -= order.discount_amount # Статус оплаты payment_status_choices = [s[0] for s in payment_statuses] payment_status_weights = [s[1] for s in payment_statuses] order.payment_status = random.choices(payment_status_choices, weights=payment_status_weights)[0] if order.payment_status == 'paid': order.amount_paid = order.total_amount order.is_paid = True elif order.payment_status == 'partial': order.amount_paid = order.total_amount * Decimal(random.uniform(0.2, 0.8)) order.is_paid = False else: order.amount_paid = Decimal(0) order.is_paid = False order.save() created_count += 1 self.stdout.write(f' [OK] Заказ #{order.order_number} на {delivery_date} (товаров: {len(order_products)})') except Exception as e: self.stdout.write(self.style.ERROR(f'[ОШИБКА] Заказ {i+1}: {str(e)}')) self.stdout.write(self.style.SUCCESS(f'\n[ЗАВЕРШЕНО] Успешно создано {created_count} заказов!')) self.stdout.write(f'Даты доставки: от {today - timedelta(days=15)} до {today + timedelta(days=15)}') self.stdout.write(self.style.SUCCESS('\n[ВАЖНО] Резервы товаров созданы автоматически через Django сигналы!'))