mirror of
https://github.com/seanmorley15/AdventureLog.git
synced 2025-08-05 05:05:17 +02:00
Merge d7d75e8a1e
into 4e96e529f4
This commit is contained in:
commit
3acef4a614
4 changed files with 48 additions and 2 deletions
|
@ -114,6 +114,11 @@ class VisitAdmin(admin.ModelAdmin):
|
||||||
search_fields = ('notes',)
|
search_fields = ('notes',)
|
||||||
|
|
||||||
|
|
||||||
|
def save_model(self, request, obj, form, change):
|
||||||
|
obj.full_clean()
|
||||||
|
super().save_model(request, obj, form, change)
|
||||||
|
|
||||||
|
|
||||||
def image_display(self, obj):
|
def image_display(self, obj):
|
||||||
if obj.image: # Ensure this field matches your model's image field
|
if obj.image: # Ensure this field matches your model's image field
|
||||||
public_url = os.environ.get('PUBLIC_URL', 'http://127.0.0.1:8000').rstrip('/')
|
public_url = os.environ.get('PUBLIC_URL', 'http://127.0.0.1:8000').rstrip('/')
|
||||||
|
|
|
@ -548,9 +548,33 @@ class Visit(models.Model):
|
||||||
updated_at = models.DateTimeField(auto_now=True)
|
updated_at = models.DateTimeField(auto_now=True)
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
if self.start_date > self.end_date:
|
super().clean()
|
||||||
|
|
||||||
|
# Validate start date is before end date
|
||||||
|
if self.start_date and self.end_date and self.start_date > self.end_date:
|
||||||
raise ValidationError('The start date must be before or equal to the end date.')
|
raise ValidationError('The start date must be before or equal to the end date.')
|
||||||
|
|
||||||
|
# Validates that visit dates fall within their collection date range
|
||||||
|
if self.start_date and self.end_date and self.adventure:
|
||||||
|
collections = self.adventure.collections.filter(start_date__isnull=False, end_date__isnull=False)
|
||||||
|
|
||||||
|
if collections.exists():
|
||||||
|
visit_start_date = self.start_date.date() if hasattr(self.start_date, 'date') else self.start_date
|
||||||
|
visit_end_date = self.end_date.date() if hasattr(self.end_date, 'date') else self.end_date
|
||||||
|
|
||||||
|
for collection in collections:
|
||||||
|
collection_start_date = collection.start_date
|
||||||
|
collection_end_date = collection.end_date
|
||||||
|
|
||||||
|
if not (
|
||||||
|
collection_start_date <= visit_start_date <= collection_end_date and
|
||||||
|
collection_start_date <= visit_end_date <= collection_end_date
|
||||||
|
):
|
||||||
|
raise ValidationError(
|
||||||
|
f'Visit dates ({visit_start_date}) to ({visit_end_date}) for {self.adventure.name}' \
|
||||||
|
'should be between the collection date range'
|
||||||
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.adventure.name} - {self.start_date} to {self.end_date}"
|
return f"{self.adventure.name} - {self.start_date} to {self.end_date}"
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
import os
|
import os
|
||||||
from .models import Adventure, AdventureImage, ChecklistItem, Collection, Note, Transportation, Checklist, Visit, Category, Attachment, Lodging
|
from .models import Adventure, AdventureImage, ChecklistItem, Collection, Note, Transportation, Checklist, Visit, Category, Attachment, Lodging
|
||||||
|
from .utils.timezone_utils import format_datetime_in_selected_timezone
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from main.utils import CustomModelSerializer
|
from main.utils import CustomModelSerializer
|
||||||
from users.serializers import CustomUserDetailsSerializer
|
from users.serializers import CustomUserDetailsSerializer
|
||||||
|
@ -254,6 +255,8 @@ class AdventureSerializer(CustomModelSerializer):
|
||||||
|
|
||||||
class TransportationSerializer(CustomModelSerializer):
|
class TransportationSerializer(CustomModelSerializer):
|
||||||
distance = serializers.SerializerMethodField()
|
distance = serializers.SerializerMethodField()
|
||||||
|
start_date_local = serializers.SerializerMethodField()
|
||||||
|
end_date_local = serializers.SerializerMethodField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Transportation
|
model = Transportation
|
||||||
|
@ -262,7 +265,7 @@ class TransportationSerializer(CustomModelSerializer):
|
||||||
'link', 'date', 'flight_number', 'from_location', 'to_location',
|
'link', 'date', 'flight_number', 'from_location', 'to_location',
|
||||||
'is_public', 'collection', 'created_at', 'updated_at', 'end_date',
|
'is_public', 'collection', 'created_at', 'updated_at', 'end_date',
|
||||||
'origin_latitude', 'origin_longitude', 'destination_latitude', 'destination_longitude',
|
'origin_latitude', 'origin_longitude', 'destination_latitude', 'destination_longitude',
|
||||||
'start_timezone', 'end_timezone', 'distance' # ✅ Add distance here
|
'start_timezone', 'end_timezone', 'distance', 'start_date_local', 'end_date_local' # ✅ Add distance here
|
||||||
]
|
]
|
||||||
read_only_fields = ['id', 'created_at', 'updated_at', 'user_id', 'distance']
|
read_only_fields = ['id', 'created_at', 'updated_at', 'user_id', 'distance']
|
||||||
|
|
||||||
|
@ -279,6 +282,12 @@ class TransportationSerializer(CustomModelSerializer):
|
||||||
return None
|
return None
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def get_start_date_local(self, obj):
|
||||||
|
return format_datetime_in_selected_timezone(obj.date, obj.start_timezone)
|
||||||
|
|
||||||
|
def get_end_date_local(self, obj):
|
||||||
|
return format_datetime_in_selected_timezone(obj.end_date, obj.end_timezone)
|
||||||
|
|
||||||
class LodgingSerializer(CustomModelSerializer):
|
class LodgingSerializer(CustomModelSerializer):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
8
backend/server/adventures/utils/timezone_utils.py
Normal file
8
backend/server/adventures/utils/timezone_utils.py
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import pytz
|
||||||
|
|
||||||
|
|
||||||
|
def format_datetime_in_selected_timezone(dt, user_tz):
|
||||||
|
if dt is None and user_tz is None:
|
||||||
|
return None
|
||||||
|
tz = pytz.timezone(user_tz)
|
||||||
|
return dt.astimezone(tz).isoformat()
|
Loading…
Add table
Add a link
Reference in a new issue