From 757d120d7e665e2277720b96dcc392df2f2c7be3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=88=D0=BA=D0=B8=D0=BD=20=D0=A1=D0=B5=D1=80?= =?UTF-8?q?=D0=B3=D0=B5=D0=B9?= Date: Wed, 17 Dec 2025 11:59:04 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BA=D0=BE=D0=BC=D0=B0=D0=BD=D0=B4=D1=83=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20=D0=B3=D0=B5=D0=BD=D0=B5=D1=80=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D0=B8=20=D0=B2=D1=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../commands/generate_test_marks.py | 93 +++++++++++++++++-- 1 file changed, 83 insertions(+), 10 deletions(-) diff --git a/dbapp/mainapp/management/commands/generate_test_marks.py b/dbapp/mainapp/management/commands/generate_test_marks.py index f9ac8c7..7002c61 100644 --- a/dbapp/mainapp/management/commands/generate_test_marks.py +++ b/dbapp/mainapp/management/commands/generate_test_marks.py @@ -3,16 +3,20 @@ Management command для генерации тестовых отметок с Использование: python manage.py generate_test_marks --satellite_id=1 --user_id=1 --date_range=10.10.2025-15.10.2025 + python manage.py generate_test_marks --satellite_id=1 --user_id=1 --date_range=10.10.2025-15.10.2025 --tech_analyze_ids=1,2,3 + python manage.py generate_test_marks --satellite_id=1 --user_id=1 --date_range=10.10.2025-15.10.2025 --time_range=7:00-9:30 Параметры: --satellite_id: ID спутника (обязательный) --user_id: ID пользователя CustomUser (обязательный) --date_range: Диапазон дат в формате ДД.ММ.ГГГГ-ДД.ММ.ГГГГ (обязательный) + --tech_analyze_ids: ID теханализов через запятую (опциональный, если не указан - все теханализы спутника) + --time_range: Временной диапазон в формате ЧЧ:ММ-ЧЧ:ММ (опциональный, по умолчанию 8:00-11:00) --clear: Удалить существующие отметки перед генерацией Особенности: - Генерирует отметки только в будние дни (пн-пт) - - Время отметок: утро с 8:00 до 11:00 + - Время отметок: по умолчанию утро с 8:00 до 11:00 (настраивается через --time_range) - Одна отметка в день для всех сигналов спутника - Все отметки в один день имеют одинаковый timestamp (пакетное сохранение) - Все отметки имеют значение True (сигнал присутствует) @@ -49,16 +53,38 @@ class Command(BaseCommand): required=True, help='Диапазон дат в формате ДД.ММ.ГГГГ-ДД.ММ.ГГГГ (например: 10.10.2025-15.10.2025)' ) + parser.add_argument( + '--tech_analyze_ids', + type=str, + required=False, + help='ID теханализов через запятую (например: 1,2,3). Если не указан - все теханализы спутника' + ) + parser.add_argument( + '--time_range', + type=str, + required=False, + default='8:00-11:00', + help='Временной диапазон в формате ЧЧ:ММ-ЧЧ:ММ (например: 7:00-9:30). По умолчанию: 8:00-11:00' + ) parser.add_argument( '--clear', action='store_true', help='Удалить существующие отметки перед генерацией' ) + def parse_time(self, time_str): + """Парсит время в формате ЧЧ:ММ или Ч:ММ""" + parts = time_str.strip().split(':') + if len(parts) != 2: + raise ValueError(f'Неверный формат времени: {time_str}') + return int(parts[0]), int(parts[1]) + def handle(self, *args, **options): satellite_id = options['satellite_id'] user_id = options['user_id'] date_range = options['date_range'] + tech_analyze_ids_str = options['tech_analyze_ids'] + time_range = options['time_range'] clear = options['clear'] # Проверяем существование пользователя @@ -85,6 +111,40 @@ class Command(BaseCommand): f'Неверный формат даты. Используйте ДД.ММ.ГГГГ-ДД.ММ.ГГГГ (например: 10.10.2025-15.10.2025). Ошибка: {e}' ) + # Парсим временной диапазон + try: + time_start_str, time_end_str = time_range.split('-') + start_hour, start_minute = self.parse_time(time_start_str) + end_hour, end_minute = self.parse_time(time_end_str) + + # Валидация времени + if not (0 <= start_hour <= 23 and 0 <= start_minute <= 59): + raise ValueError(f'Некорректное начальное время: {time_start_str}') + if not (0 <= end_hour <= 23 and 0 <= end_minute <= 59): + raise ValueError(f'Некорректное конечное время: {time_end_str}') + + # Конвертируем в минуты для удобства сравнения и генерации + start_minutes = start_hour * 60 + start_minute + end_minutes = end_hour * 60 + end_minute + + if start_minutes >= end_minutes: + raise CommandError('Начальное время должно быть раньше конечного') + + except ValueError as e: + raise CommandError( + f'Неверный формат времени. Используйте ЧЧ:ММ-ЧЧ:ММ (например: 7:00-9:30). Ошибка: {e}' + ) + + # Парсим ID теханализов если указаны + tech_analyze_ids = None + if tech_analyze_ids_str: + try: + tech_analyze_ids = [int(tid.strip()) for tid in tech_analyze_ids_str.split(',')] + except ValueError: + raise CommandError( + f'Неверный формат tech_analyze_ids. Используйте числа через запятую (например: 1,2,3)' + ) + # Проверяем существование спутника try: satellite = Satellite.objects.get(id=satellite_id) @@ -92,23 +152,35 @@ class Command(BaseCommand): raise CommandError(f'Спутник с ID {satellite_id} не найден') # Получаем теханализы для спутника - tech_analyzes = list(TechAnalyze.objects.filter(satellite=satellite)) + tech_analyzes_qs = TechAnalyze.objects.filter(satellite=satellite) + + # Фильтруем по ID теханализов если указаны + if tech_analyze_ids: + tech_analyzes_qs = tech_analyzes_qs.filter(id__in=tech_analyze_ids) + + tech_analyzes = list(tech_analyzes_qs) ta_count = len(tech_analyzes) if ta_count == 0: - raise CommandError(f'Нет теханализов для спутника "{satellite.name}"') + if tech_analyze_ids: + raise CommandError(f'Нет теханализов для спутника "{satellite.name}" с указанными ID {tech_analyze_ids}') + else: + raise CommandError(f'Нет теханализов для спутника "{satellite.name}"') self.stdout.write(f'Спутник: {satellite.name}') self.stdout.write(f'Теханализов: {ta_count}') + if tech_analyze_ids: + self.stdout.write(f'ID теханализов: {tech_analyze_ids}') self.stdout.write(f'Пользователь: {custom_user}') self.stdout.write(f'Период: {start_str} - {end_str} (только будние дни)') - self.stdout.write(f'Время: 8:00 - 11:00') + self.stdout.write(f'Время: {time_start_str.strip()} - {time_end_str.strip()}') # Удаляем существующие отметки если указан флаг if clear: - deleted_count = ObjectMark.objects.filter( - tech_analyze__satellite=satellite - ).delete()[0] + delete_qs = ObjectMark.objects.filter(tech_analyze__satellite=satellite) + if tech_analyze_ids: + delete_qs = delete_qs.filter(tech_analyze_id__in=tech_analyze_ids) + deleted_count = delete_qs.delete()[0] self.stdout.write( self.style.WARNING(f'Удалено существующих отметок: {deleted_count}') ) @@ -127,9 +199,10 @@ class Command(BaseCommand): if current_date.weekday() < 5: workdays_count += 1 - # Генерируем случайное время в диапазоне 8:00-11:00 - random_hour = random.randint(8, 10) - random_minute = random.randint(0, 59) + # Генерируем случайное время в указанном диапазоне + random_total_minutes = random.randint(start_minutes, end_minutes) + random_hour = random_total_minutes // 60 + random_minute = random_total_minutes % 60 random_second = random.randint(0, 59) mark_time = current_date.replace(