Переделки и улучшения

This commit is contained in:
2025-11-21 16:56:58 +03:00
parent 58838614a5
commit 0d239ef1de
11 changed files with 604 additions and 138 deletions

View File

@@ -491,6 +491,18 @@ class Source(models.Model):
verbose_name="Принадлежность объекта",
help_text="Принадлежность объекта (страна, организация и т.д.)",
)
confirm_at = models.DateTimeField(
null=True,
blank=True,
verbose_name="Дата подтверждения",
help_text="Дата и время добавления последней полученной точки ГЛ",
)
last_signal_at = models.DateTimeField(
null=True,
blank=True,
verbose_name="Последний сигнал",
help_text="Дата и время последней отметки о наличии сигнала",
)
coords_average = gis.PointField(
srid=4326,
@@ -550,6 +562,135 @@ class Source(models.Model):
help_text="Пользователь, последним изменивший запись",
)
def update_coords_average(self, new_coord_tuple):
"""
Обновляет coords_average в зависимости от типа объекта (info).
Логика:
- Если info == "Подвижные": coords_average = последняя добавленная координата
- Иначе (Стационарные и др.): coords_average = инкрементальное среднее
Args:
new_coord_tuple: кортеж (longitude, latitude) новой координаты
"""
from django.contrib.gis.geos import Point
from .utils import calculate_mean_coords
# Если тип объекта "Подвижные" - просто устанавливаем последнюю координату
if self.info and self.info.name == "Подвижные":
self.coords_average = Point(new_coord_tuple, srid=4326)
else:
# Для стационарных объектов - вычисляем среднее
if self.coords_average:
# Есть предыдущее среднее - вычисляем новое среднее
current_coord = (self.coords_average.x, self.coords_average.y)
new_avg, _ = calculate_mean_coords(current_coord, new_coord_tuple)
self.coords_average = Point(new_avg, srid=4326)
else:
# Первая координата - просто устанавливаем её
self.coords_average = Point(new_coord_tuple, srid=4326)
def get_last_geo_coords(self):
"""
Получает координаты последней добавленной точки ГЛ для этого источника.
Сортировка по ID (последняя добавленная в базу).
Returns:
tuple: (longitude, latitude) или None если точек нет
"""
# Получаем последний ObjItem для этого Source (по ID)
last_objitem = self.source_objitems.filter(
geo_obj__coords__isnull=False
).select_related('geo_obj').order_by('-id').first()
if last_objitem and last_objitem.geo_obj and last_objitem.geo_obj.coords:
return (last_objitem.geo_obj.coords.x, last_objitem.geo_obj.coords.y)
return None
def update_confirm_at(self):
"""
Обновляет дату confirm_at на дату создания последней добавленной точки ГЛ.
"""
last_objitem = self.source_objitems.order_by('-created_at').first()
if last_objitem:
self.confirm_at = last_objitem.created_at
def update_last_signal_at(self):
"""
Обновляет дату last_signal_at на дату последней отметки о наличии сигнала (mark=True).
"""
last_signal_mark = self.marks.filter(mark=True).order_by('-timestamp').first()
if last_signal_mark:
self.last_signal_at = last_signal_mark.timestamp
else:
self.last_signal_at = None
def save(self, *args, **kwargs):
"""
Переопределенный метод save для автоматического обновления coords_average
при изменении типа объекта.
"""
from django.contrib.gis.geos import Point
# Проверяем, изменился ли тип объекта
if self.pk: # Объект уже существует
try:
old_instance = Source.objects.get(pk=self.pk)
old_info = old_instance.info
new_info = self.info
# Если тип изменился на "Подвижные"
if new_info and new_info.name == "Подвижные" and (not old_info or old_info.name != "Подвижные"):
# Устанавливаем координату последней точки
last_coords = self.get_last_geo_coords()
if last_coords:
self.coords_average = Point(last_coords, srid=4326)
# Если тип изменился с "Подвижные" на что-то другое
elif old_info and old_info.name == "Подвижные" and (not new_info or new_info.name != "Подвижные"):
# Пересчитываем среднюю координату по всем точкам
self._recalculate_average_coords()
except Source.DoesNotExist:
pass
super().save(*args, **kwargs)
def _recalculate_average_coords(self):
"""
Пересчитывает среднюю координату по всем точкам источника.
Используется при переключении с "Подвижные" на "Стационарные".
Сортировка по ID (порядок добавления в базу), инкрементальное усреднение
как в функциях импорта.
"""
from django.contrib.gis.geos import Point
from .utils import calculate_mean_coords
# Получаем все точки для этого источника, сортируем по ID (порядок добавления)
objitems = self.source_objitems.filter(
geo_obj__coords__isnull=False
).select_related('geo_obj').order_by('id')
if not objitems.exists():
return
# Вычисляем среднюю координату инкрементально (как в функциях импорта)
coords_average = None
for objitem in objitems:
if objitem.geo_obj and objitem.geo_obj.coords:
coord = (objitem.geo_obj.coords.x, objitem.geo_obj.coords.y)
if coords_average is None:
# Первая точка - просто устанавливаем её
coords_average = coord
else:
# Последующие точки - вычисляем среднее между текущим средним и новой точкой
coords_average, _ = calculate_mean_coords(coords_average, coord)
if coords_average:
self.coords_average = Point(coords_average, srid=4326)
class Meta:
verbose_name = "Источник"
verbose_name_plural = "Источники"