diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..a55e7a1 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/Procfile.tailwind b/Procfile.tailwind new file mode 100644 index 0000000..bd98629 --- /dev/null +++ b/Procfile.tailwind @@ -0,0 +1,2 @@ +django: python manage.py runserver +tailwind: python manage.py tailwind start \ No newline at end of file diff --git a/TeamForge/settings.py b/TeamForge/settings.py index 9d1ca02..6b3c506 100644 --- a/TeamForge/settings.py +++ b/TeamForge/settings.py @@ -132,7 +132,7 @@ MEDIA_ROOT = BASE_DIR / "media" CONSTANCE_BACKEND = "constance.backends.database.DatabaseBackend" CONSTANCE_CONFIG = { "TF_CLUB_NAME": (config("TF_CLUB_NAME", default="TeamForge", cast=str), "Club Name", str), - "TF_CLUB_HOME": (config("TF_CLUB_HOME", default="TeamForge", cast=str), "Club Location", str), + "TF_CLUB_HOME": (config("TF_CLUB_HOME", default="TeamForge Home", cast=str), "Club Location", str), "TF_DEFAULT_SEASON_MONTH": (config("TF_DEFAULT_SEASON_MONTH", default=8, cast=int), "Default season start month", int), "TF_DEFAULT_SEASON_DAY": (config("TF_DEFAULT_SEASON_DAY", default=1, cast=int), "Default season start day", int), "TF_DEFAULT_SEASON_DURATION": (config("TF_DEFAULT_SEASON_DURATION", default="1y", cast=str), "Default season duration", str), diff --git a/members/admin.py b/members/admin.py index 8c38f3f..af69ec6 100644 --- a/members/admin.py +++ b/members/admin.py @@ -1,3 +1,28 @@ from django.contrib import admin +from django.utils.translation import gettext_lazy as _ -# Register your models here. +from .models import Member + + +@admin.register(Member) +class MemberAdmin(admin.ModelAdmin): + def family_member_count(self, obj): + return obj.family_members.count() + + def show_user_is_active(self, obj): + return obj.user.is_active + + show_user_is_active.boolean = True + show_user_is_active.short_description = _("active?") + + list_display = ["__str__", "user__email", "show_user_is_active", "family_member_count", "birthday", "created", "updated"] + date_hierarchy = "birthday" + list_filter = ["user__is_superuser", "user__is_active"] + readonly_fields = ["created", "updated", "access_token"] + filter_horizontal = ["family_members"] + raw_id_fields = ["user"] + fieldsets = [ + ("GENERAL INFORMATION", {"fields": ["user", "family_members", "birthday", "license", "access_token"]}), + ("CONTACT_INFORMATION", {"fields": ["phone_number", "emergency_phone_number"]}), + ("METADATA", {"fields": ["created", "updated"]}), + ] diff --git a/members/migrations/0003_member_created_member_updated_alter_member_family.py b/members/migrations/0003_member_created_member_updated_alter_member_family.py new file mode 100644 index 0000000..86cb857 --- /dev/null +++ b/members/migrations/0003_member_created_member_updated_alter_member_family.py @@ -0,0 +1,36 @@ +# Generated by Django 6.0 on 2026-01-03 12:00 + +import django.utils.timezone +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("members", "0002_member_family"), + ] + + operations = [ + migrations.AddField( + model_name="member", + name="created", + field=models.DateTimeField( + auto_now_add=True, + default=django.utils.timezone.now, + verbose_name="created", + ), + preserve_default=False, + ), + migrations.AddField( + model_name="member", + name="updated", + field=models.DateTimeField(auto_now=True, verbose_name="updated"), + ), + migrations.AlterField( + model_name="member", + name="family", + field=models.ManyToManyField( + blank=True, to="members.member", verbose_name="family" + ), + ), + ] diff --git a/members/migrations/0004_member_access_token_member_birthday_and_more.py b/members/migrations/0004_member_access_token_member_birthday_and_more.py new file mode 100644 index 0000000..2747b2c --- /dev/null +++ b/members/migrations/0004_member_access_token_member_birthday_and_more.py @@ -0,0 +1,55 @@ +# Generated by Django 6.0 on 2026-01-03 12:12 + +import phonenumber_field.modelfields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("members", "0003_member_created_member_updated_alter_member_family"), + ] + + operations = [ + migrations.AddField( + model_name="member", + name="access_token", + field=models.CharField( + blank=True, max_length=255, null=True, verbose_name="access token" + ), + ), + migrations.AddField( + model_name="member", + name="birthday", + field=models.DateField(blank=True, null=True, verbose_name="birthday"), + ), + migrations.AddField( + model_name="member", + name="emergency_phone_number", + field=phonenumber_field.modelfields.PhoneNumberField( + blank=True, + max_length=128, + null=True, + region=None, + verbose_name="emergency phone number", + ), + ), + migrations.AddField( + model_name="member", + name="license", + field=models.CharField( + blank=True, max_length=20, null=True, verbose_name="license" + ), + ), + migrations.AddField( + model_name="member", + name="phone_number", + field=phonenumber_field.modelfields.PhoneNumberField( + blank=True, + max_length=128, + null=True, + region=None, + verbose_name="phone number", + ), + ), + ] diff --git a/members/migrations/0005_remove_member_family_member_family_members.py b/members/migrations/0005_remove_member_family_member_family_members.py new file mode 100644 index 0000000..c14fcbc --- /dev/null +++ b/members/migrations/0005_remove_member_family_member_family_members.py @@ -0,0 +1,24 @@ +# Generated by Django 6.0 on 2026-01-03 12:20 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("members", "0004_member_access_token_member_birthday_and_more"), + ] + + operations = [ + migrations.RemoveField( + model_name="member", + name="family", + ), + migrations.AddField( + model_name="member", + name="family_members", + field=models.ManyToManyField( + blank=True, to="members.member", verbose_name="family members" + ), + ), + ] diff --git a/members/models.py b/members/models.py index 315ccb1..3ae0762 100644 --- a/members/models.py +++ b/members/models.py @@ -1,15 +1,34 @@ from django.conf import settings from django.db import models from django.utils.translation import gettext_lazy as _ +from phonenumber_field.modelfields import PhoneNumberField from rules import is_superuser from rules.contrib.models import RulesModel from members.rules import is_member_manager +class MemberManager(models.Manager): + def get_queryset(self) -> models.QuerySet: + return super().get_queryset().select_related("user") + + class Member(RulesModel): user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="member", verbose_name=_("user")) - family = models.ManyToManyField("self", symmetrical=True, blank=True, verbose_name=_("family")) + family_members = models.ManyToManyField("self", symmetrical=True, blank=True, verbose_name=_("family members")) + + birthday = models.DateField(_("birthday"), blank=True, null=True) + license = models.CharField(_("license"), max_length=20, blank=True, null=True) + + phone_number = PhoneNumberField(_("phone number"), blank=True, null=True) + emergency_phone_number = PhoneNumberField(_("emergency phone number"), blank=True, null=True) + + access_token = models.CharField(_("access token"), max_length=255, blank=True, null=True) + + created = models.DateTimeField(auto_now_add=True, verbose_name=_("created")) + updated = models.DateTimeField(auto_now=True, verbose_name=_("updated")) + + objects = MemberManager() class Meta: verbose_name = _("member")