feat: Fully replace the Adoption Notice Status model with the field

This commit is contained in:
2025-08-31 10:52:48 +02:00
parent 70f077e393
commit fd481fef2e
16 changed files with 102 additions and 219 deletions

View File

@@ -7,30 +7,26 @@ from django.utils.html import format_html
from django.urls import reverse from django.urls import reverse
from django.utils.http import urlencode from django.utils.http import urlencode
from .models import User, Language, Text, ReportComment, ReportAdoptionNotice, Log, Timestamp, SearchSubscription, \ from .models import Language, Text, ReportComment, ReportAdoptionNotice, Log, Timestamp, SearchSubscription, \
SpeciesSpecificURL, ImportantLocation, SocialMediaPost SpeciesSpecificURL, ImportantLocation, SocialMediaPost
from .models import Animal, Species, RescueOrganization, AdoptionNotice, Location, Rule, Image, ModerationAction, \ from .models import Animal, Species, RescueOrganization, AdoptionNotice, Location, Rule, Image, ModerationAction, \
Comment, Report, Announcement, AdoptionNoticeStatus, User, Subscriptions, Notification Comment, Announcement, User, Subscriptions, Notification
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from .tools.model_helpers import AdoptionNoticeStatusChoices
class StatusInline(admin.StackedInline):
model = AdoptionNoticeStatus
@admin.register(AdoptionNotice) @admin.register(AdoptionNotice)
class AdoptionNoticeAdmin(admin.ModelAdmin): class AdoptionNoticeAdmin(admin.ModelAdmin):
search_fields = ("name__icontains", "description__icontains") search_fields = ("name__icontains", "description__icontains")
list_filter = ("owner",) list_filter = ("owner",)
inlines = [
StatusInline,
]
actions = ("activate",) actions = ("activate",)
def activate(self, request, queryset): def activate(self, request, queryset):
for obj in queryset: for obj in queryset:
obj.set_active() obj.adoption_notice_status = AdoptionNoticeStatusChoices.Active.SEARCHING
obj.save()
activate.short_description = _("Ausgewählte Vermittlungen aktivieren") activate.short_description = _("Ausgewählte Vermittlungen aktivieren")
@@ -162,10 +158,12 @@ class LocationAdmin(admin.ModelAdmin):
ImportantLocationInline, ImportantLocationInline,
] ]
@admin.register(SocialMediaPost) @admin.register(SocialMediaPost)
class SocialMediaPostAdmin(admin.ModelAdmin): class SocialMediaPostAdmin(admin.ModelAdmin):
list_filter = ("platform",) list_filter = ("platform",)
admin.site.register(Animal) admin.site.register(Animal)
admin.site.register(Species) admin.site.register(Species)
admin.site.register(Rule) admin.site.register(Rule)

View File

