Fakultas Ilmu Komputer UI

Commit 2ef0ec65 authored by Ami's avatar Ami
Browse files

resolving merge conflict between PBI-12 and other PBIs

parents f18b2f8b 7e768657
......@@ -2,22 +2,48 @@ from django.contrib.auth.models import Group
from rest_framework import serializers, exceptions
from dj_rest_auth.serializers import LoginSerializer
from dj_rest_auth.registration.serializers import RegisterSerializer
from payment.serializers import CartSerializer
from .models import CustomUser
class CustomUserDetailsSerializer(serializers.ModelSerializer):
class UserAuthSerializer(serializers.ModelSerializer):
def to_representation(self, instance):
result = super().to_representation(instance)
result['is_finished_onboarding'] = True
if instance.groups.exists():
result['role'] = instance.groups.first().name
if result['role'] == 'client':
if hasattr(instance, 'diet_questionnaire'):
result['is_finished_onboarding'] = \
(len(instance.diet_questionnaire.finished_steps) == 6)
else:
result['is_finished_onboarding'] = False
if instance.is_staff:
result['role'] = 'admin'
if instance.cart.exists():
result['cart'] = CartSerializer(instance.cart.last()).data
result['transaction_status'] = instance.cart.last().transaction_status
else:
result['cart'] = {}
result['transaction_status'] = None
return result
class Meta:
model = CustomUser
fields = ('id', 'name', 'email',)
read_only_fields = ('id', 'email',)
class CustomUserDetailsSerializer(serializers.ModelSerializer):
def to_representation(self, instance):
result = super().to_representation(instance)
if instance.groups.exists():
result['role'] = instance.groups.first().name
if instance.is_staff:
result['role'] = 'admin'
return result
class Meta:
......
......@@ -10,7 +10,10 @@ from dietela_program.models import DietelaProgram
from nutritionists.models import Nutritionist
from .models import CustomUser
from .serializers import (
CustomLoginSerializer, CustomRegisterSerializer,CustomUserDetailsSerializer
CustomLoginSerializer,
CustomRegisterSerializer,
CustomUserDetailsSerializer,
UserAuthSerializer,
)
from .google_utils import validate_google_token
......@@ -93,7 +96,11 @@ class UserModelTests(APITestCase):
languages="Bahasa Indonesia, Bahasa Inggris",
)
cls.cart = Cart.objects.create(program=cls.dietela_program, nutritionist=cls.nutritionist)
cls.cart = Cart.objects.create(
program=cls.dietela_program,
nutritionist=cls.nutritionist,
user=cls.custom_user_1
)
def test_create_user(self):
user = CustomUser.objects.create_user(name='tes', email='email2@email.com',
......@@ -353,6 +360,25 @@ class UserModelTests(APITestCase):
serializer = CustomLoginSerializer()
self.assertEqual(serializer.update(None, {}), None)
def test_user_auth_serializer(self):
user_data = UserAuthSerializer(self.custom_user_1).data
self.assertIn('email', user_data)
self.assertIn('name', user_data)
self.assertEqual('client', user_data.get('role'))
self.assertIn('id', user_data)
user_no_role = CustomUser()
user_no_role.name = 'no role'
user_no_role.email = 'norole@norole.com'
user_no_role.password = 'norole2404'
user_no_role.save()
user_no_role_data = UserAuthSerializer(user_no_role).data
self.assertTrue('role' not in user_no_role_data)
admin_user = CustomUser.objects.create_superuser('super2@user.com', 'foo')
admin_user_data = UserAuthSerializer(admin_user).data
self.assertEqual('admin', admin_user_data.get('role'))
@patch('authentication.google_utils.requests.get')
@patch('authentication.google_utils.json.loads')
class TestValidateGoogleToken(TestCase):
......
......@@ -45,10 +45,10 @@ def get_diet_questionnaire_payload_sample_with_step():
],
"multivitamin_tablet_suplement": "-",
"physical_activity": [
"jogging",
"basket",
"apa aja boleh"
1,
7
],
"other_physical_activity": "workout",
"diet_and_life_style_story": "-",
"disease": [
18
......@@ -69,7 +69,7 @@ def get_diet_questionnaire_payload_sample_with_step():
"step": 1
}
def get_diet_questionnaire_response_sample_with_step(id, user_id):
def get_diet_questionnaire_response_sample_with_step(id, user):
return {
"id": id,
......@@ -120,20 +120,15 @@ def get_diet_questionnaire_response_sample_with_step(id, user_id):
"night_snack_explanation": "indomi",
"food_alergies": "-",
"diet_drinks": "-",
"meal_provider": [
1,
2,
3
],
"cigarette_alcohol_condition": [
4
],
"multivitamin_tablet_suplement": "-",
"physical_activity": [
"jogging",
"basket",
"apa aja boleh"
1,
7
],
"other_physical_activity": "workout",
"diet_and_life_style_story": "-",
"disease": [
18
......@@ -146,7 +141,7 @@ def get_diet_questionnaire_response_sample_with_step(id, user_id):
"finished_steps": [
1
],
"user": user_id
"user": user
}
def get_diet_questionnaire_payload_sample_without_step():
......@@ -196,10 +191,10 @@ def get_diet_questionnaire_payload_sample_without_step():
],
"multivitamin_tablet_suplement": "-",
"physical_activity": [
"jogging",
"basket",
"apa aja boleh"
1,
7
],
"other_physical_activity": "workout",
"diet_and_life_style_story": "-",
"disease": [
18
......@@ -219,7 +214,7 @@ def get_diet_questionnaire_payload_sample_without_step():
"dietela_program_expectation": "-",
}
def get_diet_questionnaire_response_sample_without_step(id, user_id):
def get_diet_questionnaire_response_sample_without_step(id, user):
return {
"id": id,
......@@ -270,20 +265,15 @@ def get_diet_questionnaire_response_sample_without_step(id, user_id):
"night_snack_explanation": "indomi",
"food_alergies": "-",
"diet_drinks": "-",
"meal_provider": [
1,
2,
3
],
"cigarette_alcohol_condition": [
4
],
"multivitamin_tablet_suplement": "-",
"physical_activity": [
"jogging",
"basket",
"apa aja boleh"
1,
7
],
"other_physical_activity": "workout",
"diet_and_life_style_story": "-",
"disease": [
18
......@@ -294,5 +284,5 @@ def get_diet_questionnaire_response_sample_without_step(id, user_id):
"dietela_nutritionist_expectation": "-",
"dietela_program_expectation": "-",
"finished_steps": [],
"user": user_id
"user": user
}
......@@ -180,6 +180,17 @@ class CigaretteAlcoholCondition(models.IntegerChoices):
CONDITION_3 = 3, 'Terkadang mengkonsumsi salah satu jenis minuman beralkohol (contoh: bir, vodka, wine)'
CONDITION_4 = 4, 'Tidak termasuk salah satu diatas'
class PhysicalActivity(models.IntegerChoices):
ACTIVITY_1 = 1, 'Hampir tidak pernah olahraga'
ACTIVITY_2 = 2, 'Jogging'
ACTIVITY_3 = 3, 'Senam aerobic, zumba, yoga, dan sejenisnya'
ACTIVITY_4 = 4, 'Sepak bola/Futsal'
ACTIVITY_5 = 5, 'Renang'
ACTIVITY_6 = 6, 'Basket'
ACTIVITY_7 = 7, 'Bulutangkis'
ACTIVITY_8 = 8, 'Voli'
ACTIVITY_9 = 9, 'Lainnya'
class Disease(models.IntegerChoices):
DISEASE_1 = 1, 'Tidak ada'
DISEASE_2 = 2, 'Diabetes Melitus Tipe II (Kencing Manis)'
......
......@@ -3,7 +3,7 @@ from django.utils.translation import gettext_lazy as _
class TransactionStatus(models.TextChoices):
SUCCESS = "success", _("Sucess")
SUCCESS = "success", _("Success")
PENDING = "pending", _("Pending")
UNPAID = "unpaid", _("Unpaid")
ERROR = "error", _("Error")
# Generated by Django 3.1 on 2021-05-10 18:04
from django.db import migrations, models
import multiselectfield.db.fields
class Migration(migrations.Migration):
dependencies = [
('diet_questionnaire', '0006_auto_20210509_2113'),
]
operations = [
migrations.AddField(
model_name='dietquestionnaire',
name='other_physical_activity',
field=models.CharField(blank=True, max_length=200, null=True),
),
migrations.AlterField(
model_name='dietquestionnaire',
name='physical_activity',
field=multiselectfield.db.fields.MultiSelectField(blank=True, choices=[(1, 'Hampir tidak pernah olahraga'), (2, 'Jogging'), (3, 'Senam aerobic, zumba, yoga, dan sejenisnya'), (4, 'Sepak bola/Futsal'), (5, 'Renang'), (6, 'Basket'), (7, 'Bulutangkis'), (8, 'Voli')], max_length=15, null=True),
),
]
......@@ -16,6 +16,7 @@ from constants.model_choices import (
LiquidConsumptionFrequency,
MealProvider,
CigaretteAlcoholCondition,
PhysicalActivity,
Disease,
Complaint,
)
......@@ -103,7 +104,10 @@ class DietQuestionnaire(models.Model):
choices = CigaretteAlcoholCondition.choices, null=True, blank=True
)
multivitamin_tablet_suplement = models.CharField(max_length=200, null=True, blank=True)
physical_activity = ArrayField(models.CharField(max_length=200), null=True, blank=True)
physical_activity = MultiSelectField(
choices = PhysicalActivity.choices, null=True, blank=True
)
other_physical_activity = models.CharField(max_length=200, null=True, blank=True)
diet_and_life_style_story = models.TextField(null=True, blank=True)
disease = MultiSelectField(
choices = Disease.choices, null=True, blank=True
......@@ -117,3 +121,6 @@ class DietQuestionnaire(models.Model):
dietela_nutritionist_expectation = models.TextField(null=True, blank=True)
dietela_program_expectation = models.TextField(null=True, blank=True)
finished_steps = ArrayField(models.PositiveIntegerField(), null=True, blank=True, default=list)
def __str__(self):
return str(self.user)
......@@ -3,12 +3,15 @@ from constants.model_choices import (
MealProvider,
Complaint,
CigaretteAlcoholCondition,
PhysicalActivity,
Disease
)
from authentication.serializers import CustomUserDetailsSerializer
from .models import DietQuestionnaire
class DietQuestionnaireSerializer(serializers.ModelSerializer):
meal_provider = fields.MultipleChoiceField(
choices = MealProvider.choices, required=False
)
......@@ -21,10 +24,16 @@ class DietQuestionnaireSerializer(serializers.ModelSerializer):
choices = CigaretteAlcoholCondition.choices, required=False
)
physical_activity = fields.MultipleChoiceField(
choices = PhysicalActivity.choices, required=False
)
disease = fields.MultipleChoiceField(
choices = Disease.choices, required=False
)
user = CustomUserDetailsSerializer(read_only=True)
class Meta:
model = DietQuestionnaire
fields = "__all__"
......
......@@ -5,6 +5,7 @@ from rest_framework.test import APITestCase, APIClient
from rest_framework import status
from .models import DietQuestionnaire
from authentication.models import CustomUser
from authentication.serializers import CustomUserDetailsSerializer
from constants.diet_questionnaire_sample import (
get_diet_questionnaire_payload_sample_with_step,
get_diet_questionnaire_response_sample_with_step,
......@@ -42,7 +43,7 @@ class DietQuestionnaireTests(APITestCase):
cls.login_credentials = "Bearer " + cls.json_login_response['access_token']
cls.diet_questionnaire = DietQuestionnaire.objects.create(
user_id = cls.custom_user_1.id
user = cls.custom_user_1
)
cls.SPECIFIC_URL = f"{cls.BASE_URL}{cls.diet_questionnaire.id}/"
......@@ -51,17 +52,20 @@ class DietQuestionnaireTests(APITestCase):
cls.sample_response_with_step = \
get_diet_questionnaire_response_sample_with_step(
cls.diet_questionnaire.id,
cls.custom_user_1.id
CustomUserDetailsSerializer(cls.custom_user_1).data
)
cls.sample_payload_without_step = get_diet_questionnaire_payload_sample_without_step()
cls.sample_response_without_step = \
get_diet_questionnaire_response_sample_without_step(
cls.diet_questionnaire.id,
cls.custom_user_1.id
CustomUserDetailsSerializer(cls.custom_user_1).data
)
def test_string_representation(self):
self.assertEqual(str(self.diet_questionnaire), 'email@email.com')
def test_create_diet_questionnaire(self):
login_data = {
'email': 'email2@email.com',
......@@ -76,20 +80,20 @@ class DietQuestionnaireTests(APITestCase):
response = self.client.post(self.BASE_URL, {}, format='json')
json_response = json.loads(response.content)
self.assertEqual(DietQuestionnaire.objects.count(), 2)
self.assertEqual(json_response.get('user'), self.custom_user_2.id)
self.assertEqual(json_response.get('user'), CustomUserDetailsSerializer(self.custom_user_2).data)
def test_get_all_diet_questionnaire(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)
self.assertEqual(json_response[0].get('user'), self.custom_user_1.id)
self.assertEqual(json_response[0].get('user'), CustomUserDetailsSerializer(self.custom_user_1).data)
def test_get_single_diet_questionnaire_succeed(self):
self.client.credentials(HTTP_AUTHORIZATION=self.login_credentials)
response = self.client.get(f"{self.BASE_URL}{self.diet_questionnaire.id}/")
json_response = json.loads(response.content)
self.assertEqual(json_response.get('user'), self.custom_user_1.id)
self.assertEqual(json_response.get('user'), CustomUserDetailsSerializer(self.custom_user_1).data)
def test_get_single_diet_questionnaire_failed(self):
self.client.credentials(HTTP_AUTHORIZATION=self.login_credentials)
......
......@@ -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)
......
......@@ -204,7 +204,7 @@ AUTHENTICATION_BACKENDS = (
AUTH_USER_MODEL = 'authentication.CustomUser'
REST_AUTH_SERIALIZERS = {
'USER_DETAILS_SERIALIZER':'authentication.serializers.CustomUserDetailsSerializer'
'USER_DETAILS_SERIALIZER':'authentication.serializers.UserAuthSerializer'
}
REST_AUTH_REGISTER_SERIALIZERS = {
......@@ -212,3 +212,4 @@ REST_AUTH_REGISTER_SERIALIZERS = {
}
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
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)
# Generated by Django 3.1 on 2021-05-10 16:24
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('payment', '0004_cart_transaction_status'),
]
operations = [
migrations.AlterField(
model_name='cart',
name='transaction_status',
field=models.CharField(choices=[('success', 'Success'), ('pending', 'Pending'), ('unpaid', 'Unpaid'), ('error', 'Error')], default='unpaid', max_length=128),
),
]
......@@ -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
......
......@@ -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)
#from django.contrib import admin
from django.contrib import admin
from .models import DietRecommendation
# Register your models here.
admin.site.register(DietRecommendation)
# 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')),
],
),
]
# 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'),
),
]
# 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'),
),
]