From e03c6c0a14bd58c1708fcbadeb849c2e6cdf3dab Mon Sep 17 00:00:00 2001 From: Kukl3v <91890264+Kukl3v@users.noreply.github.com> Date: Wed, 9 Oct 2024 21:15:08 +0400 Subject: [PATCH] GymProgram and Appointment entities --- server/appointment/__init__.py | 0 server/appointment/admin.py | 3 + server/appointment/apps.py | 6 ++ server/appointment/migrations/0001_initial.py | 25 +++++++ server/appointment/migrations/0002_initial.py | 22 +++++++ server/appointment/migrations/0003_initial.py | 23 +++++++ server/appointment/migrations/__init__.py | 0 server/appointment/models.py | 11 ++++ server/appointment/serializers.py | 16 +++++ server/appointment/tests.py | 3 + server/appointment/views.py | 11 ++++ server/gym_program/migrations/0001_initial.py | 27 ++++++++ server/gym_program/migrations/0002_initial.py | 23 +++++++ server/gym_program/models.py | 15 ++++- server/gym_program/serializers.py | 16 +++++ server/gym_program/views.py | 65 ++++++++++++++++++- server/metric/migrations/0001_initial.py | 9 ++- server/metric/migrations/0002_initial.py | 23 +++++++ server/metric/models.py | 5 +- server/metric/serializers.py | 17 +++++ server/metric/views.py | 26 ++++---- server/server/settings.py | 2 + server/training/__init__.py | 0 server/training/admin.py | 3 + server/training/apps.py | 6 ++ server/training/migrations/__init__.py | 0 server/training/models.py | 3 + server/training/tests.py | 3 + server/training/views.py | 3 + server/user/migrations/0001_initial.py | 4 +- server/user/models.py | 3 + 31 files changed, 350 insertions(+), 23 deletions(-) create mode 100644 server/appointment/__init__.py create mode 100644 server/appointment/admin.py create mode 100644 server/appointment/apps.py create mode 100644 server/appointment/migrations/0001_initial.py create mode 100644 server/appointment/migrations/0002_initial.py create mode 100644 server/appointment/migrations/0003_initial.py create mode 100644 server/appointment/migrations/__init__.py create mode 100644 server/appointment/models.py create mode 100644 server/appointment/serializers.py create mode 100644 server/appointment/tests.py create mode 100644 server/appointment/views.py create mode 100644 server/gym_program/migrations/0001_initial.py create mode 100644 server/gym_program/migrations/0002_initial.py create mode 100644 server/gym_program/serializers.py create mode 100644 server/metric/migrations/0002_initial.py create mode 100644 server/training/__init__.py create mode 100644 server/training/admin.py create mode 100644 server/training/apps.py create mode 100644 server/training/migrations/__init__.py create mode 100644 server/training/models.py create mode 100644 server/training/tests.py create mode 100644 server/training/views.py diff --git a/server/appointment/__init__.py b/server/appointment/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/server/appointment/admin.py b/server/appointment/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/server/appointment/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/server/appointment/apps.py b/server/appointment/apps.py new file mode 100644 index 0000000..7b5e362 --- /dev/null +++ b/server/appointment/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class AppointmentConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'appointment' diff --git a/server/appointment/migrations/0001_initial.py b/server/appointment/migrations/0001_initial.py new file mode 100644 index 0000000..7723b82 --- /dev/null +++ b/server/appointment/migrations/0001_initial.py @@ -0,0 +1,25 @@ +# Generated by Django 4.2.16 on 2024-10-09 16:37 + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Appointment', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('start_date', models.DateField(default=django.utils.timezone.now)), + ], + options={ + 'db_table': 'appointment_table', + }, + ), + ] diff --git a/server/appointment/migrations/0002_initial.py b/server/appointment/migrations/0002_initial.py new file mode 100644 index 0000000..2d4bc2d --- /dev/null +++ b/server/appointment/migrations/0002_initial.py @@ -0,0 +1,22 @@ +# Generated by Django 4.2.16 on 2024-10-09 16:37 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('gym_program', '0001_initial'), + ('appointment', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='appointment', + name='gym_program', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='gym_program.gymprogram'), + ), + ] diff --git a/server/appointment/migrations/0003_initial.py b/server/appointment/migrations/0003_initial.py new file mode 100644 index 0000000..ca80a62 --- /dev/null +++ b/server/appointment/migrations/0003_initial.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.16 on 2024-10-09 16:37 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('appointment', '0002_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.AddField( + model_name='appointment', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/server/appointment/migrations/__init__.py b/server/appointment/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/server/appointment/models.py b/server/appointment/models.py new file mode 100644 index 0000000..052fda2 --- /dev/null +++ b/server/appointment/models.py @@ -0,0 +1,11 @@ +from django.db import models +from django.utils import timezone + + +class Appointment(models.Model): + user = models.ForeignKey('user.User', on_delete=models.CASCADE) + gym_program = models.ForeignKey('gym_program.GymProgram', on_delete=models.CASCADE) + start_date = models.DateField(blank=False, null=False, default=timezone.now) + + class Meta: + db_table = 'appointment_table' diff --git a/server/appointment/serializers.py b/server/appointment/serializers.py new file mode 100644 index 0000000..287c17f --- /dev/null +++ b/server/appointment/serializers.py @@ -0,0 +1,16 @@ +from rest_framework import serializers +from server.user.serializers import CustomUserDetailsSerializer +from server.gym_program.serializers import GymProgramSerializer +from .models import Appointment + + +class AppointmentSerializer(serializers.ModelSerializer): + user = CustomUserDetailsSerializer(read_only=True) + gym_program = GymProgramSerializer(read_only=True) + + class Meta: + model = Appointment + fields = ('id', + 'user', + 'gym_program', + 'start_date') diff --git a/server/appointment/tests.py b/server/appointment/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/server/appointment/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/server/appointment/views.py b/server/appointment/views.py new file mode 100644 index 0000000..9380c16 --- /dev/null +++ b/server/appointment/views.py @@ -0,0 +1,11 @@ +from rest_framework.decorators import api_view +from .models import Appointment +from .serializers import AppointmentSerializer +from rest_framework.response import Response + + +@api_view(['GET']) +def appointment_list(request): + appointments = Appointment.objects.all() + serializer = AppointmentSerializer(appointments, many=True) + return Response(serializer.data) diff --git a/server/gym_program/migrations/0001_initial.py b/server/gym_program/migrations/0001_initial.py new file mode 100644 index 0000000..13a658c --- /dev/null +++ b/server/gym_program/migrations/0001_initial.py @@ -0,0 +1,27 @@ +# Generated by Django 4.2.16 on 2024-10-09 16:37 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='GymProgram', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(default='', max_length=64)), + ('description', models.TextField(blank=True, default='')), + ('duration', models.PositiveSmallIntegerField(validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4)])), + ], + options={ + 'db_table': 'gym_program_table', + }, + ), + ] diff --git a/server/gym_program/migrations/0002_initial.py b/server/gym_program/migrations/0002_initial.py new file mode 100644 index 0000000..ecb4ffb --- /dev/null +++ b/server/gym_program/migrations/0002_initial.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.16 on 2024-10-09 16:37 + +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('gym_program', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('appointment', '0003_initial'), + ] + + operations = [ + migrations.AddField( + model_name='gymprogram', + name='users', + field=models.ManyToManyField(through='appointment.Appointment', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/server/gym_program/models.py b/server/gym_program/models.py index 71a8362..f971d4b 100644 --- a/server/gym_program/models.py +++ b/server/gym_program/models.py @@ -1,3 +1,16 @@ from django.db import models +from django.core.validators import MinValueValidator, MaxValueValidator -# Create your models here. + +class GymProgram(models.Model): + + name = models.CharField(max_length=64, blank=False, default='') + description = models.TextField(blank=True, default='') + duration = models.PositiveSmallIntegerField(validators=[MinValueValidator(1), MaxValueValidator(4)]) + users = models.ManyToManyField('user.User', through='appointment.Appointment') + + def __str__(self): + return f"Name: {self.name}, Description: {self.description}, Duration: {self.duration}" + + class Meta: + db_table = 'gym_program_table' diff --git a/server/gym_program/serializers.py b/server/gym_program/serializers.py new file mode 100644 index 0000000..fd85b7e --- /dev/null +++ b/server/gym_program/serializers.py @@ -0,0 +1,16 @@ +from rest_framework import serializers +from .models import GymProgram +from server.user.serializers import CustomUserDetailsSerializer + + +class GymProgramSerializer(serializers.ModelSerializer): + users = CustomUserDetailsSerializer(many=True, read_only=True) + + class Meta: + model = GymProgram + fields = ('id', + 'name', + 'description', + 'duration', + 'users' + ) diff --git a/server/gym_program/views.py b/server/gym_program/views.py index 91ea44a..32ad478 100644 --- a/server/gym_program/views.py +++ b/server/gym_program/views.py @@ -1,3 +1,64 @@ -from django.shortcuts import render +from rest_framework.decorators import api_view, permission_classes +from rest_framework.response import Response +from rest_framework import status +from django.shortcuts import get_object_or_404 -# Create your views here. +from .models import GymProgram +from server.appointment.models import Appointment +from .serializers import GymProgramSerializer +from server.appointment.serializers import AppointmentSerializer +from server.user.models import User + + +@api_view(['GET', 'POST']) +def gym_program_list(request): + if request.method == 'GET': + gym_programs = GymProgram.objects.all() + serializer = GymProgramSerializer(gym_programs, many=True) + return Response(serializer.data) + + elif request.method == 'POST': + serializer = GymProgramSerializer(data=request.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) + + +@api_view(['GET', 'PUT', 'DELETE']) +def gym_program_detail(request, pk): + gym_program = get_object_or_404(GymProgram, pk=pk) + + if request.method == 'GET': + serializer = GymProgramSerializer(gym_program) + return Response(serializer.data) + + elif request.method == 'PUT': + serializer = GymProgramSerializer(gym_program, data=request.data) + if serializer.is_valid(): + serializer.save() + return Response(serializer.data) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + elif request.method == 'DELETE': + gym_program.delete() + return Response(status=status.HTTP_204_NO_CONTENT) + + +@api_view(['POST', 'DELETE']) +def manage_user_program(request, gym_program_pk, user_pk): + gym_program = get_object_or_404(GymProgram, pk=gym_program_pk) + user = get_object_or_404(User, pk=user_pk) + + if request.method == 'POST': + if Appointment.objects.filter(user=user, gym_program=gym_program).exists(): + return Response({"detail": "User is already part of the program."}, status=status.HTTP_400_BAD_REQUEST) + + appointment = Appointment.objects.create(user=user, gym_program=gym_program) + serializer = AppointmentSerializer(appointment) + return Response(serializer.data, status=status.HTTP_201_CREATED) + + elif request.method == 'DELETE': + appointment = get_object_or_404(Appointment, gym_program=gym_program, user=user) + appointment.delete() + return Response(status=status.HTTP_204_NO_CONTENT) diff --git a/server/metric/migrations/0001_initial.py b/server/metric/migrations/0001_initial.py index 75f1067..8cd107e 100644 --- a/server/metric/migrations/0001_initial.py +++ b/server/metric/migrations/0001_initial.py @@ -1,9 +1,7 @@ -# Generated by Django 4.2.16 on 2024-10-05 14:16 +# Generated by Django 4.2.16 on 2024-10-09 16:37 -from django.conf import settings import django.core.validators from django.db import migrations, models -import django.db.models.deletion class Migration(migrations.Migration): @@ -11,7 +9,6 @@ class Migration(migrations.Migration): initial = True dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ @@ -23,7 +20,9 @@ class Migration(migrations.Migration): ('weight', models.FloatField(default=0.0, validators=[django.core.validators.MinValueValidator(0.0)])), ('height', models.FloatField(default=0.0, validators=[django.core.validators.MinValueValidator(0.0)])), ('birth_date', models.DateField(default='2000-01-01')), - ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], + options={ + 'db_table': 'metric_table', + }, ), ] diff --git a/server/metric/migrations/0002_initial.py b/server/metric/migrations/0002_initial.py new file mode 100644 index 0000000..43015cd --- /dev/null +++ b/server/metric/migrations/0002_initial.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.16 on 2024-10-09 16:37 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('metric', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='metric', + name='user', + field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/server/metric/models.py b/server/metric/models.py index 9715e3a..aaf7808 100644 --- a/server/metric/models.py +++ b/server/metric/models.py @@ -20,4 +20,7 @@ class Metric(models.Model): birth_date = models.DateField(blank=False, null=False, default='2000-01-01') def __str__(self): - return f"{self.gender}, Weight: {self.weight}, Height: {self.height}, Birth date: {self.birth_date}" + return f"Gender: {self.gender}, Weight: {self.weight}, Height: {self.height}, Birth date: {self.birth_date}" + + class Meta: + db_table = 'metric_table' diff --git a/server/metric/serializers.py b/server/metric/serializers.py index 150bb1a..f6c7e3e 100644 --- a/server/metric/serializers.py +++ b/server/metric/serializers.py @@ -11,3 +11,20 @@ class MetricSerializer(serializers.ModelSerializer): 'height', 'birth_date' ) + + +class MetricListSerializer(serializers.ModelSerializer): + email = serializers.SerializerMethodField() + + class Meta: + model = Metric + fields = ('id', + 'email', + 'gender', + 'weight', + 'height', + 'birth_date' + ) + + def get_email(self, obj): + return obj.user.email diff --git a/server/metric/views.py b/server/metric/views.py index 59d564d..2bd814f 100644 --- a/server/metric/views.py +++ b/server/metric/views.py @@ -3,18 +3,29 @@ from rest_framework.response import Response from rest_framework import status from django.shortcuts import get_object_or_404 from .models import Metric -from .serializers import MetricSerializer +from .serializers import MetricSerializer, MetricListSerializer @api_view(['GET', 'POST']) def metric_list(request): + user = request.user + if request.method == 'GET': metrics = Metric.objects.all() - serializer = MetricSerializer(metrics, many=True) + serializer = MetricListSerializer(metrics, many=True) return Response(serializer.data) + elif request.method == 'POST': + if Metric.objects.filter(user=user).exists(): + return Response({'detail': 'Metric already exists for this user.'}, status=status.HTTP_400_BAD_REQUEST) + serializer = MetricSerializer(data=request.data) + if serializer.is_valid(): + serializer.save(user=user) + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) -@api_view(['GET', 'PUT', 'POST', 'DELETE']) + +@api_view(['GET', 'PUT', 'DELETE']) def metric_detail(request): user = request.user @@ -31,15 +42,6 @@ def metric_detail(request): return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) - elif request.method == 'POST': - if Metric.objects.filter(user=user).exists(): - return Response({'detail': 'Metric already exists for this user.'}, status=status.HTTP_400_BAD_REQUEST) - serializer = MetricSerializer(data=request.data) - if serializer.is_valid(): - serializer.save(user=user) - return Response(serializer.data, status=status.HTTP_201_CREATED) - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) - elif request.method == 'DELETE': metric = get_object_or_404(Metric, user=user) metric.delete() diff --git a/server/server/settings.py b/server/server/settings.py index d5558bc..95f5835 100644 --- a/server/server/settings.py +++ b/server/server/settings.py @@ -51,6 +51,8 @@ INSTALLED_APPS = [ 'corsheaders', 'user.apps.UserConfig', 'metric.apps.MetricConfig', + 'gym_program.apps.GymProgramConfig', + 'appointment.apps.AppointmentConfig', ] MIDDLEWARE = [ diff --git a/server/training/__init__.py b/server/training/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/server/training/admin.py b/server/training/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/server/training/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/server/training/apps.py b/server/training/apps.py new file mode 100644 index 0000000..8051e6c --- /dev/null +++ b/server/training/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class TrainingConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'training' diff --git a/server/training/migrations/__init__.py b/server/training/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/server/training/models.py b/server/training/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/server/training/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/server/training/tests.py b/server/training/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/server/training/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/server/training/views.py b/server/training/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/server/training/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/server/user/migrations/0001_initial.py b/server/user/migrations/0001_initial.py index 4566677..176a1df 100644 --- a/server/user/migrations/0001_initial.py +++ b/server/user/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.16 on 2024-10-05 11:19 +# Generated by Django 4.2.16 on 2024-10-09 16:37 from django.db import migrations, models import user.models @@ -27,7 +27,7 @@ class Migration(migrations.Migration): ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')), ], options={ - 'abstract': False, + 'db_table': 'user_table', }, managers=[ ('objects', user.models.UserManager()), diff --git a/server/user/models.py b/server/user/models.py index f16a088..050efdc 100644 --- a/server/user/models.py +++ b/server/user/models.py @@ -33,3 +33,6 @@ class User(AbstractBaseUser, PermissionsMixin): def __str__(self): return self.email + + class Meta: + db_table = 'user_table'