@@ -73,9 +73,9 @@ class AdoptionNoticeApiView(APIView):
# Only set active when user has trust level moderator or higher # Only set active when user has trust level moderator or higher
if request.user_to_notify.trust_level >= TrustLevel.MODERATOR: if request.user_to_notify.trust_level >= TrustLevel.MODERATOR:
adoption_notice.set_active() adoption_notice.adoption_notice_status = AdoptionNoticeStatusChoices.Active.SEARCHING
else: else:
adoption_notice.set_unchecked() adoption_notice.adoption_notice_status = AdoptionNoticeStatusChoices.AwaitingAction.WAITING_FOR_REVIEW
# Log the action # Log the action
Log.objects.create( Log.objects.create(

View File

@@ -0,0 +1,21 @@
# Generated by Django 5.2.1 on 2025-08-30 22:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('fellchensammlung', '0061_datamigration_status_model_to_field'),
]
operations = [
migrations.AlterField(
model_name='adoptionnotice',
name='adoption_notice_status',
field=models.TextField(choices=[('active_searching', 'Searching'), ('active_interested', 'Interested'), ('awaiting_action_waiting_for_review', 'Waiting for review'), ('awaiting_action_needs_additional_info', 'Needs additional info'), ('closed_successful_with_notfellchen', 'Successful (with Notfellchen)'), ('closed_successful_without_notfellchen', 'Successful (without Notfellchen)'), ('closed_animal_died', 'Animal died'), ('closed_for_other_adoption_notice', 'Closed for other adoption notice'), ('closed_not_open_for_adoption_anymore', 'Not open for adoption anymore'), ('closed_link_to_more_info_not_reachable', 'Der Link zu weiteren Informationen ist nicht mehr erreichbar.'), ('closed_other', 'Other (closed)'), ('disabled_against_the_rules', 'Against the rules'), ('disabled_unchecked', 'Unchecked'), ('disabled_other', 'Other (disabled)')], max_length=64, verbose_name='Status'),
),
migrations.DeleteModel(
name='AdoptionNoticeStatus',
),
]

View File

@@ -513,60 +513,30 @@ class AdoptionNotice(models.Model):
""" """
return geo.object_in_distance(self, position, max_distance, unknown_true) return geo.object_in_distance(self, position, max_distance, unknown_true)
@staticmethod
def _values_of(list_of_enums):
return list(map(lambda x: x[0], list_of_enums))
@property @property
def is_active(self): def is_active(self):
if not hasattr(self, 'adoptionnoticestatus'): return self.adoption_notice_status in self._values_of(AdoptionNoticeStatusChoices.Active.choices)
return False
return self.adoptionnoticestatus.is_active
@property @property
def is_disabled(self): def is_disabled(self):
if not hasattr(self, 'adoptionnoticestatus'): return self.adoption_notice_status in self._values_of(AdoptionNoticeStatusChoices.Disabled.choices)
return False
return self.adoptionnoticestatus.is_disabled
@property @property
def is_closed(self): def is_closed(self):
if not hasattr(self, 'adoptionnoticestatus'): return self.adoption_notice_status in self._values_of(AdoptionNoticeStatusChoices.Closed.choices)
return False
return self.adoptionnoticestatus.is_closed
@property
def is_interested(self):
if not hasattr(self, 'adoptionnoticestatus'):
return False
return self.adoptionnoticestatus.is_interested
@property @property
def is_awaiting_action(self): def is_awaiting_action(self):
if not hasattr(self, 'adoptionnoticestatus'): return self.adoption_notice_status in self._values_of(AdoptionNoticeStatusChoices.AwaitingAction.choices)
return False
return self.adoptionnoticestatus.is_awaiting_action
@property
def is_disabled_unchecked(self):
if not hasattr(self, 'adoptionnoticestatus'):
return False
return self.adoptionnoticestatus.is_disabled_unchecked
def set_closed(self, minor_status=None):
self.last_checked = timezone.now()
self.save()
self.adoptionnoticestatus.set_closed(minor_status)
def set_active(self):
self.last_checked = timezone.now()
self.save()
if not hasattr(self, 'adoptionnoticestatus'):
AdoptionNoticeStatus.create_other(self)
self.adoptionnoticestatus.set_active()
def set_unchecked(self): def set_unchecked(self):
self.last_checked = timezone.now() self.last_checked = timezone.now()
self.adoption_notice_status = AdoptionNoticeStatusChoices.Disabled.UNCHECKED
self.save() self.save()
if not hasattr(self, 'adoptionnoticestatus'):
AdoptionNoticeStatus.create_other(self)
self.adoptionnoticestatus.set_unchecked()
for subscription in self.get_subscriptions(): for subscription in self.get_subscriptions():
notification_title = _("Vermittlung deaktiviert:") + f" {self.name}" notification_title = _("Vermittlung deaktiviert:") + f" {self.name}"
@@ -586,124 +556,6 @@ class AdoptionNotice(models.Model):
return last_post.created_at return last_post.created_at
class AdoptionNoticeStatus(models.Model):
"""
The major status indicates a general state of an adoption notice
whereas the minor status is used for reporting
"""
class Meta:
verbose_name = _('Vermittlungsstatus')
verbose_name_plural = _('Vermittlungsstati')
ACTIVE = "active"
AWAITING_ACTION = "awaiting_action"
CLOSED = "closed"
DISABLED = "disabled"
MAJOR_STATUS_CHOICES = {
ACTIVE: "active",
AWAITING_ACTION: "in review",
CLOSED: "closed",
DISABLED: "disabled",
}
MINOR_STATUS_CHOICES = {
ACTIVE: {
"searching": "searching",
"interested": "interested",
},
AWAITING_ACTION: {
"waiting_for_review": "waiting_for_review",
"needs_additional_info": "needs_additional_info",
},
CLOSED: {
"successful_with_notfellchen": "successful_with_notfellchen",
"successful_without_notfellchen": "successful_without_notfellchen",
"animal_died": "animal_died",
"closed_for_other_adoption_notice": "closed_for_other_adoption_notice",
"not_open_for_adoption_anymore": "not_open_for_adoption_anymore",
"other": "other"
},
DISABLED: {
"against_the_rules": "against_the_rules",
"missing_information": "missing_information",
"technical_error": "technical_error",
"unchecked": "unchecked",
"other": "other"
}
}
major_status = models.CharField(choices=MAJOR_STATUS_CHOICES, max_length=200)
minor_choices = {}
for key in MINOR_STATUS_CHOICES:
minor_choices.update(MINOR_STATUS_CHOICES[key])
minor_status = models.CharField(choices=minor_choices, max_length=200)
adoption_notice = models.OneToOneField(AdoptionNotice, on_delete=models.CASCADE)
updated_at = models.DateTimeField(auto_now=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.adoption_notice}: {self.major_status}, {self.minor_status}"
def as_string(self):
return f"{self.major_status}, {self.minor_status}"
@property
def is_active(self):
return self.major_status == self.ACTIVE
@property
def is_disabled(self):
return self.major_status == self.DISABLED
@property
def is_closed(self):
return self.major_status == self.CLOSED
@property
def is_awaiting_action(self):
return self.major_status == self.AWAITING_ACTION
@property
def is_interested(self):
return self.major_status == self.ACTIVE and self.minor_status == "interested"
@property
def is_disabled_unchecked(self):
return self.major_status == self.DISABLED and self.minor_status == "unchecked"
@staticmethod
def get_minor_choices(major_status):
return AdoptionNoticeStatus.MINOR_STATUS_CHOICES[major_status]
@staticmethod
def create_other(an_instance):
# Used as empty status to be changed immediately
major_status = AdoptionNoticeStatus.DISABLED
minor_status = AdoptionNoticeStatus.MINOR_STATUS_CHOICES[AdoptionNoticeStatus.DISABLED]["other"]
AdoptionNoticeStatus.objects.create(major_status=major_status,
minor_status=minor_status,
adoption_notice=an_instance)
def set_closed(self, minor_status=None):
self.major_status = self.MAJOR_STATUS_CHOICES[self.CLOSED]
if minor_status is None:
self.minor_status = self.MINOR_STATUS_CHOICES[self.CLOSED]["other"]
else:
self.minor_status = self.MINOR_STATUS_CHOICES[self.CLOSED][minor_status]
self.save()
def set_unchecked(self):
self.major_status = self.MAJOR_STATUS_CHOICES[self.DISABLED]
self.minor_status = self.MINOR_STATUS_CHOICES[self.DISABLED]["unchecked"]
self.save()
def set_active(self):
self.major_status = self.MAJOR_STATUS_CHOICES[self.ACTIVE]
self.minor_status = self.MINOR_STATUS_CHOICES[self.ACTIVE]["searching"]
self.save()
class SexChoices(models.TextChoices): class SexChoices(models.TextChoices):
FEMALE = "F", _("Weiblich") FEMALE = "F", _("Weiblich")
MALE = "M", _("Männlich") MALE = "M", _("Männlich")

View File

@@ -1,6 +1,8 @@
import logging import logging
from random import randint from random import randint
from fellchensammlung.tools.model_helpers import AdoptionNoticeStatusChoices
from notfellchen import settings from notfellchen import settings
from django.utils import timezone from django.utils import timezone
from datetime import timedelta from datetime import timedelta
@@ -86,7 +88,8 @@ def deactivate_404_adoption_notices():
for adoption_notice in get_active_adoption_notices(): for adoption_notice in get_active_adoption_notices():
if adoption_notice.further_information and adoption_notice.further_information != "": if adoption_notice.further_information and adoption_notice.further_information != "":
if is_404(adoption_notice.further_information): if is_404(adoption_notice.further_information):
adoption_notice.set_closed() adoption_notice.adoption_notice_status = AdoptionNoticeStatusChoices.Closed.LINK_TO_MORE_INFO_NOT_REACHABLE
adoption_notice.save()
logging_msg = f"Automatically set Adoption Notice {adoption_notice.id} closed as link to more information returened 404" logging_msg = f"Automatically set Adoption Notice {adoption_notice.id} closed as link to more information returened 404"
logging.info(logging_msg) logging.info(logging_msg)
Log.objects.create(action="automated", text=logging_msg) Log.objects.create(action="automated", text=logging_msg)

View File

@@ -9,14 +9,14 @@ def gather_metrics_data():
"""Adoption notices""" """Adoption notices"""
num_adoption_notices = AdoptionNotice.objects.count() num_adoption_notices = AdoptionNotice.objects.count()
adoption_notices_active = AdoptionNotice.objects.filter( adoption_notices_active = AdoptionNotice.objects.filter(
adoptionnoticestatus=AdoptionNoticeStatusChoices.all_choices()) # TODO fix adoption_notice_status__in=AdoptionNoticeStatusChoices.Active.values)
num_adoption_notices_active = adoption_notices_active.count() num_adoption_notices_active = adoption_notices_active.count()
num_adoption_notices_closed = AdoptionNotice.objects.filter( num_adoption_notices_closed = AdoptionNotice.objects.filter(
adoptionnoticestatus=AdoptionNoticeStatusChoices.all_choices()) # TODO fix adoption_notice_status__in=AdoptionNoticeStatusChoices.Closed.values).count()
num_adoption_notices_disabled = AdoptionNotice.objects.filter( num_adoption_notices_disabled = AdoptionNotice.objects.filter(
adoptionnoticestatus=AdoptionNoticeStatusChoices.all_choices()) # TODO fix adoption_notice_status__in=AdoptionNoticeStatusChoices.Disabled.values).count()
num_adoption_notices_awaiting_action = AdoptionNotice.objects.filter( num_adoption_notices_awaiting_action = AdoptionNotice.objects.filter(
adoptionnoticestatus=AdoptionNoticeStatusChoices.all_choices()) # TODO fix adoption_notice_status__in=AdoptionNoticeStatusChoices.AwaitingAction.values).count()
adoption_notices_without_location = AdoptionNotice.objects.filter(location__isnull=True).count() adoption_notices_without_location = AdoptionNotice.objects.filter(location__isnull=True).count()

View File

@@ -89,6 +89,7 @@ class AdoptionNoticeStatusChoices:
ANIMAL_DIED = "closed_animal_died", _("Animal died") ANIMAL_DIED = "closed_animal_died", _("Animal died")
FOR_OTHER_ADOPTION_NOTICE = "closed_for_other_adoption_notice", _("Closed for other adoption notice") FOR_OTHER_ADOPTION_NOTICE = "closed_for_other_adoption_notice", _("Closed for other adoption notice")
NOT_OPEN_ANYMORE = "closed_not_open_for_adoption_anymore", _("Not open for adoption anymore") NOT_OPEN_ANYMORE = "closed_not_open_for_adoption_anymore", _("Not open for adoption anymore")
LINK_TO_MORE_INFO_NOT_REACHABLE = "closed_link_to_more_info_not_reachable", _("Der Link zu weiteren Informationen ist nicht mehr erreichbar.")
OTHER = "closed_other", _("Other (closed)") OTHER = "closed_other", _("Other (closed)")
class Descriptions: class Descriptions:

View File

@@ -1,9 +1,9 @@
from fellchensammlung.models import User, Notification, TrustLevel from fellchensammlung.models import User, Notification, TrustLevel, AdoptionNoticeStatusChoices
from fellchensammlung.models import NotificationTypeChoices as ntc from fellchensammlung.models import NotificationTypeChoices as ntc
def notify_of_AN_to_be_checked(adoption_notice): def notify_of_AN_to_be_checked(adoption_notice):
if adoption_notice.is_disabled_unchecked: if adoption_notice.adoption_notice_status == AdoptionNoticeStatusChoices.AwaitingAction.WAITING_FOR_REVIEW:
users_to_notify = set(User.objects.filter(trust_level__gt=TrustLevel.MODERATOR)) users_to_notify = set(User.objects.filter(trust_level__gt=TrustLevel.MODERATOR))
users_to_notify.add(adoption_notice.owner) users_to_notify.add(adoption_notice.owner)
for user in users_to_notify: for user in users_to_notify:

View File

@@ -2,6 +2,7 @@ import logging
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from .geo import LocationProxy, Position from .geo import LocationProxy, Position
from .model_helpers import AdoptionNoticeStatusChoices
from ..forms import AdoptionNoticeSearchForm, RescueOrgSearchForm from ..forms import AdoptionNoticeSearchForm, RescueOrgSearchForm
from ..models import SearchSubscription, AdoptionNotice, SexChoicesWithAll, Location, \ from ..models import SearchSubscription, AdoptionNotice, SexChoicesWithAll, Location, \
Notification, NotificationTypeChoices, RescueOrganization Notification, NotificationTypeChoices, RescueOrganization
@@ -95,9 +96,8 @@ class AdoptionNoticeSearch:
return True return True
def get_adoption_notices(self): def get_adoption_notices(self):
adoptions = AdoptionNotice.objects.order_by("-created_at") adoptions = AdoptionNotice.objects.filter(
# Filter for active adoption notices adoption_notice_status__in=AdoptionNoticeStatusChoices.Active.values).order_by("-created_at")
adoptions = [adoption for adoption in adoptions if adoption.is_active]
# Check if adoption notice fits search. # Check if adoption notice fits search.
adoptions = [adoption for adoption in adoptions if self.adoption_notice_fits_search(adoption)] adoptions = [adoption for adoption in adoptions if self.adoption_notice_fits_search(adoption)]

View File

@@ -59,9 +59,8 @@ def fail_if_user_not_owner_or_trust_level(user, django_object, trust_level=Trust
def index(request): def index(request):
"""View function for home page of site.""" """View function for home page of site."""
latest_adoption_list = AdoptionNotice.objects.filter( active_adoptions = AdoptionNotice.objects.filter(
adoption_notice_status__in=AdoptionNoticeStatusChoices.Active.choices).order_by("-created_at") adoption_notice_status__in=AdoptionNoticeStatusChoices.Active.values).order_by("-created_at")
active_adoptions = [adoption for adoption in latest_adoption_list if adoption.is_active]
language_code = translation.get_language() language_code = translation.get_language()
lang = Language.objects.get(languagecode=language_code) lang = Language.objects.get(languagecode=language_code)
active_announcements = Announcement.get_active_announcements(lang) active_announcements = Announcement.get_active_announcements(lang)
@@ -102,9 +101,13 @@ def handle_an_check_actions(request, action, adoption_notice=None):
return render(request, "fellchensammlung/errors/403.html", status=403) return render(request, "fellchensammlung/errors/403.html", status=403)
if action == "checked_inactive": if action == "checked_inactive":
adoption_notice.set_closed() adoption_notice.adoption_notice_status = AdoptionNoticeStatusChoices.Closed.NOT_OPEN_ANYMORE
adoption_notice.last_checked = timezone.now()
adoption_notice.save()
elif action == "checked_active": elif action == "checked_active":
adoption_notice.set_active() adoption_notice.adoption_notice_status = AdoptionNoticeStatusChoices.Active.SEARCHING
adoption_notice.last_checked = timezone.now()
adoption_notice.save()
return None return None
@@ -286,9 +289,10 @@ def add_adoption_notice(request):
an_instance.owner = request.user an_instance.owner = request.user
if request.user.trust_level >= TrustLevel.MODERATOR: if request.user.trust_level >= TrustLevel.MODERATOR:
an_instance.set_active() an_instance.adoption_notice_status = AdoptionNoticeStatusChoices.Active.SEARCHING
else: else:
an_instance.set_unchecked() an_instance.adoption_notice_status = AdoptionNoticeStatusChoices.AwaitingAction.WAITING_FOR_REVIEW
an_instance.save()
# Get the species and number of animals from the form # Get the species and number of animals from the form
species = form.cleaned_data["species"] species = form.cleaned_data["species"]
@@ -660,7 +664,8 @@ def updatequeue(request):
else: else:
last_checked_adoption_list = AdoptionNotice.objects.filter(owner=request.user).order_by("last_checked") last_checked_adoption_list = AdoptionNotice.objects.filter(owner=request.user).order_by("last_checked")
adoption_notices_active = [adoption for adoption in last_checked_adoption_list if adoption.is_active] adoption_notices_active = [adoption for adoption in last_checked_adoption_list if adoption.is_active]
adoption_notices_disabled = [adoption for adoption in last_checked_adoption_list if adoption.is_disabled_unchecked] adoption_notices_disabled = [adoption for adoption in last_checked_adoption_list if
adoption.adoption_notice_status == AdoptionNoticeStatusChoices.Disabled.UNCHECKED]
context = {"adoption_notices_disabled": adoption_notices_disabled, context = {"adoption_notices_disabled": adoption_notices_disabled,
"adoption_notices_active": adoption_notices_active} "adoption_notices_active": adoption_notices_active}
return render(request, 'fellchensammlung/updatequeue.html', context=context) return render(request, 'fellchensammlung/updatequeue.html', context=context)
@@ -922,7 +927,10 @@ def deactivate_an(request, adoption_notice_id):
adoption_notice = get_object_or_404(AdoptionNotice, pk=adoption_notice_id) adoption_notice = get_object_or_404(AdoptionNotice, pk=adoption_notice_id)
if request.method == "POST": if request.method == "POST":
reason_for_closing = request.POST.get("reason_for_closing") reason_for_closing = request.POST.get("reason_for_closing")
adoption_notice.set_closed(reason_for_closing) if reason_for_closing not in AdoptionNoticeStatusChoices.Closed.choices:
return render(request, "fellchensammlung/errors/403.html", status=403)
adoption_notice.adoption_notice_status = reason_for_closing
adoption_notice.save()
return redirect(reverse("adoption-notice-detail", args=[adoption_notice.pk], )) return redirect(reverse("adoption-notice-detail", args=[adoption_notice.pk], ))
context = {"adoption_notice": adoption_notice, } context = {"adoption_notice": adoption_notice, }
return render(request, 'fellchensammlung/misc/deactivate-an.html', context=context) return render(request, 'fellchensammlung/misc/deactivate-an.html', context=context)

View File

@@ -8,6 +8,7 @@ from django.test import TestCase
from model_bakery import baker from model_bakery import baker
from fellchensammlung.models import AdoptionNotice, RescueOrganization from fellchensammlung.models import AdoptionNotice, RescueOrganization
from fellchensammlung.tools.model_helpers import AdoptionNoticeStatusChoices
class DeactivationTest(TestCase): class DeactivationTest(TestCase):
@@ -25,10 +26,10 @@ class DeactivationTest(TestCase):
name="TestAdoption3", name="TestAdoption3",
created_at=less_than_three_weeks_ago) created_at=less_than_three_weeks_ago)
cls.adoption1.set_active() cls.adoption1.adoption_notice_status = AdoptionNoticeStatusChoices.Active.SEARCHING
cls.adoption1.last_checked = more_than_three_weeks_ago # Reset updated_at to simulate test conditions cls.adoption1.last_checked = more_than_three_weeks_ago # Reset updated_at to simulate test conditions
cls.adoption1.save() cls.adoption1.save()
cls.adoption3.set_active() cls.adoption3.adoption_notice_status = AdoptionNoticeStatusChoices.Active.SEARCHING
cls.adoption3.last_checked = less_than_three_weeks_ago # Reset updated_at to simulate test conditions cls.adoption3.last_checked = less_than_three_weeks_ago # Reset updated_at to simulate test conditions
cls.adoption3.save() cls.adoption3.save()
@@ -67,20 +68,20 @@ class PingTest(TestCase):
name="TestAdoption1", name="TestAdoption1",
created_at=less_than_three_weeks_ago, created_at=less_than_three_weeks_ago,
last_checked=less_than_three_weeks_ago, last_checked=less_than_three_weeks_ago,
further_information=link_active) further_information=link_active,
adoption_notice_status=AdoptionNoticeStatusChoices.Active.SEARCHING)
cls.adoption2 = baker.make(AdoptionNotice, cls.adoption2 = baker.make(AdoptionNotice,
name="TestAdoption2", name="TestAdoption2",
created_at=less_than_three_weeks_ago, created_at=less_than_three_weeks_ago,
last_checked=less_than_three_weeks_ago, last_checked=less_than_three_weeks_ago,
further_information=link_inactive) further_information=link_inactive,
adoption_notice_status=AdoptionNoticeStatusChoices.Active.SEARCHING)
cls.adoption3 = baker.make(AdoptionNotice, cls.adoption3 = baker.make(AdoptionNotice,
name="TestAdoption3", name="TestAdoption3",
created_at=less_than_three_weeks_ago, created_at=less_than_three_weeks_ago,
last_checked=less_than_three_weeks_ago, last_checked=less_than_three_weeks_ago,
further_information=None) further_information=None,
cls.adoption1.set_active() adoption_notice_status=AdoptionNoticeStatusChoices.Active.SEARCHING)
cls.adoption2.set_active()
cls.adoption3.set_active()
def test_is_404(self): def test_is_404(self):
urls = [("https://hyteck.de/maxwell", True), urls = [("https://hyteck.de/maxwell", True),

View File

@@ -7,7 +7,7 @@ from fellchensammlung.models import SearchSubscription, User, TrustLevel, Adopti
from model_bakery import baker from model_bakery import baker
from fellchensammlung.tools.geo import LocationProxy from fellchensammlung.tools.geo import LocationProxy
from fellchensammlung.tools.model_helpers import NotificationTypeChoices from fellchensammlung.tools.model_helpers import NotificationTypeChoices, AdoptionNoticeStatusChoices
from fellchensammlung.tools.search import AdoptionNoticeSearch, notify_search_subscribers from fellchensammlung.tools.search import AdoptionNoticeSearch, notify_search_subscribers
@@ -45,7 +45,7 @@ class TestSearch(TestCase):
species=rat, species=rat,
sex=SexChoices.MALE, sex=SexChoices.MALE,
description="Eine unglaublich süße Ratte") description="Eine unglaublich süße Ratte")
cls.adoption1.set_active() cls.adoption1.adoption_notice_status = AdoptionNoticeStatusChoices.Active.SEARCHING
cls.adoption2 = baker.make(AdoptionNotice, name="TestAdoption2", owner=cls.test_user0, location=cls.location_berlin) cls.adoption2 = baker.make(AdoptionNotice, name="TestAdoption2", owner=cls.test_user0, location=cls.location_berlin)
rat2 = baker.make(Animal, rat2 = baker.make(Animal,
@@ -54,7 +54,7 @@ class TestSearch(TestCase):
species=rat, species=rat,
sex=SexChoices.FEMALE, sex=SexChoices.FEMALE,
description="Eine unglaublich süße Ratte") description="Eine unglaublich süße Ratte")
cls.adoption2.set_active() cls.adoption2.adoption_notice_status = AdoptionNoticeStatusChoices.Active.SEARCHING
cls.subscription1 = SearchSubscription.objects.create(owner=cls.test_user1, cls.subscription1 = SearchSubscription.objects.create(owner=cls.test_user1,
location=cls.location_tue, location=cls.location_tue,

View File

@@ -2,7 +2,7 @@ from django.test import TestCase
from model_bakery import baker from model_bakery import baker
from fellchensammlung.models import User, TrustLevel, Species, Location, AdoptionNotice, Notification from fellchensammlung.models import User, TrustLevel, Species, Location, AdoptionNotice, Notification
from fellchensammlung.tools.model_helpers import NotificationTypeChoices from fellchensammlung.tools.model_helpers import NotificationTypeChoices, AdoptionNoticeStatusChoices
from fellchensammlung.tools.notifications import notify_of_AN_to_be_checked from fellchensammlung.tools.notifications import notify_of_AN_to_be_checked
@@ -26,7 +26,7 @@ class TestNotifications(TestCase):
cls.test_user0.save() cls.test_user0.save()
cls.adoption1 = baker.make(AdoptionNotice, name="TestAdoption1", owner=cls.test_user1, ) cls.adoption1 = baker.make(AdoptionNotice, name="TestAdoption1", owner=cls.test_user1, )
cls.adoption1.set_unchecked() # Could also emit notification cls.adoption1.adoption_notice_status = AdoptionNoticeStatusChoices.AwaitingAction.WAITING_FOR_REVIEW
def test_notify_of_AN_to_be_checked(self): def test_notify_of_AN_to_be_checked(self):
notify_of_AN_to_be_checked(self.adoption1) notify_of_AN_to_be_checked(self.adoption1)

View File

@@ -1,14 +1,11 @@
from django.test import TestCase from django.test import TestCase
from django.contrib.auth.models import Permission
from django.urls import reverse from django.urls import reverse
from model_bakery import baker from model_bakery import baker
from fellchensammlung.models import Animal, Species, AdoptionNotice, User, Location, AdoptionNoticeStatus, TrustLevel, \ from fellchensammlung.models import Species, AdoptionNotice, User, Location, TrustLevel, \
Animal, Subscriptions, Comment, Notification, SearchSubscription Animal, Subscriptions, Comment, Notification
from fellchensammlung.tools.geo import LocationProxy from fellchensammlung.tools.model_helpers import NotificationTypeChoices, AdoptionNoticeStatusChoices
from fellchensammlung.tools.model_helpers import NotificationTypeChoices
from fellchensammlung.views import add_adoption_notice
class AnimalAndAdoptionTest(TestCase): class AnimalAndAdoptionTest(TestCase):
@@ -158,7 +155,7 @@ class UpdateQueueTest(TestCase):
# Make sure correct status is set and AN is not shown anymore # Make sure correct status is set and AN is not shown anymore
self.assertNotContains(response, "TestAdoption3") self.assertNotContains(response, "TestAdoption3")
self.assertFalse(self.adoption3.is_active) self.assertFalse(self.adoption3.is_active)
self.assertEqual(self.adoption3.adoptionnoticestatus.major_status, AdoptionNoticeStatus.CLOSED) self.assertTrue(self.adoption3.is_closed)
class AdoptionDetailTest(TestCase): class AdoptionDetailTest(TestCase):
@@ -189,8 +186,8 @@ class AdoptionDetailTest(TestCase):
adoption3.location = stuttgart adoption3.location = stuttgart
adoption3.save() adoption3.save()
adoption1.set_active() adoption1.adoption_notice_status = AdoptionNoticeStatusChoices.Active.SEARCHING
adoption3.set_active() adoption3.adoption_notice_status = AdoptionNoticeStatusChoices.Active.INTERESTED
adoption2.set_unchecked() adoption2.set_unchecked()
def test_basic_view(self): def test_basic_view(self):

View File

@@ -6,6 +6,8 @@ from fellchensammlung.models import User, TrustLevel, AdoptionNotice, Species, R
Location, ImportantLocation Location, ImportantLocation
from model_bakery import baker from model_bakery import baker
from fellchensammlung.tools.model_helpers import AdoptionNoticeStatusChoices
class BasicViewTest(TestCase): class BasicViewTest(TestCase):
@classmethod @classmethod
@@ -26,7 +28,10 @@ class BasicViewTest(TestCase):
for i in range(0, 8): for i in range(0, 8):
ans.append(baker.make(AdoptionNotice, name=f"TestAdoption{i}")) ans.append(baker.make(AdoptionNotice, name=f"TestAdoption{i}"))
for i in range(0, 4): for i in range(0, 4):
AdoptionNotice.objects.get(name=f"TestAdoption{i}").set_active() adoption_notice = AdoptionNotice.objects.get(name=f"TestAdoption{i}")
adoption_notice.adoption_notice_status = AdoptionNoticeStatusChoices.Active.SEARCHING
adoption_notice.save()
rule1 = Rule.objects.create(title="Rule 1", rule_text="Description of r1", rule_identifier="rule1", rule1 = Rule.objects.create(title="Rule 1", rule_text="Description of r1", rule_identifier="rule1",
language=Language.objects.get(name="English")) language=Language.objects.get(name="English"))

View File

@@ -4,11 +4,8 @@ from django.urls import reverse
from model_bakery import baker from model_bakery import baker
from fellchensammlung.models import Animal, Species, AdoptionNotice, User, Location, AdoptionNoticeStatus, TrustLevel, \ from fellchensammlung.models import AdoptionNotice, User, Location, SearchSubscription
Animal, Subscriptions, Comment, Notification, SearchSubscription from fellchensammlung.tools.model_helpers import AdoptionNoticeStatusChoices
from fellchensammlung.tools.geo import LocationProxy
from fellchensammlung.tools.model_helpers import NotificationTypeChoices
from fellchensammlung.views import add_adoption_notice
class SearchTest(TestCase): class SearchTest(TestCase):
@@ -28,9 +25,11 @@ class SearchTest(TestCase):
# Location of Berlin: lat 52.5170365 lon 13.3888599 PLZ 10115 (Mitte) # Location of Berlin: lat 52.5170365 lon 13.3888599 PLZ 10115 (Mitte)
adoption1 = baker.make(AdoptionNotice, name="TestAdoption1") adoption1 = baker.make(AdoptionNotice, name="TestAdoption1",
adoption_notice_status=AdoptionNoticeStatusChoices.Active.SEARCHING)
adoption2 = baker.make(AdoptionNotice, name="TestAdoption2") adoption2 = baker.make(AdoptionNotice, name="TestAdoption2")
adoption3 = baker.make(AdoptionNotice, name="TestAdoption3") adoption3 = baker.make(AdoptionNotice, name="TestAdoption3",
adoption_notice_status=AdoptionNoticeStatusChoices.Active.INTERESTED)
berlin = Location.get_location_from_string("Berlin") berlin = Location.get_location_from_string("Berlin")
adoption1.location = berlin adoption1.location = berlin
@@ -40,8 +39,6 @@ class SearchTest(TestCase):
adoption3.location = stuttgart adoption3.location = stuttgart
adoption3.save() adoption3.save()
adoption1.set_active()
adoption3.set_active()
adoption2.set_unchecked() adoption2.set_unchecked()
cls.subscription1 = SearchSubscription.objects.create(owner=test_user1, cls.subscription1 = SearchSubscription.objects.create(owner=test_user1,