feat: Add search for rescue orgs
This commit is contained in:
@@ -2,9 +2,9 @@ import logging
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from .geo import LocationProxy, Position
|
||||
from ..forms import AdoptionNoticeSearchForm
|
||||
from ..forms import AdoptionNoticeSearchForm, RescueOrgSearchForm
|
||||
from ..models import SearchSubscription, AdoptionNotice, SexChoicesWithAll, Location, \
|
||||
Notification, NotificationTypeChoices
|
||||
Notification, NotificationTypeChoices, RescueOrganization
|
||||
|
||||
|
||||
def notify_search_subscribers(adoption_notice: AdoptionNotice, only_if_active: bool = True):
|
||||
@@ -18,7 +18,7 @@ def notify_search_subscribers(adoption_notice: AdoptionNotice, only_if_active: b
|
||||
return
|
||||
for search_subscription in SearchSubscription.objects.all():
|
||||
logging.debug(f"Search subscription {search_subscription} found.")
|
||||
search = Search(search_subscription=search_subscription)
|
||||
search = AdoptionNoticeSearch(search_subscription=search_subscription)
|
||||
if search.adoption_notice_fits_search(adoption_notice):
|
||||
notification_text = f"{_('Zu deiner Suche')} {search_subscription} wurde eine neue Vermittlung gefunden"
|
||||
Notification.objects.create(user_to_notify=search_subscription.owner,
|
||||
@@ -33,7 +33,7 @@ def notify_search_subscribers(adoption_notice: AdoptionNotice, only_if_active: b
|
||||
logging.info(f"Subscribers for AN {adoption_notice.pk} have been notified\n")
|
||||
|
||||
|
||||
class Search:
|
||||
class AdoptionNoticeSearch:
|
||||
def __init__(self, request=None, search_subscription=None):
|
||||
self.sex = None
|
||||
self.area_search = None
|
||||
@@ -45,7 +45,7 @@ class Search:
|
||||
self.location_string = None
|
||||
|
||||
if request:
|
||||
self.search_from_request(request)
|
||||
self.adoption_notice_search_from_request(request)
|
||||
elif search_subscription:
|
||||
self.search_from_search_subscription(search_subscription)
|
||||
|
||||
@@ -103,7 +103,7 @@ class Search:
|
||||
|
||||
return adoptions
|
||||
|
||||
def search_from_request(self, request):
|
||||
def adoption_notice_search_from_request(self, request):
|
||||
if request.method == 'POST':
|
||||
self.search_form = AdoptionNoticeSearchForm(request.POST)
|
||||
self.search_form.is_valid()
|
||||
@@ -157,3 +157,75 @@ class Search:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
class RescueOrgSearch:
|
||||
def __init__(self, request):
|
||||
self.area_search = None
|
||||
self.max_distance = None
|
||||
self.location = None # Can either be Location (DjangoModel) or LocationProxy
|
||||
self.place_not_found = False # Indicates that a location was given but could not be geocoded
|
||||
self.search_form = None
|
||||
# Either place_id or location string must be set for area search
|
||||
self.location_string = None
|
||||
|
||||
self.rescue_org_search_from_request(request)
|
||||
|
||||
def __str__(self):
|
||||
return f"{_('Suche')}: {self.location=}, {self.area_search=}, {self.max_distance=}"
|
||||
|
||||
def __eq__(self, other):
|
||||
"""
|
||||
Custom equals that also supports SearchSubscriptions
|
||||
|
||||
Only allowed to be called for located subscriptions
|
||||
"""
|
||||
# If both locations are empty check only the max distance
|
||||
if self.location is None and other.location is None:
|
||||
return self.max_distance == other.max_distance
|
||||
# If one location is empty and the other is not, they are not equal
|
||||
elif self.location is not None and other.location is None or self.location is None and other.location is not None:
|
||||
return False
|
||||
return self.location == other.location and self.max_distance == other.max_distance
|
||||
|
||||
def _locate(self):
|
||||
try:
|
||||
self.location = LocationProxy(self.location_string)
|
||||
except ValueError:
|
||||
self.place_not_found = True
|
||||
|
||||
@property
|
||||
def position(self):
|
||||
if self.area_search and not self.place_not_found:
|
||||
return Position(latitude=self.location.latitude, longitude=self.location.longitude)
|
||||
else:
|
||||
return None
|
||||
|
||||
def rescue_org_fits_search(self, rescue_org: RescueOrganization):
|
||||
# make sure it's an area search and the place is found to check location
|
||||
if self.area_search and not self.place_not_found:
|
||||
# If adoption notice is in not in search distance, return false
|
||||
if not rescue_org.in_distance(self.location.position, self.max_distance):
|
||||
logging.debug("Area mismatch")
|
||||
return False
|
||||
return True
|
||||
|
||||
def get_rescue_orgs(self):
|
||||
rescue_orgs = RescueOrganization.objects.all()
|
||||
fitting_rescue_orgs = [rescue_org for rescue_org in rescue_orgs if self.rescue_org_fits_search(rescue_org)]
|
||||
|
||||
return fitting_rescue_orgs
|
||||
|
||||
def rescue_org_search_from_request(self, request):
|
||||
if request.method == 'POST':
|
||||
self.search_form = RescueOrgSearchForm(request.POST)
|
||||
self.search_form.is_valid()
|
||||
|
||||
if self.search_form.cleaned_data["location_string"] != "" and self.search_form.cleaned_data[
|
||||
"max_distance"] != "":
|
||||
self.area_search = True
|
||||
self.location_string = self.search_form.cleaned_data["location_string"]
|
||||
self.max_distance = int(self.search_form.cleaned_data["max_distance"])
|
||||
self._locate()
|
||||
else:
|
||||
self.search_form = RescueOrgSearchForm()
|
||||
|
Reference in New Issue
Block a user