From 91e747837c324cb76a22fb4045ee889773464903 Mon Sep 17 00:00:00 2001 From: Glenda Emanuella Sutanto Date: Mon, 10 May 2021 03:35:02 +0700 Subject: [PATCH 01/10] [RED] Created tests for diet recommendation in profile --- profile_dietku/tests.py | 125 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 3 deletions(-) diff --git a/profile_dietku/tests.py b/profile_dietku/tests.py index d0fc3cd..47e22b5 100644 --- a/profile_dietku/tests.py +++ b/profile_dietku/tests.py @@ -1,6 +1,8 @@ import json +import io from django.test import TestCase from django.contrib.auth.models import Group +from django.core.files.uploadedfile import SimpleUploadedFile from rest_framework.test import APITestCase, APIClient from rest_framework import status from dietela_quiz.models import DietProfile @@ -8,6 +10,8 @@ from authentication.models import CustomUser from nutritionists.models import Nutritionist from authentication.serializers import CustomUserDetailsSerializer from django.db.models import Q +from .models import DietRecommendation + class GetProfilesTest(APITestCase): client = APIClient() @@ -116,7 +120,122 @@ class GetProfilesTest(APITestCase): self.assertEqual(response.data, serializer.data) self.assertEqual(response.status_code, status.HTTP_200_OK) - - - +class DietRecommendationTests(APITestCase): + + @classmethod + def setUpTestData(cls): + cls.BASE_URL = "/diet-recommendation/" + + cls.nutritionist = Nutritionist.objects.create( + id=1, + full_name_and_degree="Test, S.Gz", + registration_certificate_no="1234567890", + university="Universitas Indonesia", + mastered_nutritional_problems="Manajemen berat badan, hipertensi", + handled_age_group="12-17 tahun (Remaja)", + another_practice_place="RSCM", + languages="Bahasa Indonesia, Bahasa Inggris", + ) + + cls.custom_user_1 = CustomUser.objects.create_user( + name='tes', + email='email@email.com', + password='abc', + nutritionist=cls.nutritionist + ) + + cls.custom_user_2 = CustomUser.objects.create_user( + name='tes2', + email='email2@email.com', + password='abc', + nutritionist=cls.nutritionist + ) + + cls.diet_recommendation = DietRecommendation.objects.create( + client=cls.custom_user_2, + nutritionist=cls.custom_user_2.nutritionist + ) + + cls.SPECIFIC_URL = f"{cls.BASE_URL}{cls.diet_recommendation.id}/" + + def test_string_representation(self): + self.assertEqual(str(self.diet_recommendation), 'email2@email.com - Test, S.Gz') + + def test_create_diet_recommendation_succeed(self): + tmp_file = SimpleUploadedFile("testfile.pdf", bytes("abc", 'utf-8'), content_type="application/pdf") + data = { + 'client': self.custom_user_1.id, + 'nutritionist': self.custom_user_1.nutritionist.id, + 'client_plan_meal': tmp_file, + 'nutritional_advice': 'baik baik ya', + 'lifestyle_advice': 'baik baik ya', + } + + response = self.client.post(self.BASE_URL, data, format='multipart') + json_response = json.loads(response.content) + self.assertIn('.pdf', json_response.get('client_plan_meal')) + self.assertEqual(json_response.get('client'), self.custom_user_1.id) + self.assertEqual(json_response.get('nutritionist'), self.custom_user_1.nutritionist.id) + self.assertEqual(json_response.get('nutritional_advice'), 'baik baik ya') + self.assertEqual(json_response.get('lifestyle_advice'), 'baik baik ya') + self.assertEqual(DietRecommendation.objects.count(), 2) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + + def test_create_diet_recommendation_failed(self): + data = { + 'client': self.custom_user_1.id, + 'nutritionist': self.custom_user_1.nutritionist.id, + 'client_plan_meal': 'tesfile.pdf', + 'nutritional_advice': 'baik baik ya', + 'lifestyle_advice': 'baik baik ya', + } + + response = self.client.post(self.BASE_URL, data, format='multipart') + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + + def test_get_all_diet_recommendation(self): + response = self.client.get(self.BASE_URL) + json_response = json.loads(response.content) + self.assertEqual(len(json_response), 1) + self.assertEqual(json_response[0].get('client'), self.custom_user_2.id) + self.assertEqual(json_response[0].get('nutritionist'), self.custom_user_2.nutritionist.id) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + def test_get_single_diet_recommendation_succeed(self): + response = self.client.get(self.SPECIFIC_URL) + json_response = json.loads(response.content) + self.assertEqual(json_response.get('client'), self.custom_user_2.id) + self.assertEqual(json_response.get('nutritionist'), self.custom_user_2.nutritionist.id) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + def test_get_single_diet_recommendation_failed(self): + response = self.client.get(f"{self.BASE_URL}-1/") + self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + + def test_update_diet_recommendation_succeed(self): + tmp_file = SimpleUploadedFile("testfile2.pdf", bytes("abc", 'utf-8'), content_type="application/pdf") + data = { + 'client_plan_meal': tmp_file, + 'nutritional_advice': 'makan yang banyak ya', + 'lifestyle_advice': 'yuk hidup sehat' + } + + response = self.client.patch(self.SPECIFIC_URL, data, format='multipart') + json_response = json.loads(response.content) + self.assertEqual(json_response.get('client'), self.custom_user_2.id) + self.assertEqual(json_response.get('nutritionist'), self.custom_user_2.nutritionist.id) + self.assertIn('.pdf', json_response.get('client_plan_meal')) + self.assertEqual(json_response.get('nutritional_advice'), 'makan yang banyak ya') + self.assertEqual(json_response.get('lifestyle_advice'), 'yuk hidup sehat') + self.assertEqual(response.status_code, status.HTTP_200_OK) + + def test_update_diet_recommendation_failed(self): + data = { + 'client_plan_meal': 'testfile2.pdf', + 'nutritional_advice': 'makan yang banyak ya', + 'lifestyle_advice': 'yuk hidup sehat' + } + + response = self.client.post(self.BASE_URL, data, format='multipart') + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) -- GitLab From 907af7210e44127038b834a998ced2d1f17f3567 Mon Sep 17 00:00:00 2001 From: Glenda Emanuella Sutanto Date: Mon, 10 May 2021 03:59:09 +0700 Subject: [PATCH 02/10] [GREEN] Implemented diet recommendation in profile --- dietela_backend/settings.py | 1 + dietela_backend/urls.py | 5 +++- profile_dietku/migrations/0001_initial.py | 29 +++++++++++++++++++++++ profile_dietku/models.py | 20 ++++++++++++++++ profile_dietku/serializers.py | 10 ++++++++ profile_dietku/tests.py | 1 - profile_dietku/urls.py | 3 ++- profile_dietku/views.py | 9 ++++++- 8 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 profile_dietku/migrations/0001_initial.py create mode 100644 profile_dietku/models.py create mode 100644 profile_dietku/serializers.py diff --git a/dietela_backend/settings.py b/dietela_backend/settings.py index 84b9927..c7f31ae 100644 --- a/dietela_backend/settings.py +++ b/dietela_backend/settings.py @@ -212,3 +212,4 @@ REST_AUTH_REGISTER_SERIALIZERS = { } MEDIA_ROOT = os.path.join(BASE_DIR, 'media') +MEDIA_URL = '/media/' diff --git a/dietela_backend/urls.py b/dietela_backend/urls.py index 3d603f6..22aebf7 100644 --- a/dietela_backend/urls.py +++ b/dietela_backend/urls.py @@ -1,5 +1,8 @@ from django.contrib import admin from django.urls import path, include +from django.conf.urls.static import static +from django.conf import settings + urlpatterns = [ path('admin/', admin.site.urls), @@ -10,4 +13,4 @@ urlpatterns = [ path('', include('authentication.urls')), path('', include('diet_questionnaire.urls')), path('', include('profile_dietku.urls')), -] +] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/profile_dietku/migrations/0001_initial.py b/profile_dietku/migrations/0001_initial.py new file mode 100644 index 0000000..25621e3 --- /dev/null +++ b/profile_dietku/migrations/0001_initial.py @@ -0,0 +1,29 @@ +# Generated by Django 3.1 on 2021-05-09 18:22 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('nutritionists', '0002_nutritionist_profile_picture'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='DietRecommendation', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('client_plan_meal', models.FileField(upload_to='')), + ('nutritional_advice', models.TextField(blank=True, null=True)), + ('lifestyle_advice', models.TextField(blank=True, null=True)), + ('client', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('nutritionist', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='nutritionists.nutritionist')), + ], + ), + ] diff --git a/profile_dietku/models.py b/profile_dietku/models.py new file mode 100644 index 0000000..c5e1adb --- /dev/null +++ b/profile_dietku/models.py @@ -0,0 +1,20 @@ +from django.db import models +from nutritionists.models import Nutritionist +from authentication.models import CustomUser + + +class DietRecommendation(models.Model): + nutritionist = models.ForeignKey( + Nutritionist, + on_delete=models.CASCADE + ) + client = models.OneToOneField( + CustomUser, + on_delete=models.CASCADE + ) + client_plan_meal = models.FileField(blank=True, null=True) + nutritional_advice = models.TextField(blank=True, null=True) + lifestyle_advice = models.TextField(blank=True, null=True) + + def __str__(self): + return f"{self.client} - {self.nutritionist}" diff --git a/profile_dietku/serializers.py b/profile_dietku/serializers.py new file mode 100644 index 0000000..b32ab7b --- /dev/null +++ b/profile_dietku/serializers.py @@ -0,0 +1,10 @@ +from rest_framework import serializers +from .models import DietRecommendation + + +class DietRecommendationSerializer(serializers.ModelSerializer): + + class Meta: + model = DietRecommendation + fields = "__all__" + \ No newline at end of file diff --git a/profile_dietku/tests.py b/profile_dietku/tests.py index 47e22b5..bf20ec4 100644 --- a/profile_dietku/tests.py +++ b/profile_dietku/tests.py @@ -1,5 +1,4 @@ import json -import io from django.test import TestCase from django.contrib.auth.models import Group from django.core.files.uploadedfile import SimpleUploadedFile diff --git a/profile_dietku/urls.py b/profile_dietku/urls.py index 4b563c4..d6c2305 100644 --- a/profile_dietku/urls.py +++ b/profile_dietku/urls.py @@ -1,8 +1,9 @@ from rest_framework import routers from django.urls import path -from .views import GetProfilesViewSet +from .views import GetProfilesViewSet, DietRecommendationViewSet router = routers.SimpleRouter() +router.register('diet-recommendation', DietRecommendationViewSet) urlpatterns = [ path('profiles/', GetProfilesViewSet.as_view(), name='get_profiles'), diff --git a/profile_dietku/views.py b/profile_dietku/views.py index 7679d00..0609534 100644 --- a/profile_dietku/views.py +++ b/profile_dietku/views.py @@ -1,7 +1,9 @@ -from rest_framework import generics +from rest_framework import generics, viewsets from django.db.models import Q from authentication.models import CustomUser from authentication.serializers import CustomUserDetailsSerializer +from .serializers import DietRecommendationSerializer +from .models import DietRecommendation class GetProfilesViewSet(generics.ListAPIView): @@ -22,3 +24,8 @@ class GetProfilesViewSet(generics.ListAPIView): queryset = queryset.filter( Q(nutritionist=nutritionist_id) & ~Q(id=self.request.user.id)) return queryset + + +class DietRecommendationViewSet(viewsets.ModelViewSet): + serializer_class = DietRecommendationSerializer + queryset = DietRecommendation.objects.all() -- GitLab From 18cc4f9e829dcf3a53128a228c1061666549ab3c Mon Sep 17 00:00:00 2001 From: Glenda Emanuella Sutanto Date: Mon, 10 May 2021 14:42:22 +0700 Subject: [PATCH 03/10] [CHORES] Registered diet recommendation models in admin --- profile_dietku/admin.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/profile_dietku/admin.py b/profile_dietku/admin.py index 5538909..80985e3 100644 --- a/profile_dietku/admin.py +++ b/profile_dietku/admin.py @@ -1,3 +1,4 @@ -#from django.contrib import admin +from django.contrib import admin +from .models import DietRecommendation -# Register your models here. +admin.site.register(DietRecommendation) -- GitLab From 1e8479e98a7bc966454a8813b077a1a2b96affee Mon Sep 17 00:00:00 2001 From: Glenda Emanuella Sutanto Date: Mon, 10 May 2021 17:41:13 +0700 Subject: [PATCH 04/10] [RED] Created test for creating diet recommendation object after payment redirection --- payment/tests.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/payment/tests.py b/payment/tests.py index bc81088..0f754a3 100644 --- a/payment/tests.py +++ b/payment/tests.py @@ -14,6 +14,7 @@ from dietela_program.models import DietelaProgram from nutritionists.models import Nutritionist from authentication.models import CustomUser from diet_questionnaire.models import DietQuestionnaire +from profile_dietku.models import DietRecommendation class CartTests(APITestCase): @@ -24,8 +25,6 @@ class CartTests(APITestCase): cls.SET_TRANSACTION_STATUS_URL = "/payment/set-transaction-status/" cls.MIDTRANS_REDIRECTION_URL = "/payment/midtrans-redirection/" - cls.custom_user = CustomUser.objects.create_user(name='tes', email='email@email.com', password='abc') - cls.dietela_program_1 = DietelaProgram.objects.create( unique_code="PRG1", name="Program 1", @@ -55,6 +54,13 @@ class CartTests(APITestCase): languages="Bahasa Indonesia, Bahasa Inggris", ) + cls.custom_user = CustomUser.objects.create_user( + name='tes', + email='email@email.com', + password='abc', + nutritionist=cls.nutritionist_1, + ) + cls.cart_1 = Cart.objects.create( program = cls.dietela_program_1, nutritionist = cls.nutritionist_1, @@ -165,6 +171,10 @@ class CartTests(APITestCase): self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(DietQuestionnaire.objects.count(), 1) self.assertEqual(DietQuestionnaire.objects.last().user, self.cart_3.user) + self.assertEqual(DietRecommendation.objects.count(), 1) + self.assertEqual(DietRecommendation.objects.last().client, self.cart_3.user) + self.assertEqual(DietRecommendation.objects.last().nutritionist, self.cart_3.user.nutritionist) + def test_midtrans_redirection_failed_because_cart_does_not_exist(self): url = self.MIDTRANS_REDIRECTION_URL -- GitLab From 7f8235ff02438c3ec6de950354e1c99ace5deb94 Mon Sep 17 00:00:00 2001 From: Glenda Emanuella Sutanto Date: Mon, 10 May 2021 17:57:23 +0700 Subject: [PATCH 05/10] [GREEN] Updated views to create diet recommendation object after payment redirection --- payment/views.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/payment/views.py b/payment/views.py index 0510258..473e4dd 100644 --- a/payment/views.py +++ b/payment/views.py @@ -8,6 +8,7 @@ from constants.string_constants import CART_NOT_FOUND_MESSAGE from dietela_program.serializers import DietelaProgramSerializer from dietela_program.models import DietelaProgram from diet_questionnaire.models import DietQuestionnaire +from profile_dietku.models import DietRecommendation from .serializers import CartSerializer from .models import Cart @@ -121,5 +122,9 @@ class MidtransRedirectionViewSet(viewsets.ViewSet): cart.save() DietQuestionnaire.objects.create(user=cart.user) + DietRecommendation.objects.create( + client=cart.user, + nutritionist=cart.user.nutritionist + ) return Response(status=status.HTTP_200_OK) -- GitLab From d538820d7b51015ecc5e3b958bffcec88cd00021 Mon Sep 17 00:00:00 2001 From: Glenda Emanuella Sutanto Date: Mon, 10 May 2021 18:05:28 +0700 Subject: [PATCH 06/10] [RED] Created tests to serve diet recommendation flow change --- profile_dietku/tests.py | 102 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 92 insertions(+), 10 deletions(-) diff --git a/profile_dietku/tests.py b/profile_dietku/tests.py index bf20ec4..715a33a 100644 --- a/profile_dietku/tests.py +++ b/profile_dietku/tests.py @@ -7,6 +7,7 @@ from rest_framework import status from dietela_quiz.models import DietProfile from authentication.models import CustomUser from nutritionists.models import Nutritionist +from diet_questionnaire.models import DietQuestionnaire from authentication.serializers import CustomUserDetailsSerializer from django.db.models import Q from .models import DietRecommendation @@ -19,7 +20,7 @@ class GetProfilesTest(APITestCase): cls.BASE_URL = "/profiles/" cls.SPECIFIC_URL = "/profiles/?nutritionist=1" - cls.diet_profile = DietProfile.objects.create( + cls.diet_profile_1 = DietProfile.objects.create( name="test", email="test@test.com", age=20, @@ -41,6 +42,28 @@ class GetProfilesTest(APITestCase): problem_to_solve=1, health_problem=[2, 3]) + cls.diet_profile_2 = DietProfile.objects.create( + name="test2", + email="test2@test.com", + age=20, + weight=61, + height=172, + gender=2, + special_condition=1, + body_activity=1, + vegetables_in_one_day=1, + fruits_in_one_day=1, + fried_food_in_one_day=1, + sweet_snacks_in_one_day=1, + sweet_drinks_in_one_day=1, + packaged_food_in_one_day=1, + large_meal_in_one_day=1, + snacks_in_one_day=1, + breakfast_type=1, + current_condition=1, + problem_to_solve=1, + health_problem=[2, 3]) + cls.nutritionist = Nutritionist.objects.create( id=1, full_name_and_degree="Test, S.Gz", @@ -56,16 +79,45 @@ class GetProfilesTest(APITestCase): name='tes', email='test@test.com', password='abc', - diet_profile=cls.diet_profile, - nutritionist=cls.nutritionist) + diet_profile=cls.diet_profile_1, + nutritionist=cls.nutritionist + ) - cls.custom_user_2 = CustomUser.objects.create_user(name='tes', email='email2@gmail.com', password='abc') + cls.custom_user_2 = CustomUser.objects.create_user( + name='tes', + email='email2@gmail.com', + password='abc', + diet_profile=cls.diet_profile_2, + nutritionist=cls.nutritionist + ) cls.custom_user_3 = CustomUser.objects.create_user( name='tesb', email='test2@2test.com', password='abc', nutritionist=cls.nutritionist) + + cls.diet_questionnaire_1 = DietQuestionnaire.objects.create( + user=cls.custom_user_1, + agree_to_all_statements_consent=1, + personal_data_consent=1 + ) + + cls.diet_recommendation_1 = DietRecommendation.objects.create( + client=cls.custom_user_1, + nutritionist=cls.custom_user_1.nutritionist + ) + + cls.diet_questionnaire_2 = DietQuestionnaire.objects.create( + user=cls.custom_user_2, + agree_to_all_statements_consent=1, + personal_data_consent=1 + ) + + cls.diet_recommendation_2 = DietRecommendation.objects.create( + client=cls.custom_user_2, + nutritionist=cls.custom_user_2.nutritionist + ) cls.g0 = Group.objects.get(name='client') cls.g0.user_set.remove(cls.custom_user_3) @@ -76,9 +128,19 @@ class GetProfilesTest(APITestCase): def test_get_all_users(self): response = self.client.get(self.BASE_URL) + expected_response = [] users = CustomUser.objects.all() - serializer = CustomUserDetailsSerializer(users, many=True) - self.assertEqual(response.data, serializer.data) + for user in users: + expected_response.append({ + 'user': CustomUserDetailsSerializer(user).data, + 'diet_profile_id': user.diet_profile.id \ + if user.diet_profile is not None else '-', + 'diet_questionnaire_id': user.diet_questionnaire.id \ + if hasattr(user, 'diet_questionnaire') else '-', + 'diet_recommendation_id': user.diet_recommendation.id \ + if hasattr(user, 'diet_recommendation') else '-' + }) + self.assertEqual(response.data, expected_response) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_get_user_belonging_to_a_nutritionist(self): @@ -96,8 +158,18 @@ class GetProfilesTest(APITestCase): self.client.credentials(HTTP_AUTHORIZATION='Bearer ' + json_response['access_token']) response = self.client.get(self.BASE_URL,secure=True) users = CustomUser.objects.filter(Q(nutritionist=1) & ~Q(email='test2@2test.com')) - serializer = CustomUserDetailsSerializer(users, many=True) - self.assertEqual(response.data, serializer.data) + expected_response = [] + for user in users: + expected_response.append({ + 'user': CustomUserDetailsSerializer(user).data, + 'diet_profile_id': user.diet_profile.id \ + if user.diet_profile is not None else '-', + 'diet_questionnaire_id': user.diet_questionnaire.id \ + if hasattr(user, 'diet_questionnaire') else '-', + 'diet_recommendation_id': user.diet_recommendation.id \ + if hasattr(user, 'diet_recommendation') else '-' + }) + self.assertEqual(response.data, expected_response) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_get_user_by_non_nutritionist(self): @@ -115,8 +187,18 @@ class GetProfilesTest(APITestCase): self.client.credentials(HTTP_AUTHORIZATION='Bearer ' + json_response['access_token']) response = self.client.get(self.BASE_URL,secure=True) users = CustomUser.objects.all() - serializer = CustomUserDetailsSerializer(users, many=True) - self.assertEqual(response.data, serializer.data) + expected_response = [] + for user in users: + expected_response.append({ + 'user': CustomUserDetailsSerializer(user).data, + 'diet_profile_id': user.diet_profile.id \ + if user.diet_profile is not None else '-', + 'diet_questionnaire_id': user.diet_questionnaire.id \ + if hasattr(user, 'diet_questionnaire') else '-', + 'diet_recommendation_id': user.diet_recommendation.id \ + if hasattr(user, 'diet_recommendation') else '-' + }) + self.assertEqual(response.data, expected_response) self.assertEqual(response.status_code, status.HTTP_200_OK) -- GitLab From 26e9b0315ecc06506a15975a5ef906858a3bc7e9 Mon Sep 17 00:00:00 2001 From: Glenda Emanuella Sutanto Date: Mon, 10 May 2021 19:03:44 +0700 Subject: [PATCH 07/10] [GREEN] Implemented diet recommendation flow change --- diet_questionnaire/views.py | 2 +- .../migrations/0002_auto_20210510_1446.py | 32 +++++++++++++++++++ .../migrations/0003_auto_20210510_1447.py | 18 +++++++++++ profile_dietku/models.py | 8 +++-- profile_dietku/serializers.py | 1 - profile_dietku/views.py | 19 ++++++++++- 6 files changed, 74 insertions(+), 6 deletions(-) create mode 100644 profile_dietku/migrations/0002_auto_20210510_1446.py create mode 100644 profile_dietku/migrations/0003_auto_20210510_1447.py diff --git a/diet_questionnaire/views.py b/diet_questionnaire/views.py index b75012d..44f7dd9 100644 --- a/diet_questionnaire/views.py +++ b/diet_questionnaire/views.py @@ -21,7 +21,7 @@ class DietQuestionnaireViewSet(viewsets.ModelViewSet): return Response(serializer.data, status=status.HTTP_200_OK) def retrieve(self, request, pk=None): - instance = get_object_or_404(self.get_queryset(), pk=pk) + instance = get_object_or_404(DietQuestionnaire.objects.all(), pk=pk) serializer = DietQuestionnaireSerializer(instance) return Response(serializer.data, status=status.HTTP_200_OK) diff --git a/profile_dietku/migrations/0002_auto_20210510_1446.py b/profile_dietku/migrations/0002_auto_20210510_1446.py new file mode 100644 index 0000000..41254ba --- /dev/null +++ b/profile_dietku/migrations/0002_auto_20210510_1446.py @@ -0,0 +1,32 @@ +# Generated by Django 3.1 on 2021-05-10 07:46 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('nutritionists', '0002_nutritionist_profile_picture'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('profile_dietku', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='dietrecommendation', + name='client', + field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='diet_recommendation', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='dietrecommendation', + name='client_plan_meal', + field=models.FileField(blank=True, null=True, upload_to=''), + ), + migrations.AlterField( + model_name='dietrecommendation', + name='nutritionist', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='diet_recommendation', to='nutritionists.nutritionist'), + ), + ] diff --git a/profile_dietku/migrations/0003_auto_20210510_1447.py b/profile_dietku/migrations/0003_auto_20210510_1447.py new file mode 100644 index 0000000..dfa48d9 --- /dev/null +++ b/profile_dietku/migrations/0003_auto_20210510_1447.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1 on 2021-05-10 07:47 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('profile_dietku', '0002_auto_20210510_1446'), + ] + + operations = [ + migrations.AlterField( + model_name='dietrecommendation', + name='client_plan_meal', + field=models.FileField(blank=True, null=True, upload_to='diet-recommendation'), + ), + ] diff --git a/profile_dietku/models.py b/profile_dietku/models.py index c5e1adb..17575c7 100644 --- a/profile_dietku/models.py +++ b/profile_dietku/models.py @@ -6,13 +6,15 @@ from authentication.models import CustomUser class DietRecommendation(models.Model): nutritionist = models.ForeignKey( Nutritionist, - on_delete=models.CASCADE + on_delete=models.CASCADE, + related_name='diet_recommendation' ) client = models.OneToOneField( CustomUser, - on_delete=models.CASCADE + on_delete=models.CASCADE, + related_name='diet_recommendation' ) - client_plan_meal = models.FileField(blank=True, null=True) + client_plan_meal = models.FileField(blank=True, null=True, upload_to='diet-recommendation') nutritional_advice = models.TextField(blank=True, null=True) lifestyle_advice = models.TextField(blank=True, null=True) diff --git a/profile_dietku/serializers.py b/profile_dietku/serializers.py index b32ab7b..94a7a56 100644 --- a/profile_dietku/serializers.py +++ b/profile_dietku/serializers.py @@ -7,4 +7,3 @@ class DietRecommendationSerializer(serializers.ModelSerializer): class Meta: model = DietRecommendation fields = "__all__" - \ No newline at end of file diff --git a/profile_dietku/views.py b/profile_dietku/views.py index 0609534..26dad02 100644 --- a/profile_dietku/views.py +++ b/profile_dietku/views.py @@ -1,4 +1,5 @@ -from rest_framework import generics, viewsets +from rest_framework import generics, viewsets, status +from rest_framework.response import Response from django.db.models import Q from authentication.models import CustomUser from authentication.serializers import CustomUserDetailsSerializer @@ -25,6 +26,22 @@ class GetProfilesViewSet(generics.ListAPIView): Q(nutritionist=nutritionist_id) & ~Q(id=self.request.user.id)) return queryset + def list(self, request): + queryset = self.get_queryset() + + response = [] + for user in queryset: + response.append({ + 'user': CustomUserDetailsSerializer(user).data, + 'diet_profile_id': user.diet_profile.id \ + if user.diet_profile is not None else '-', + 'diet_questionnaire_id': user.diet_questionnaire.id \ + if hasattr(user, 'diet_questionnaire') else '-', + 'diet_recommendation_id': user.diet_recommendation.id \ + if hasattr(user, 'diet_recommendation') else '-' + }) + + return Response(response, status=status.HTTP_200_OK) class DietRecommendationViewSet(viewsets.ModelViewSet): serializer_class = DietRecommendationSerializer -- GitLab From b3ff94432eeb79bbee5543894f092204f99f1c0b Mon Sep 17 00:00:00 2001 From: Glenda Emanuella Sutanto Date: Mon, 10 May 2021 19:46:12 +0700 Subject: [PATCH 08/10] [REFACTOR] Made non-existent value in response as a null + removed unused variable --- profile_dietku/tests.py | 19 +++++++++---------- profile_dietku/views.py | 6 +++--- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/profile_dietku/tests.py b/profile_dietku/tests.py index 715a33a..782f7b7 100644 --- a/profile_dietku/tests.py +++ b/profile_dietku/tests.py @@ -18,7 +18,6 @@ class GetProfilesTest(APITestCase): @classmethod def setUpTestData(cls): cls.BASE_URL = "/profiles/" - cls.SPECIFIC_URL = "/profiles/?nutritionist=1" cls.diet_profile_1 = DietProfile.objects.create( name="test", @@ -134,11 +133,11 @@ class GetProfilesTest(APITestCase): expected_response.append({ 'user': CustomUserDetailsSerializer(user).data, 'diet_profile_id': user.diet_profile.id \ - if user.diet_profile is not None else '-', + if user.diet_profile is not None else None, 'diet_questionnaire_id': user.diet_questionnaire.id \ - if hasattr(user, 'diet_questionnaire') else '-', + if hasattr(user, 'diet_questionnaire') else None, 'diet_recommendation_id': user.diet_recommendation.id \ - if hasattr(user, 'diet_recommendation') else '-' + if hasattr(user, 'diet_recommendation') else None }) self.assertEqual(response.data, expected_response) self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -163,11 +162,11 @@ class GetProfilesTest(APITestCase): expected_response.append({ 'user': CustomUserDetailsSerializer(user).data, 'diet_profile_id': user.diet_profile.id \ - if user.diet_profile is not None else '-', + if user.diet_profile is not None else None, 'diet_questionnaire_id': user.diet_questionnaire.id \ - if hasattr(user, 'diet_questionnaire') else '-', + if hasattr(user, 'diet_questionnaire') else None, 'diet_recommendation_id': user.diet_recommendation.id \ - if hasattr(user, 'diet_recommendation') else '-' + if hasattr(user, 'diet_recommendation') else None }) self.assertEqual(response.data, expected_response) self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -192,11 +191,11 @@ class GetProfilesTest(APITestCase): expected_response.append({ 'user': CustomUserDetailsSerializer(user).data, 'diet_profile_id': user.diet_profile.id \ - if user.diet_profile is not None else '-', + if user.diet_profile is not None else None, 'diet_questionnaire_id': user.diet_questionnaire.id \ - if hasattr(user, 'diet_questionnaire') else '-', + if hasattr(user, 'diet_questionnaire') else None, 'diet_recommendation_id': user.diet_recommendation.id \ - if hasattr(user, 'diet_recommendation') else '-' + if hasattr(user, 'diet_recommendation') else None }) self.assertEqual(response.data, expected_response) self.assertEqual(response.status_code, status.HTTP_200_OK) diff --git a/profile_dietku/views.py b/profile_dietku/views.py index 26dad02..4a214e7 100644 --- a/profile_dietku/views.py +++ b/profile_dietku/views.py @@ -34,11 +34,11 @@ class GetProfilesViewSet(generics.ListAPIView): response.append({ 'user': CustomUserDetailsSerializer(user).data, 'diet_profile_id': user.diet_profile.id \ - if user.diet_profile is not None else '-', + if user.diet_profile is not None else None, 'diet_questionnaire_id': user.diet_questionnaire.id \ - if hasattr(user, 'diet_questionnaire') else '-', + if hasattr(user, 'diet_questionnaire') else None, 'diet_recommendation_id': user.diet_recommendation.id \ - if hasattr(user, 'diet_recommendation') else '-' + if hasattr(user, 'diet_recommendation') else None }) return Response(response, status=status.HTTP_200_OK) -- GitLab From d90ebf7d2a017581ca2e2f96bb0014638db5d16e Mon Sep 17 00:00:00 2001 From: Glenda Emanuella Sutanto Date: Tue, 11 May 2021 16:35:36 +0700 Subject: [PATCH 09/10] [REFACTOR] Filtered get all diet recommendations request by token --- profile_dietku/tests.py | 13 +++++++++++++ profile_dietku/views.py | 6 ++++++ 2 files changed, 19 insertions(+) diff --git a/profile_dietku/tests.py b/profile_dietku/tests.py index 782f7b7..329376d 100644 --- a/profile_dietku/tests.py +++ b/profile_dietku/tests.py @@ -203,6 +203,8 @@ class GetProfilesTest(APITestCase): class DietRecommendationTests(APITestCase): + client = APIClient() + @classmethod def setUpTestData(cls): cls.BASE_URL = "/diet-recommendation/" @@ -239,6 +241,16 @@ class DietRecommendationTests(APITestCase): cls.SPECIFIC_URL = f"{cls.BASE_URL}{cls.diet_recommendation.id}/" + cls.login_data = { + 'email': 'email2@email.com', + 'password': 'abc', + 'role': 'client', + } + + cls.login_response = cls.client.post('/auth/user-login/', cls.login_data, format='json') + cls.json_login_response = json.loads(cls.login_response.content) + cls.login_credentials = "Bearer " + cls.json_login_response['access_token'] + def test_string_representation(self): self.assertEqual(str(self.diet_recommendation), 'email2@email.com - Test, S.Gz') @@ -275,6 +287,7 @@ class DietRecommendationTests(APITestCase): self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_get_all_diet_recommendation(self): + self.client.credentials(HTTP_AUTHORIZATION=self.login_credentials) response = self.client.get(self.BASE_URL) json_response = json.loads(response.content) self.assertEqual(len(json_response), 1) diff --git a/profile_dietku/views.py b/profile_dietku/views.py index 4a214e7..40c3871 100644 --- a/profile_dietku/views.py +++ b/profile_dietku/views.py @@ -46,3 +46,9 @@ class GetProfilesViewSet(generics.ListAPIView): class DietRecommendationViewSet(viewsets.ModelViewSet): serializer_class = DietRecommendationSerializer queryset = DietRecommendation.objects.all() + + def list(self, request): + instances = self.get_queryset().filter(client=request.user) + + serializer = DietRecommendationSerializer(instances, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) -- GitLab From 929699451d64c3e9f6ccaae3f95ded54d18e3857 Mon Sep 17 00:00:00 2001 From: Glenda Emanuella Sutanto Date: Tue, 11 May 2021 22:56:54 +0700 Subject: [PATCH 10/10] [CHORES] Improved admin site so that admin can create password through it --- authentication/admin.py | 52 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/authentication/admin.py b/authentication/admin.py index d547620..c8a8790 100644 --- a/authentication/admin.py +++ b/authentication/admin.py @@ -1,5 +1,53 @@ from django.contrib import admin - +from django.contrib.auth.admin import UserAdmin as BaseUserAdmin from .models import CustomUser -admin.site.register(CustomUser) + +class UserAdmin(BaseUserAdmin): + # The fields to be used in displaying the User model. + # These override the definitions on the base UserAdmin + # that reference specific fields on auth.User. + list_display = ('email',) + fieldsets = ( + (None, {'fields': (\ + 'name', + 'email', + 'password', + 'groups', + 'diet_profile', + 'nutritionist', + 'date_joined', + 'is_staff', + 'is_active', + 'is_superuser', + 'user_permissions', + 'last_login' + )}), + ) + # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin + # overrides get_fieldsets to use this attribute when creating a user. + add_fieldsets = ( + (None, { + 'classes': ('wide',), + 'fields': (\ + 'name', + 'email', + 'password1', + 'password2', + 'groups', + 'diet_profile', + 'nutritionist', + 'date_joined', + 'is_staff', + 'is_active', + 'is_superuser', + 'user_permissions', + 'last_login' + )} + ), + ) + search_fields = ('email',) + ordering = ('email',) + + +admin.site.register(CustomUser, UserAdmin) -- GitLab