feat: Make date of birt optional, fixes #30

This commit is contained in:
2026-01-20 22:15:16 +01:00
parent 0e6a9c7c7d
commit 9457b19e83
3 changed files with 120 additions and 8 deletions

View File

@@ -5,9 +5,8 @@ from .models import AdoptionNotice, Animal, Image, ReportAdoptionNotice, ReportC
Comment, SexChoicesWithAll, DistanceChoices, SpeciesSpecificURL, RescueOrganization Comment, SexChoicesWithAll, DistanceChoices, SpeciesSpecificURL, RescueOrganization
from django_registration.forms import RegistrationForm from django_registration.forms import RegistrationForm
from crispy_forms.helper import FormHelper from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit, Layout, Fieldset, HTML, Row, Column, Field, Hidden from crispy_forms.layout import Submit, Layout, Fieldset
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from notfellchen.settings import MEDIA_URL
from crispy_forms.layout import Div from crispy_forms.layout import Div
from .tools.model_helpers import reason_for_signup_label, reason_for_signup_help_text, AdoptionNoticeStatusChoices from .tools.model_helpers import reason_for_signup_label, reason_for_signup_help_text, AdoptionNoticeStatusChoices

View File

@@ -0,0 +1,104 @@
# Generated by Django 5.2.8 on 2026-01-20 21:09
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("fellchensammlung", "0073_adoption_notice_status_successful"),
]
operations = [
migrations.AlterField(
model_name="animal",
name="date_of_birth",
field=models.DateField(blank=True, null=True, verbose_name="Geburtsdatum"),
),
migrations.AlterField(
model_name="historicalanimal",
name="date_of_birth",
field=models.DateField(blank=True, null=True, verbose_name="Geburtsdatum"),
),
migrations.AlterField(
model_name="historicalrescueorganization",
name="external_object_identifier",
field=models.CharField(
blank=True,
help_text="Id des Objekts in der externen Datenbank (kann leer gelassen werden)",
max_length=200,
null=True,
verbose_name="External Object Identifier",
),
),
migrations.AlterField(
model_name="historicalrescueorganization",
name="external_source_identifier",
field=models.CharField(
blank=True,
choices=[("OSM", "Open Street Map")],
help_text="Name der Datenbank aus der die Tierschutzorganisation importiert wurde (kann leer gelassen werden)",
max_length=200,
null=True,
verbose_name="External Source Identifier",
),
),
migrations.AlterField(
model_name="historicalrescueorganization",
name="parent_org",
field=models.ForeignKey(
blank=True,
db_constraint=False,
null=True,
on_delete=django.db.models.deletion.DO_NOTHING,
related_name="+",
to="fellchensammlung.rescueorganization",
verbose_name="Übergeordnete Organisation",
),
),
migrations.AlterField(
model_name="rescueorganization",
name="external_object_identifier",
field=models.CharField(
blank=True,
help_text="Id des Objekts in der externen Datenbank (kann leer gelassen werden)",
max_length=200,
null=True,
verbose_name="External Object Identifier",
),
),
migrations.AlterField(
model_name="rescueorganization",
name="external_source_identifier",
field=models.CharField(
blank=True,
choices=[("OSM", "Open Street Map")],
help_text="Name der Datenbank aus der die Tierschutzorganisation importiert wurde (kann leer gelassen werden)",
max_length=200,
null=True,
verbose_name="External Source Identifier",
),
),
migrations.AlterField(
model_name="rescueorganization",
name="parent_org",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.PROTECT,
to="fellchensammlung.rescueorganization",
verbose_name="Übergeordnete Organisation",
),
),
migrations.AlterField(
model_name="speciesspecificurl",
name="rescue_organization",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="species_specific_urls",
to="fellchensammlung.rescueorganization",
verbose_name="Tierschutzorganisation",
),
),
]

View File

