Compare commits

..

No commits in common. "caf98ba60b8a2b364405beeef15958695ae2351e" and "8de5f162eb46a7737a779abfad635acd8458d24a" have entirely different histories.

7 changed files with 33 additions and 83 deletions

View File

@ -20,35 +20,11 @@ http://notfellchen.org/
Via token
---------
.. warning::
This is currently not supported.
All users are able to generate a token that allows them to use the API. This can be done in the user's profile.
An application can then send this token in the request header for authorization.
.. code-block::
$ curl -X GET http://notfellchen.org/api/adoption_notice -H 'Authorization: Token 49b39856955dc6e5cc04365498d4ad30ea3aed78'
Endpoints
---------
Get Adoption Notices
++++++++++++++++++++
.. code-block::
curl --request GET \
--url http://localhost:8000/api/adoption_notice \
--header 'Authorization: {{token}}'
Create Adoption Notice
++++++++++++++++++++++
.. code-block::
curl --request POST \
--url http://localhost:8000/api/adoption_notice \
--header 'Authorization: {{token}}' \
--header 'content-type: multipart/form-data' \
--form name=TestAdoption1 \
--form searching_since=2024-11-19 \
--form 'description=Lorem ipsum **dolor sit** amet' \
--form further_information=https://notfellchen.org \
--form location_string=Berlin \
--form group_only=true

View File

@ -24,13 +24,6 @@ class AdoptionNoticeAdmin(admin.ModelAdmin):
inlines = [
StatusInline,
]
actions = ("activate",)
def activate(self, request, queryset):
for obj in queryset:
obj.set_active()
activate.short_description = _("Ausgewählte Vermittlungen aktivieren")
# Re-register UserAdmin

View File

@ -1,12 +1,9 @@
from django.contrib.auth.models import User
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework import permissions
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from django.db import transaction
from fellchensammlung.models import AdoptionNotice, Animal, Log, TrustLevel
from fellchensammlung.tasks import add_adoption_notice_location
from ..models import AdoptionNotice
from .serializers import AdoptionNoticeSerializer
@ -21,35 +18,20 @@ class AdoptionNoticeApiView(APIView):
serializer = AdoptionNoticeSerializer(adoption_notices, many=True, context=serializer_context)
return Response(serializer.data, status=status.HTTP_200_OK)
@transaction.atomic
def post(self, request, *args, **kwargs):
"""
API view to add an adoption notice.b
"""
serializer = AdoptionNoticeSerializer(data=request.data, context={'request': request})
if not serializer.is_valid():
data = {
'name': request.data.get('name'),
"searching_since": request.data.get('searching_since'),
"description": request.data.get('description'),
"organization": request.data.get('organization'),
"further_information": request.data.get('further_information'),
"location_string": request.data.get('location_string'),
"group_only": request.data.get('group_only'),
"owner": request.data.get('owner')
}
serializer = AdoptionNoticeSerializer(data=data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
adoption_notice = serializer.save(owner=request.user)
# Add the location
add_adoption_notice_location.delay_on_commit(adoption_notice.pk)
# Only set active when user has trust level moderator or higher
if request.user.trust_level >= TrustLevel.MODERATOR:
adoption_notice.set_active()
else:
adoption_notice.set_unchecked()
# Log the action
Log.objects.create(
user=request.user,
action="add_adoption_notice",
text=f"{request.user} added adoption notice {adoption_notice.pk} via API",
)
# Return success response with new adoption notice details
return Response(
{"message": "Adoption notice created successfully!", "id": adoption_notice.pk},
status=status.HTTP_201_CREATED,
)

View File

@ -350,22 +350,22 @@ class AdoptionNotice(models.Model):
def set_closed(self):
self.last_checked = timezone.now()
self.save()
self.adoptionnoticestatus.set_closed()
self.save()
def set_active(self):
self.last_checked = timezone.now()
self.save()
if not hasattr(self, 'adoptionnoticestatus'):
AdoptionNoticeStatus.create_other(self)
self.adoptionnoticestatus.set_active()
self.save()
def set_unchecked(self):
self.last_checked = timezone.now()
self.save()
if not hasattr(self, 'adoptionnoticestatus'):
AdoptionNoticeStatus.create_other(self)
self.adoptionnoticestatus.set_unchecked()
self.save()
for subscription in self.get_subscriptions():
notification_title = _("Vermittlung deaktiviert:") + f" {self}"

View File

@ -53,11 +53,11 @@ def clean_locations(quiet=True):
def get_unchecked_adoption_notices(weeks=3):
now = timezone.now()
n_weeks_ago = now - timedelta(weeks=weeks)
three_weeks_ago = now - timedelta(weeks=weeks)
# Query for active adoption notices that were not checked in the last n weeks
# Query for active adoption notices that were checked in the last three weeks
unchecked_adoptions = AdoptionNotice.objects.filter(
last_checked__lte=n_weeks_ago
last_checked__lte=three_weeks_ago
)
active_unchecked_adoptions = [adoption for adoption in unchecked_adoptions if adoption.is_active]
return active_unchecked_adoptions
@ -71,7 +71,7 @@ def get_active_adoption_notices():
def deactivate_unchecked_adoption_notices():
for adoption_notice in get_unchecked_adoption_notices(weeks=3):
adoption_notice.set_unchecked()
AdoptionNoticeStatus.objects.get(adoption_notice=adoption_notice).set_unchecked()
def deactivate_404_adoption_notices():

View File

@ -10,7 +10,7 @@ from model_bakery import baker
from fellchensammlung.models import AdoptionNotice
class DeactivationTest(TestCase):
class DeactiviationTest(TestCase):
@classmethod
def setUpTestData(cls):
now = timezone.now()
@ -19,18 +19,16 @@ class DeactivationTest(TestCase):
cls.adoption1 = baker.make(AdoptionNotice,
name="TestAdoption1",
created_at=more_than_three_weeks_ago)
created_at=more_than_three_weeks_ago,
last_checked=more_than_three_weeks_ago)
cls.adoption2 = baker.make(AdoptionNotice, name="TestAdoption2")
cls.adoption3 = baker.make(AdoptionNotice,
name="TestAdoption3",
created_at=less_than_three_weeks_ago)
created_at=less_than_three_weeks_ago,
last_checked=less_than_three_weeks_ago)
cls.adoption1.set_active()
cls.adoption1.last_checked = more_than_three_weeks_ago # Reset updated_at to simulate test conditions
cls.adoption1.save()
cls.adoption3.set_active()
cls.adoption3.last_checked = less_than_three_weeks_ago # Reset updated_at to simulate test conditions
cls.adoption3.save()
def test_get_unchecked_adoption_notices(self):
result = get_unchecked_adoption_notices()
@ -96,3 +94,4 @@ class PingTest(TestCase):
self.adoption2.refresh_from_db()
self.assertTrue(self.adoption1.is_active)
self.assertFalse(self.adoption2.is_active)