Переделки и улучшения
This commit is contained in:
@@ -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 = "Источники"
|
||||
|
||||
Reference in New Issue
Block a user