@@ -168,11 +168,13 @@ class RescueOrganization(models.Model):
description = models.TextField(null=True, blank=True, verbose_name=_('Beschreibung')) # Markdown allowed description = models.TextField(null=True, blank=True, verbose_name=_('Beschreibung')) # Markdown allowed
external_object_identifier = models.CharField(max_length=200, null=True, blank=True, external_object_identifier = models.CharField(max_length=200, null=True, blank=True,
verbose_name=_('External Object Identifier'), verbose_name=_('External Object Identifier'),
help_text=_("Id des Objekts in der externen Datenbank (kann leer gelassen werden)")) help_text=_(
"Id des Objekts in der externen Datenbank (kann leer gelassen werden)"))
external_source_identifier = models.CharField(max_length=200, null=True, blank=True, external_source_identifier = models.CharField(max_length=200, null=True, blank=True,
choices=ExternalSourceChoices.choices, choices=ExternalSourceChoices.choices,
verbose_name=_('External Source Identifier'), verbose_name=_('External Source Identifier'),
help_text=_("Name der Datenbank aus der die Tierschutzorganisation importiert wurde (kann leer gelassen werden)")) help_text=_(
"Name der Datenbank aus der die Tierschutzorganisation importiert wurde (kann leer gelassen werden)"))
exclude_from_check = models.BooleanField(default=False, verbose_name=_('Von Prüfung ausschließen'), exclude_from_check = models.BooleanField(default=False, verbose_name=_('Von Prüfung ausschließen'),
help_text=_("Organisation von der manuellen Überprüfung ausschließen, " help_text=_("Organisation von der manuellen Überprüfung ausschließen, "
"z.B. weil Tiere nicht online geführt werden")) "z.B. weil Tiere nicht online geführt werden"))
@@ -185,7 +187,8 @@ class RescueOrganization(models.Model):
ongoing_communication = models.BooleanField(default=False, verbose_name=_('In aktiver Kommunikation'), ongoing_communication = models.BooleanField(default=False, verbose_name=_('In aktiver Kommunikation'),
help_text=_( help_text=_(
"Es findet gerade Kommunikation zwischen Notfellchen und der Organisation statt.")) "Es findet gerade Kommunikation zwischen Notfellchen und der Organisation statt."))
parent_org = models.ForeignKey("RescueOrganization", on_delete=models.PROTECT, blank=True, null=True, verbose_name=_("Übergeordnete Organisation")) parent_org = models.ForeignKey("RescueOrganization", on_delete=models.PROTECT, blank=True, null=True,
verbose_name=_("Übergeordnete Organisation"))
# allows to specify if a rescue organization has a specialization for dedicated species # allows to specify if a rescue organization has a specialization for dedicated species
specializations = models.ManyToManyField(Species, blank=True) specializations = models.ManyToManyField(Species, blank=True)
twenty_id = models.UUIDField(verbose_name=_("Twenty-ID"), null=True, blank=True, twenty_id = models.UUIDField(verbose_name=_("Twenty-ID"), null=True, blank=True,
@@ -634,7 +637,7 @@ class Animal(models.Model):
verbose_name = _('Tier') verbose_name = _('Tier')
verbose_name_plural = _('Tiere') verbose_name_plural = _('Tiere')
date_of_birth = models.DateField(verbose_name=_('Geburtsdatum')) date_of_birth = models.DateField(verbose_name=_('Geburtsdatum'), null=True, blank=True)
name = models.CharField(max_length=200, verbose_name=_('Name')) name = models.CharField(max_length=200, verbose_name=_('Name'))
description = models.TextField(null=True, blank=True, verbose_name=_('Beschreibung')) description = models.TextField(null=True, blank=True, verbose_name=_('Beschreibung'))
species = models.ForeignKey(Species, on_delete=models.PROTECT, verbose_name=_("Tierart")) species = models.ForeignKey(Species, on_delete=models.PROTECT, verbose_name=_("Tierart"))
@@ -655,12 +658,18 @@ class Animal(models.Model):
@property @property
def age(self): def age(self):
return timezone.now().today().date() - self.date_of_birth if self.date_of_birth:
return timezone.now().today().date() - self.date_of_birth
else:
return None
@property @property
def hr_age(self): def hr_age(self):
"""Returns a human-readable age based on the date of birth.""" """Returns a human-readable age based on the date of birth."""
return misc.age_as_hr_string(self.age) if self.date_of_birth:
return misc.age_as_hr_string(self.age)
else:
return _("Unbekannt")
def get_photo(self): def get_photo(self):
""" """