service.py
5.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import json
import calendar
import pytz
from django.core.serializers.json import DjangoJSONEncoder
from datetime import datetime, timedelta, time
from .models import Evento, FechaEvento
class GenerarFechas:
def __init__(self, evento: Evento, mes: int):
self.fechas_generadas = {}
self.evento = evento
self.mes = mes
def obtener_rango_del_mes(self):
"""Obtiene el rango de fechas para el mes específico."""
year = datetime.now().year
self.mes = int(self.mes)
primer_dia, ultimo_dia = calendar.monthrange(year, self.mes)
fecha_inicio_mes = datetime(year, self.mes, 1)
fecha_fin_mes = datetime(year, self.mes, ultimo_dia)
return fecha_inicio_mes, fecha_fin_mes
def ajustar_fechas_a_rango_mes(self):
"""Ajusta las fechas del evento al rango del mes especificado."""
zona_horaria = pytz.timezone('America/Argentina/Buenos_Aires')
fecha_inicio_evento = self.combinar_fecha_hora(self.evento.fecha_inicio, self.evento.hora_inicio, zona_horaria)
fecha_fin_evento = self.combinar_fecha_hora(self.evento.fecha_final, self.evento.hora_fin, zona_horaria)
fecha_inicio_mes, fecha_fin_mes = self.obtener_rango_del_mes()
fecha_inicio_evento = max(fecha_inicio_evento, zona_horaria.localize(fecha_inicio_mes))
fecha_fin_evento = min(fecha_fin_evento, zona_horaria.localize(fecha_fin_mes))
return fecha_inicio_evento, fecha_fin_evento
@staticmethod
def combinar_fecha_hora(fecha, hora, zona_horaria):
"""Combina la fecha y hora en un solo objeto datetime."""
if fecha is None or hora is None:
return None
fecha_hora = datetime.combine(fecha, hora)
return zona_horaria.localize(fecha_hora) if fecha_hora.tzinfo is None else fecha_hora
def obtener_dias_del_evento(self):
"""Obtiene los días de la semana en los que se realiza el evento (en formato 1 a 7)."""
dias_evento = []
for fecha in self.evento.fechas.all():
if fecha.duracion_evento is not None: # Solo considerar fechas con duracion_evento definido
dias_evento.append(int(fecha.duracion_evento)) # Convertir a entero y agregar a la lista
return dias_evento
def procesar_fechas_evento(self):
"""Genera las fechas del evento ajustadas al mes especificado."""
fecha_inicio, fecha_fin = self.ajustar_fechas_a_rango_mes()
dias_evento = self.obtener_dias_del_evento()
fechas_null = self.evento.fechas.filter(dias__isnull=True)
self.asignar_fechas_nulas(fechas_null, dias_evento, fecha_inicio)
self.generar_fechas_para_dias_especificos(fecha_inicio, fecha_fin, dias_evento)
return self.fechas_generadas
def asignar_fechas_nulas(self, fechas_null, dias_evento, fecha_inicio):
"""Asigna fechas a las entradas que no tienen días especificados."""
for fecha_obj in fechas_null:
dia_semana = fecha_inicio.weekday() + 1 # Ajustar de 0-6 a 1-7
if dia_semana in dias_evento:
fecha_obj.dias = fecha_inicio.date()
fecha_obj.save(update_fields=['dias'])
self.fechas_generadas[fecha_inicio.strftime('%Y-%m-%d')] = fecha_obj.pk
def generar_fechas_para_dias_especificos(self, fecha_inicio, fecha_fin, dias_evento):
"""Genera fechas adicionales dentro del rango si coinciden con los días seleccionados."""
fecha_actual = fecha_inicio
while fecha_actual <= fecha_fin:
dia_semana = fecha_actual.weekday() + 1 # Ajustar de 0-6 a 1-7
if dia_semana in dias_evento:
self.agregar_fecha(fecha_actual, dia_semana)
fecha_actual += timedelta(days=1)
def agregar_fecha(self, fecha_actual, dia_semana):
"""Agrega una fecha al evento si no existe ya en el sistema."""
if not FechaEvento.objects.filter(dias=fecha_actual, duracion_evento=str(dia_semana)).exists():
nueva_fecha = FechaEvento.objects.create(dias=fecha_actual, duracion_evento=str(dia_semana))
self.evento.fechas.add(nueva_fecha)
self.fechas_generadas[fecha_actual.strftime('%Y-%m-%d')] = nueva_fecha.pk
def obtener_datos_evento(self):
"""Devuelve los datos del evento en formato serializado."""
return {
'titulo': self.evento.titulo,
'categoria': self.evento.categoria,
'descripcion': self.evento.descripcion,
'direccion': self.evento.direccion,
'fecha_inicio': self.evento.fecha_inicio.isoformat() if self.evento.fecha_inicio else None,
'hora_inicio': self.evento.hora_inicio.isoformat() if self.evento.hora_inicio else None,
'fecha_final': self.evento.fecha_final.isoformat() if self.evento.fecha_final else None,
'hora_fin': self.evento.hora_fin.isoformat() if self.evento.hora_fin else None,
'url': self.evento.url,
'imagen': self.evento.imagen.url if self.evento.imagen else None,
'fechas': list(self.evento.fechas.values('id', 'duracion_evento', 'dias')),
'organismo': list(self.evento.organismo.values('short_name')),
'dependencia': list(self.evento.dependencia.values('short_name')),
}