diff --git a/informasi_fasilitas/admin.py b/informasi_fasilitas/admin.py index 3f66350a7bb784d3026d24f14705cfdd35428893..16f4a849df7954cd199653404a88808252e56da2 100644 --- a/informasi_fasilitas/admin.py +++ b/informasi_fasilitas/admin.py @@ -1,7 +1,10 @@ from django.contrib import admin -from .models import Lokasi, Fasilitas, Komentar +from .models import Lokasi, Fasilitas, Komentar, Kegiatan, KomentarKegiatan, FotoKegiatan # Register your models here. admin.site.register(Lokasi) admin.site.register(Fasilitas) admin.site.register(Komentar) +admin.site.register(Kegiatan) +admin.site.register(KomentarKegiatan) +admin.site.register(FotoKegiatan) diff --git a/informasi_fasilitas/migrations/0013_fotokegiatan_kegiatan_komentarkegiatan.py b/informasi_fasilitas/migrations/0013_fotokegiatan_kegiatan_komentarkegiatan.py new file mode 100644 index 0000000000000000000000000000000000000000..b6e7a899e6eacb4dd936412feb991bd19c3694a4 --- /dev/null +++ b/informasi_fasilitas/migrations/0013_fotokegiatan_kegiatan_komentarkegiatan.py @@ -0,0 +1,48 @@ +# Generated by Django 3.1.7 on 2021-05-06 10:09 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('informasi_fasilitas', '0012_auto_20210329_1332'), + ] + + operations = [ + migrations.CreateModel( + name='Kegiatan', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('nama_kegiatan', models.CharField(max_length=50)), + ('penyelenggara', models.CharField(max_length=50)), + ('deskripsi', models.TextField()), + ('time_start', models.DateTimeField(default=django.utils.timezone.now)), + ('time_end', models.DateTimeField(blank=True, null=True)), + ('lokasi', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='informasi_fasilitas.lokasi')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='KomentarKegiatan', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('deskripsi', models.TextField()), + ('created', models.DateTimeField(auto_now_add=True)), + ('kegiatan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='informasi_fasilitas.kegiatan')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='FotoKegiatan', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('foto', models.ImageField(upload_to='')), + ('kegiatan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='informasi_fasilitas.kegiatan')), + ], + ), + ] diff --git a/informasi_fasilitas/migrations/0014_kegiatan_narahubung.py b/informasi_fasilitas/migrations/0014_kegiatan_narahubung.py new file mode 100644 index 0000000000000000000000000000000000000000..d94fea35da808cb8354e0fa310a4d5e3c3411e37 --- /dev/null +++ b/informasi_fasilitas/migrations/0014_kegiatan_narahubung.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.7 on 2021-05-10 11:47 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('informasi_fasilitas', '0013_fotokegiatan_kegiatan_komentarkegiatan'), + ] + + operations = [ + migrations.AddField( + model_name='kegiatan', + name='narahubung', + field=models.TextField(null=True), + ), + ] diff --git a/informasi_fasilitas/migrations/0015_auto_20210511_0249.py b/informasi_fasilitas/migrations/0015_auto_20210511_0249.py new file mode 100644 index 0000000000000000000000000000000000000000..7aca39c748935ff7fd3b1b903313d19dad319ed1 --- /dev/null +++ b/informasi_fasilitas/migrations/0015_auto_20210511_0249.py @@ -0,0 +1,24 @@ +# Generated by Django 3.1.7 on 2021-05-11 02:49 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('informasi_fasilitas', '0014_kegiatan_narahubung'), + ] + + operations = [ + migrations.AlterField( + model_name='fotokegiatan', + name='foto', + field=models.ImageField(default=None, null=True, upload_to='kegiatan/'), + ), + migrations.AlterField( + model_name='fotokegiatan', + name='kegiatan', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='images', to='informasi_fasilitas.kegiatan'), + ), + ] diff --git a/informasi_fasilitas/migrations/0016_kegiatan_links.py b/informasi_fasilitas/migrations/0016_kegiatan_links.py new file mode 100644 index 0000000000000000000000000000000000000000..c49399f85137f4e1df7ad4327ed0d4b3b3b9ca37 --- /dev/null +++ b/informasi_fasilitas/migrations/0016_kegiatan_links.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.7 on 2021-05-16 16:56 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('informasi_fasilitas', '0015_auto_20210511_0249'), + ] + + operations = [ + migrations.AddField( + model_name='kegiatan', + name='links', + field=models.TextField(blank=True, null=True), + ), + ] diff --git a/informasi_fasilitas/models.py b/informasi_fasilitas/models.py index 1e90a63677c1587c8225d9f9c48a8d5e9a46fa97..7745493a26ce75058beed0fe5342e1af3a0a9f70 100644 --- a/informasi_fasilitas/models.py +++ b/informasi_fasilitas/models.py @@ -73,6 +73,20 @@ class Fasilitas(models.Model): image = models.ImageField(upload_to="fasilitas/", null=True, default=None) is_verified = models.BooleanField(default=False) + +class Kegiatan(models.Model): + objects = models.Manager() + lokasi = models.ForeignKey(Lokasi, on_delete=models.CASCADE) + user = models.ForeignKey(User, on_delete=models.CASCADE) + nama_kegiatan = models.CharField(max_length=50) + penyelenggara = models.CharField(max_length=50) + narahubung = models.TextField(null=True) + deskripsi = models.TextField(null=False) + links = models.TextField(null=True, blank=True) + time_start = models.DateTimeField(blank=False, null=False, default=timezone.now) + time_end = models.DateTimeField(blank=True, null=True) + + class Komentar(models.Model): objects = models.Manager() fasilitas = models.ForeignKey(Fasilitas, on_delete=models.CASCADE) @@ -90,4 +104,16 @@ class Dislikes(models.Model): objects = models.Manager() user = models.ForeignKey(User, on_delete=models.CASCADE) fasilitas = models.ForeignKey(Fasilitas, on_delete=models.CASCADE) - created = models.DateTimeField(auto_now_add=True) \ No newline at end of file + created = models.DateTimeField(auto_now_add=True) + +class KomentarKegiatan(models.Model): + objects = models.Manager() + user = models.ForeignKey(User, on_delete=models.CASCADE) + kegiatan = models.ForeignKey(Kegiatan, on_delete=models.CASCADE) + deskripsi = models.TextField() + created = models.DateTimeField(auto_now_add=True) + +class FotoKegiatan(models.Model): + objects = models.Manager() + kegiatan = models.ForeignKey(Kegiatan, related_name="images", on_delete=models.CASCADE) + foto = models.ImageField(upload_to="kegiatan/", null=True, default=None) diff --git a/informasi_fasilitas/serializers.py b/informasi_fasilitas/serializers.py index e191b99cdb7bc7ddd15b8ec5b8b7fe1b2c1b91b2..8b034aef7b9308862534aa442bb618a76eba4979 100644 --- a/informasi_fasilitas/serializers.py +++ b/informasi_fasilitas/serializers.py @@ -1,6 +1,7 @@ from rest_framework import serializers -from .models import Lokasi +from .models import Lokasi, Kegiatan, KomentarKegiatan, FotoKegiatan + class LokasiSerializer(serializers.ModelSerializer): @@ -15,3 +16,44 @@ class LokasiSerializer(serializers.ModelSerializer): 'read_only': True, }, } + + +class FotoKegiatanSerializer(serializers.ModelSerializer): + place_id = serializers.CharField(source='lokasi.place_id', read_only=True) + class Meta: + model = FotoKegiatan + fields = '__all__' + extra_kwargs = { + 'foto': {'required': True}, + 'kegiatan': {'required': True}, + } + + +class KegiatanSerializer(serializers.ModelSerializer): + place_id = serializers.CharField(source='lokasi.place_id', read_only=True) + creator = serializers.CharField(source='user.last_name', read_only=True) + + class Meta: + model = Kegiatan + fields = ('id', 'place_id', 'creator', 'lokasi', 'user', + 'nama_kegiatan', 'penyelenggara', 'deskripsi', + "links","narahubung", 'time_start', 'time_end') + extra_kwargs = { + 'nama_kegiatan': {'required': True}, + 'penyelenggara': {'required': True}, + 'deskripsi': {'required': True}, + 'narahubung': {"required": True}, + 'time_start': {'required': True}, + } + + +class KomentarKegiatanSerializer(serializers.ModelSerializer): + kegiatan = serializers.IntegerField(source='kegiatan.id', read_only=True) + creator = serializers.CharField(source='user.last_name', read_only=True) + class Meta: + model = KomentarKegiatan + fields = ('id', 'creator', 'kegiatan', 'deskripsi', 'created') + extra_kwargs = { + 'deskripsi': {'required': True}, + 'created': {'required' : True} + } diff --git a/informasi_fasilitas/test_base.py b/informasi_fasilitas/test_base.py index 5db110f2aa0ed49194505648498ddb7395e9bf14..e481d3d379185b75e487e56f5651a6f595f38dbf 100644 --- a/informasi_fasilitas/test_base.py +++ b/informasi_fasilitas/test_base.py @@ -1,6 +1,7 @@ import json import tempfile +from datetime import datetime, timedelta from django.test import TestCase, Client from django.contrib.auth.models import User from django.urls import reverse, path, include @@ -13,7 +14,10 @@ from .models import ( Komentar, KURSI_RODA, Likes, - Dislikes + Dislikes, + Kegiatan, + FotoKegiatan, + KomentarKegiatan ) from pplbackend.utils import get_client_login_with_user @@ -44,6 +48,25 @@ class InformasiFasilitasTest(TestCase): 'deskripsi': 'sangat membantu', } + # Waktu mungkin perlu disesuaikan lagi test dan implementasinya + mock_kegiatan_test = { + 'nama_kegiatan': 'mock kegiatan', + 'penyelenggara': 'mock penyelenggara', + 'time_start':(datetime.now()+timedelta(days=1)).strftime("%Y-%m-%d %H:%M"), + 'time_end': (datetime.now()+timedelta(days=2)).strftime("%Y-%m-%d %H:%M"), + 'narahubung': 'sebuah narahubung', + 'deskripsi': 'sebuah deskripsi', + 'links': "www.example.com;www.example.com" + } + + mock_komentar_kegiatan_test = { + 'deskripsi': 'sangat membantu' + } + + mock_foto_kegiatan_test = { + 'foto' : '/media/lokasi/Screen_Shot_2020-12-29_at_01.48.32.png', + } + def create_user_test(self, user_dict=mock_user_test): return User.objects.create_user(**user_dict) @@ -229,6 +252,53 @@ class InformasiFasilitasTest(TestCase): user=user, fasilitas=fasilitas, ) + + def create_kegiatan_test( + self, + user=None, + user_dict=mock_user_test, + lokasi=None, + lokasi_dict=mock_lokasi_test, + kegiatan_dict=mock_kegiatan_test + ): + user = self.get_or_create_user_test( + user=user, + user_dict=user_dict, + ) + + lokasi = self.get_or_create_lokasi_test( + lokasi=lokasi, + lokasi_dict=lokasi_dict, + ) + return Kegiatan.objects.create(**kegiatan_dict, user=user, lokasi=lokasi) + + def create_foto_kegiatan_test( + self, + foto_kegiatan_dict=mock_foto_kegiatan_test + ): + kegiatan = self.create_kegiatan_test() + return FotoKegiatan.objects.create(**foto_kegiatan_dict, kegiatan=kegiatan) + + def create_komentar_kegiatan_test( + self, + user=None, + komentar_kegiatan_dict=mock_komentar_kegiatan_test, + user_dict=mock_user_test, + kegiatan=None + ): + user = self.get_or_create_user_test( + user=user, + user_dict=user_dict, + ) + + if kegiatan is None: + kegiatan = self.create_kegiatan_test() + + return KomentarKegiatan.objects.create( + **komentar_kegiatan_dict, + kegiatan=kegiatan, + user=user + ) class InformasiFasilitasViewTest(InformasiFasilitasTest): diff --git a/informasi_fasilitas/test_models.py b/informasi_fasilitas/test_models.py index b155d232fa498b698ba0ae461a138034b15a63f8..fae0d4c450595dec53f384d2ea6dc685835074f6 100644 --- a/informasi_fasilitas/test_models.py +++ b/informasi_fasilitas/test_models.py @@ -1,7 +1,7 @@ from django.db.utils import IntegrityError from .test_base import InformasiFasilitasTest -from .models import Lokasi, Fasilitas, Komentar, Likes, Dislikes +from .models import Lokasi, Fasilitas, Komentar, Likes, Dislikes, Kegiatan, FotoKegiatan, KomentarKegiatan class InformasiFasilitasModelTest(InformasiFasilitasTest): @@ -78,3 +78,18 @@ class InformasiFasilitasModelTest(InformasiFasilitasTest): self.create_likes_test() count = Likes.objects.all().count() self.assertNotEqual(count, 0) + + def test_models_create_new_kegiatan(self): + self.create_kegiatan_test() + count = Kegiatan.objects.all().count() + self.assertNotEqual(count, 0) + + def test_models_create_new_foto_kegiatan(self): + self.create_foto_kegiatan_test() + count = FotoKegiatan.objects.all().count() + self.assertNotEqual(count, 0) + + def test_models_create_new_komentar_kegiatan(self): + self.create_komentar_kegiatan_test() + count = KomentarKegiatan.objects.all().count() + self.assertNotEqual(count, 0) diff --git a/informasi_fasilitas/test_views_fasilitas.py b/informasi_fasilitas/test_views_fasilitas.py index 9fa81935ac4fd3e7031477aaaa51b2cb295d7cbf..cbd8f6f389d11adf877c74b741d367e21e0086a9 100644 --- a/informasi_fasilitas/test_views_fasilitas.py +++ b/informasi_fasilitas/test_views_fasilitas.py @@ -5,6 +5,7 @@ from django.urls import reverse from .test_base import InformasiFasilitasViewTest from .models import Fasilitas, Lokasi +from .views import TIME_FORMAT from pplbackend.utils import response_decode @@ -43,11 +44,13 @@ class FasilitasRelatedViewTest(InformasiFasilitasViewTest): expected_json = { str(self.fasilitas.id): { 'id': self.fasilitas.id, + 'creator_email': self.fasilitas.user.email, 'place_id': self.fasilitas.lokasi.place_id, 'deskripsi': self.fasilitas.deskripsi, 'creator': self.fasilitas.user.last_name, 'like': self.fasilitas.like, 'dislike': self.fasilitas.dislike, + 'date_time': self.fasilitas.date_time.strftime(TIME_FORMAT), 'rating': self.fasilitas.rating, 'tag': 'KR', 'disabilitas': ['DF'], @@ -57,8 +60,30 @@ class FasilitasRelatedViewTest(InformasiFasilitasViewTest): }, } - time = self.fasilitas.date_time.strftime("%d-%m-%Y %H:%M:%S") - expected_json[str(self.fasilitas.id)]['date_time'] = time + self.assertEqual(content, expected_json) + + def test_can_get_detail_fasilitas_json(self): + response = Client().get(self.get_detail_fasilitas_url) + content = json.loads(response.content.decode('utf-8')) + fasilitas = Fasilitas.objects.get(id=self.fasilitas.id) + expected_json = { + "id": fasilitas.id, + "place_id": fasilitas.lokasi.place_id, + "deskripsi": fasilitas.deskripsi, + "creator": self.user.last_name, + "creator_email": self.user.email, + "date_time": fasilitas.date_time.strftime(TIME_FORMAT), + "like": fasilitas.like, + "dislike": fasilitas.dislike, + "rating": fasilitas.rating, + "tag": fasilitas.tag, + "disabilitas": fasilitas.disabilitas, + "jumlah": fasilitas.jumlah, + "image": '/media/' + str(fasilitas.image), + "is_verified": fasilitas.is_verified + } + + self.assertEqual(response.status_code, HTTPStatus.OK) self.assertEqual(content, expected_json) def test_cannot_post_list_fasilitas(self): @@ -74,10 +99,6 @@ class FasilitasRelatedViewTest(InformasiFasilitasViewTest): response = Client().get(self.get_detail_fasilitas_url) self.assertEqual(response.status_code, HTTPStatus.OK) - def test_can_get_detail_fasilitas_json(self): - response = Client().get(self.get_detail_fasilitas_url) - self.assertEqual(response.status_code, HTTPStatus.OK) - def test_cannot_post_detail_fasilitas(self): response = Client().post(self.get_detail_fasilitas_url) self.assertEqual(response.status_code, HTTPStatus.METHOD_NOT_ALLOWED) diff --git a/informasi_fasilitas/test_views_kegiatan.py b/informasi_fasilitas/test_views_kegiatan.py new file mode 100644 index 0000000000000000000000000000000000000000..cd84115ec9011aad8e555d066d0f2eaadc0ccc8c --- /dev/null +++ b/informasi_fasilitas/test_views_kegiatan.py @@ -0,0 +1,214 @@ +import json +import shutil +import os +from datetime import timedelta +from http import HTTPStatus +from django.test import Client +from django.urls import reverse +from django.test import override_settings +from django.utils import timezone +from django.core.files.uploadedfile import SimpleUploadedFile +from django.conf import settings +from unittest.mock import patch +from .test_base import InformasiFasilitasViewTest +from .models import Lokasi, Kegiatan, FotoKegiatan +from pplbackend.utils import response_decode + +class KegiatanRelatedViewTest(InformasiFasilitasViewTest): + + def setUp(self): + super().setUp() + self.media_root = os.path.join(settings.BASE_DIR, 'test_file/media') + self.kegiatan = self.create_kegiatan_test(self.user, self.lokasi) + self.kwargs_place_id = {'place_id': self.lokasi.place_id} + self.kwargs_add_or_update_kegiatan = { + 'place_id': self.lokasi.place_id, + 'id': self.kegiatan.id, + } + self.kwargs_get_foto_kegiatan = { + 'place_id': self.lokasi.place_id, + 'kegiatan_id': self.kegiatan.id, + } + + self.kwargs_kegiatan_id = {'kegiatan_id' : self.kegiatan.lokasi.place_id} + + image_path1, image_path2 = ("test_file/test1.jpg", "test_file/test2.jpg") + image1 = SimpleUploadedFile("test1.jpg", content=open(image_path1, 'rb').read(), + content_type='image/jpeg') + image2 = SimpleUploadedFile("test2.jpg", content=open(image_path2, 'rb').read(), + content_type='image/jpeg') + + self.kegiatan_images = {'images': [image1, image2]} + for image in self.kegiatan_images["images"]: + FotoKegiatan.objects.create(kegiatan=self.kegiatan, foto=image) + + self.get_list_kegiatan_url = \ + reverse('list-kegiatan', kwargs=self.kwargs_place_id) + self.get_detail_kegiatan_url = \ + reverse('detail-kegiatan', kwargs=self.kwargs_add_or_update_kegiatan) + self.get_nearest_kegiatan_url = \ + reverse('nearest-kegiatan') + self.add_kegiatan_url = \ + reverse('add-kegiatan', kwargs=self.kwargs_place_id) + self.update_kegiatan_url = reverse('update-kegiatan', + kwargs=self.kwargs_add_or_update_kegiatan) + + + self.list_foto_kegiatan_url = \ + reverse('list-foto-kegiatan', kwargs=self.kwargs_get_foto_kegiatan) + + def tearDown(self): + try: + shutil.rmtree(self.media_root) + except OSError: + pass + + + @override_settings(MEDIA_ROOT=("test_file" + '/media')) + def test_can_add_kegiatan(self): + Kegiatan.objects.all().delete() + response_params = self.mock_kegiatan_test.copy() + response_params.update(self.kegiatan_images) + response = \ + self.client.post(self.add_kegiatan_url, response_params) + data = response.json() + data.pop("id", None) + expected_json = self.mock_kegiatan_test.copy() + expected_json.update({'creator': 'mock last_name', + 'place_id': 'mock_place_id' + }) + self.assertEqual(response.status_code, HTTPStatus.CREATED) + self.assertDictEqual(data, expected_json) + count = Kegiatan.objects.all().count() + count_foto = FotoKegiatan.objects.all().count() + self.assertEqual(count, 1) + self.assertEqual(count_foto, 2) + + def test_add_kegiatan_with_missing_params(self): + Kegiatan.objects.all().delete() + response_params = self.mock_kegiatan_test.copy() + response_params.pop("time_start", None) + response = \ + self.client.post(self.add_kegiatan_url, response_params) + self.assertEqual(response.status_code, HTTPStatus.BAD_REQUEST) + + def test_add_kegiatan_lokasi_not_exist(self): + Kegiatan.objects.all().delete() + url = reverse('add-kegiatan', kwargs={ + 'place_id': "IDSNKCM", + }) + response_params = self.mock_kegiatan_test.copy() + response = self.client.post(url, response_params) + self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND) + + def test_can_get_list_kegiatan(self): + response = Client().get(self.get_list_kegiatan_url) + self.assertEqual(response.status_code, HTTPStatus.OK) + content = json.loads(response.content.decode('utf-8')) + expected_json = { + str(self.kegiatan.id): { + 'id': self.kegiatan.id, + 'place_id': self.kegiatan.lokasi.place_id, + 'creator': self.kegiatan.user.last_name, + 'nama_kegiatan' : self.kegiatan.nama_kegiatan, + 'penyelenggara': self.kegiatan.penyelenggara, + 'deskripsi': self.kegiatan.deskripsi, + 'links': self.kegiatan.links, + 'narahubung': self.kegiatan.narahubung, + 'time_start': self.kegiatan.time_start, + 'time_end': self.kegiatan.time_end, + }, + } + self.assertEqual(content, expected_json) + + def test_can_get_detail_kegiatan(self): + response = Client().get(self.get_detail_kegiatan_url) + self.assertEqual(response.status_code, HTTPStatus.OK) + content = json.loads(response.content.decode('utf-8')) + expected_json = { + 'id': self.kegiatan.id, + 'place_id': self.kegiatan.lokasi.place_id, + 'creator': self.kegiatan.user.last_name, + 'nama_kegiatan' : self.kegiatan.nama_kegiatan, + 'penyelenggara': self.kegiatan.penyelenggara, + 'deskripsi': self.kegiatan.deskripsi, + 'links': self.kegiatan.links, + 'narahubung': self.kegiatan.narahubung, + 'time_start': self.kegiatan.time_start, + 'time_end': self.kegiatan.time_end, + } + self.assertEqual(content, expected_json) + + def test_can_get_nearest_kegiatan(self): + response = Client().get(self.get_nearest_kegiatan_url) + self.assertEqual(response.status_code, HTTPStatus.OK) + content = json.loads(response.content.decode('utf-8')) + expected_json = { + 'id': self.kegiatan.id, + 'place_id': self.kegiatan.lokasi.place_id, + 'creator': self.kegiatan.user.last_name, + 'nama_kegiatan' : self.kegiatan.nama_kegiatan, + 'penyelenggara': self.kegiatan.penyelenggara, + 'deskripsi': self.kegiatan.deskripsi, + 'links': self.kegiatan.links, + 'narahubung': self.kegiatan.narahubung, + 'time_start': self.kegiatan.time_start, + 'time_end': self.kegiatan.time_end, + } + self.assertEqual(content, expected_json) + + @patch('informasi_fasilitas.views_kegiatan.timezone') + def test_empty_get_nearest_kegiatan(self, mock_timezone): + mock_timezone.now.return_value = timezone.now() + timedelta(days=100) + response = Client().get(self.get_nearest_kegiatan_url) + self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND) + + @override_settings(MEDIA_ROOT=("test_file" + '/media')) + def test_can_put_update_kegiatan(self): + send_data = { + 'deskripsi': 'deskripsi kegiatan baru untuk test', + 'nama_kegiatan': 'nama kegiatan baru untuk test', + } + send_data.update(self.kegiatan_images) + response = self.client.put(self.update_kegiatan_url, data=send_data) + data = response.json() + data.pop("id", None) + expected_json = self.mock_kegiatan_test.copy() + expected_json.update({'creator': 'mock last_name', + 'place_id': 'mock_place_id' + }) + send_data.pop("images") + expected_json.update(send_data) + self.assertEqual(response.status_code, HTTPStatus.ACCEPTED) + self.assertDictEqual(data, expected_json) + + count = Kegiatan.objects.all().count() + count_foto = FotoKegiatan.objects.all().count() + self.assertEqual(count, 1) + self.assertEqual(count_foto, 4) + + + def test_update_kegiatan_lokasi_not_exist(self): + Kegiatan.objects.all().delete() + url = reverse('update-kegiatan', kwargs={ + 'place_id': "IDSNKCM", + 'id': 200, + }) + send_data = { + 'deskripsi': 'deskripsi kegiatan baru untuk test', + 'nama_kegiatan': 'nama kegiatan baru untuk test', + 'narahubung': 'narahubung baru' + } + response = self.client.put(url, data=send_data) + self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND) + + + def test_can_get_list_foto_kegiatan(self): + response = Client().get(self.list_foto_kegiatan_url) + data = response.json() + self.assertEqual(len(data), 2) + counter = 1 + for _, item in data.items(): + self.assertIn("test"+str(counter), item["foto"]) + self.assertEqual(item["kegiatan"], self.kegiatan.id) + counter += 1 diff --git a/informasi_fasilitas/test_views_komentar_kegiatan.py b/informasi_fasilitas/test_views_komentar_kegiatan.py new file mode 100644 index 0000000000000000000000000000000000000000..c712e2201833804497390f08361bcd7b65d3d518 --- /dev/null +++ b/informasi_fasilitas/test_views_komentar_kegiatan.py @@ -0,0 +1,111 @@ +import json +from http import HTTPStatus +from django.test import Client +from django.urls import reverse + +from .test_base import InformasiFasilitasViewTest +from .models import Lokasi, Kegiatan, KomentarKegiatan +from pplbackend.utils import response_decode + +class KomentarKegiatanRelatedViewTest(InformasiFasilitasViewTest): + + def setUp(self): + super().setUp() + self.kegiatan = self.create_kegiatan_test(self.user, self.lokasi) + self.kwargs_place_id = {'place_id': self.lokasi.place_id} + self.kwargs_kegiatan_id = { + 'place_id': self.lokasi.place_id, + 'kegiatan_id' : self.kegiatan.id, + } + + self.add_komentar_kegiatan_url = \ + reverse('add-komentar-kegiatan', kwargs=self.kwargs_kegiatan_id) + self.list_komentar_kegiatan_url = \ + reverse('list-komentar-kegiatan', kwargs=self.kwargs_kegiatan_id) + + def test_can_add_komentar_kegiatan(self): + KomentarKegiatan.objects.all().delete() + response = \ + self.client.post(self.add_komentar_kegiatan_url, self.mock_komentar_kegiatan_test) + self.assertEqual(response.status_code, HTTPStatus.CREATED) + + count = KomentarKegiatan.objects.filter(kegiatan=self.kegiatan).count() + self.assertEqual(count, 1) + + def test_fail_add_komentar_kegiatan(self): + KomentarKegiatan.objects.all().delete() + response = \ + self.client.post(self.add_komentar_kegiatan_url, None) + self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND) + + count = KomentarKegiatan.objects.filter(kegiatan=self.kegiatan).count() + self.assertEqual(count, 0) + + def test_can_get_list_komentar_kegiatan(self): + komentar = self.create_komentar_kegiatan_test(user=self.user, kegiatan=self.kegiatan) + response = self.client.get(self.list_komentar_kegiatan_url) + self.assertEqual(response.status_code, HTTPStatus.OK) + + response_json = response_decode(response) + expected_id = komentar.id + expected_creator = komentar.user.last_name + expected_kegiatan = komentar.kegiatan.id + expected_deskripsi = komentar.deskripsi + + self.assertEqual(response_json[str(komentar.id)]['id'], expected_id) + self.assertEqual(response_json[str(komentar.id)]['creator'], expected_creator) + self.assertEqual(response_json[str(komentar.id)]['kegiatan'], expected_kegiatan) + self.assertEqual(response_json[str(komentar.id)]['deskripsi'], expected_deskripsi) + self.assertEqual(True, ('created' in response_json[str(komentar.id)].keys())) + + def test_can_get_komentar_kegiatan(self): + komentar = self.create_komentar_kegiatan_test(user=self.user, kegiatan=self.kegiatan) + kwargs_get_komentar_kegiatan = { + 'place_id': self.lokasi.place_id, + 'kegiatan_id': self.kegiatan.id, + 'komentar_id': komentar.id, + } + get_komentar_kegiatan_url = \ + reverse('get-komentar-kegiatan', kwargs=kwargs_get_komentar_kegiatan) + response = self.client.get(get_komentar_kegiatan_url) + self.assertEqual(response.status_code, HTTPStatus.OK) + + response_json = response_decode(response) + expected_id = komentar.id + expected_creator = komentar.user.last_name + expected_kegiatan = komentar.kegiatan.id + expected_deskripsi = komentar.deskripsi + + self.assertEqual(response_json['id'], expected_id) + self.assertEqual(response_json['creator'], expected_creator) + self.assertEqual(response_json['kegiatan'], expected_kegiatan) + self.assertEqual(response_json['deskripsi'], expected_deskripsi) + self.assertEqual(True, ('created' in response_json.keys())) + + def test_fail_get_komentar_kegiatan(self): + response = self.client.get('/informasi-fasilitas/lokasi/get-komentar-kegiatan/harusnyaTidakAda/101/1011') + self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND) + + def test_can_delete_komentar_kegiatan(self): + KomentarKegiatan.objects.all().delete() + komentar = self.create_komentar_kegiatan_test(user=self.user, kegiatan=self.kegiatan) + + kwargs_delete_komentar_kegiatan = { + 'place_id': self.lokasi.place_id, + 'kegiatan_id': self.kegiatan.id, + 'komentar_id': komentar.id, + } + + delete_komentar_kegiatan_url = \ + reverse('delete-komentar-kegiatan', kwargs=kwargs_delete_komentar_kegiatan) + + response = self.client.delete(delete_komentar_kegiatan_url) + self.assertEqual(response.status_code, HTTPStatus.OK) + + count = KomentarKegiatan.objects.filter(kegiatan=self.kegiatan).count() + self.assertEqual(count, 0) + + def test_fail_delete_komentar_kegiatan(self): + response = self.client.delete('/informasi-fasilitas/lokasi/delete-komentar-kegiatan/harusnyaTidakAda/10/10101') + self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND) + diff --git a/informasi_fasilitas/urls.py b/informasi_fasilitas/urls.py index eacb246c2f4ce743d31caa4688f669a44ba99daa..9529f3ef9a6a7449b40c28efd77076ccae8a29f9 100644 --- a/informasi_fasilitas/urls.py +++ b/informasi_fasilitas/urls.py @@ -1,5 +1,5 @@ from django.urls import path -from . import views +from . import views, views_kegiatan, views_komentar_kegiatan list_lokasi_views = views.LokasiListCreateView.as_view({'get':'list'}) add_lokasi_views = views.LokasiListCreateView.as_view({'post':'create'}) @@ -29,4 +29,36 @@ urlpatterns = [ path('lokasi/like-fasilitas////', views.update_like_fasilitas, name='update-like-fasilitas'), + + path('lokasi/list-kegiatan//', + views_kegiatan.list_kegiatan, name='list-kegiatan'), + + path('lokasi/detail-kegiatan///', + views_kegiatan.detail_kegiatan, name='detail-kegiatan'), + + path('lokasi/kegiatan-terdekat', + views_kegiatan.nearest_kegiatan, name='nearest-kegiatan'), + + path('lokasi/add-kegiatan//', + views_kegiatan.add_kegiatan, name='add-kegiatan'), + + path('lokasi/update-kegiatan///', + views_kegiatan.update_kegiatan, name='update-kegiatan'), + + path('lokasi/list-foto-kegiatan//', + views_kegiatan.list_foto_kegiatan, name='list-foto-kegiatan'), + + path('lokasi/get-komentar-kegiatan///', + views_komentar_kegiatan.get_komentar_kegiatan, name='get-komentar-kegiatan'), + + path('lokasi/list-komentar-kegiatan//', + views_komentar_kegiatan.list_komentar_kegiatan, name='list-komentar-kegiatan'), + + path('lokasi/add-komentar-kegiatan//', + views_komentar_kegiatan.add_komentar_kegiatan, name='add-komentar-kegiatan'), + + path('lokasi/delete-komentar-kegiatan///', + views_komentar_kegiatan.delete_komentar_kegiatan, name='delete-komentar-kegiatan'), + + ] diff --git a/informasi_fasilitas/views.py b/informasi_fasilitas/views.py index de5e357a861338d449ea9f5b9258bf633d6b20df..bebbff7a06c1a5084eae31c9bf2ff8c3f61b0d54 100644 --- a/informasi_fasilitas/views.py +++ b/informasi_fasilitas/views.py @@ -64,6 +64,7 @@ def list_fasilitas(request, place_id): list_fasilitas = Fasilitas.objects.filter(lokasi=lokasi) return_json = {} for fasilitas in list_fasilitas: + user = fasilitas.user fasilitas.like = Likes.objects.filter( fasilitas=fasilitas).count() fasilitas.dislike = Dislikes.objects.filter( @@ -71,6 +72,7 @@ def list_fasilitas(request, place_id): return_json[fasilitas.id] = {} fasilitas_details = return_json[fasilitas.id] fasilitas_details["id"] = fasilitas.id + fasilitas_details["creator_email"] = user.email fasilitas_details["place_id"] = fasilitas.lokasi.place_id fasilitas_details["deskripsi"] = fasilitas.deskripsi fasilitas_details["creator"] = fasilitas.user.last_name @@ -141,7 +143,7 @@ def detail_fasilitas(request, place_id, id): "deskripsi": fasilitas.deskripsi, "creator": user.last_name, "creator_email": user.email, - "date_time": fasilitas.date_time, + "date_time": fasilitas.date_time.strftime(TIME_FORMAT), "like": fasilitas.like, "dislike": fasilitas.dislike, "rating": fasilitas.rating, diff --git a/informasi_fasilitas/views_kegiatan.py b/informasi_fasilitas/views_kegiatan.py new file mode 100644 index 0000000000000000000000000000000000000000..7bf9c2c23586bf21abefabda55b57230bc495f28 --- /dev/null +++ b/informasi_fasilitas/views_kegiatan.py @@ -0,0 +1,122 @@ +from http import HTTPStatus +from django.http import JsonResponse +from django.utils import timezone +from rest_framework.decorators import api_view, permission_classes, authentication_classes +from rest_framework.authentication import TokenAuthentication +from rest_framework.permissions import IsAuthenticated +from rest_framework.response import Response +from rest_framework.views import APIView +from rest_framework.exceptions import AuthenticationFailed, NotFound +from .models import Kegiatan, Lokasi, FotoKegiatan +from django.contrib.auth.models import User +from .serializers import KegiatanSerializer, FotoKegiatanSerializer + + +@api_view(['GET']) +@authentication_classes([]) +@permission_classes([]) +def list_kegiatan(request, place_id): + queryset = Kegiatan.objects.filter(lokasi__place_id=place_id) + serializer = KegiatanSerializer(queryset, many=True) + data_response = serializer.data + new_dict = {item['id']: _clean_json_kegiatan(dict(item)) for item in data_response} + return JsonResponse(new_dict, status=HTTPStatus.OK) + + +@api_view(['GET']) +@authentication_classes([]) +@permission_classes([]) +def detail_kegiatan(request, place_id, id): + try: + queryset = Kegiatan.objects.get(lokasi__place_id=place_id, id=id) + serializer = KegiatanSerializer(queryset, many=False) + return JsonResponse(_clean_json_kegiatan(serializer.data), status=HTTPStatus.OK) + except Kegiatan.DoesNotExist: + raise NotFound(detail="Kegiatan doesn't exist") + + +@api_view(['GET']) +@authentication_classes([]) +@permission_classes([]) +def nearest_kegiatan(request): + time_now = timezone.now() + queryset = Kegiatan.objects.filter(time_start__gte=time_now).order_by('time_start').first() + if queryset is None: + raise NotFound(detail="No Kegiatan available") + serializer = KegiatanSerializer(queryset, many=False) + return JsonResponse(_clean_json_kegiatan(serializer.data), status=HTTPStatus.OK) + +@api_view(['POST']) +@authentication_classes([TokenAuthentication]) +@permission_classes([IsAuthenticated]) +def add_kegiatan(request, place_id): + try: + lokasi = Lokasi.objects.get(place_id=place_id) + user = request.user + data = request.data.dict() + data.update({"user": user.id, "lokasi": lokasi.id}) + data.pop("images", []) + + serializer = KegiatanSerializer(data=data) + serializer.is_valid(raise_exception=True) + kegiatan = serializer.save() + serializer = _add_foto_kegiatan(kegiatan, request.data.getlist("images")) + + return JsonResponse(_clean_json_kegiatan(serializer.data), status=HTTPStatus.CREATED) + except Lokasi.DoesNotExist: + raise NotFound(detail="Lokasi doesn't exist") + + +@api_view(['PUT']) +@authentication_classes([TokenAuthentication]) +@permission_classes([IsAuthenticated]) +def update_kegiatan(request, place_id, id): + try: + kegiatan = Kegiatan.objects.get(lokasi__place_id=place_id, id=id) + data = request.data.dict() + data.pop("images", []) + serializer = KegiatanSerializer(kegiatan, data=data, partial=True) + serializer.is_valid(raise_exception=True) + kegiatan = serializer.save() + serializer = _add_foto_kegiatan(kegiatan, request.data.getlist("images")) + + return JsonResponse(_clean_json_kegiatan(serializer.data), status=HTTPStatus.ACCEPTED) + except Kegiatan.DoesNotExist: + raise NotFound(detail="Kegiatan doesn't exist") + +@api_view(['GET']) +@authentication_classes([]) +@permission_classes([]) +def list_foto_kegiatan(request, place_id, kegiatan_id): + queryset = FotoKegiatan.objects.filter(kegiatan__lokasi__place_id=place_id, + kegiatan_id=kegiatan_id) + serializer = FotoKegiatanSerializer(queryset, many=True) + data_response = serializer.data + new_dict = {item['id']: dict(item) for item in data_response} + return JsonResponse(new_dict, status=HTTPStatus.OK) + + +def _clean_json_kegiatan(kegiatan): + kegiatan.pop("user") + kegiatan.pop("lokasi") + return kegiatan + + +def _add_foto_kegiatan(kegiatan, list_image): + _create_list_kegiatan_foto(kegiatan, list_image) + kegiatan.refresh_from_db() + return KegiatanSerializer(kegiatan) + + +def _create_list_kegiatan_foto(kegiatan, list_image): + list_kegiatan_foto = [] + for image in list_image: + foto = FotoKegiatan.objects.create(kegiatan=kegiatan, foto=image) + list_kegiatan_foto.append(foto) + return list_kegiatan_foto + + + + + + diff --git a/informasi_fasilitas/views_komentar_kegiatan.py b/informasi_fasilitas/views_komentar_kegiatan.py new file mode 100644 index 0000000000000000000000000000000000000000..eea287289c64f3e0ed31379665e372da73a6467e --- /dev/null +++ b/informasi_fasilitas/views_komentar_kegiatan.py @@ -0,0 +1,74 @@ +from http import HTTPStatus +from django.http import JsonResponse +from django.views.decorators.csrf import csrf_exempt +from django.contrib.auth.models import User +from django.core.exceptions import ObjectDoesNotExist +from django.db.models import F + +from rest_framework.decorators import api_view, permission_classes, authentication_classes +from rest_framework.authentication import TokenAuthentication +from rest_framework.permissions import IsAuthenticated +from rest_framework.response import Response +from rest_framework.parsers import FileUploadParser +from rest_framework.views import APIView +from rest_framework.generics import ListCreateAPIView +from rest_framework import viewsets + +from .serializers import KomentarKegiatanSerializer +from .models import Lokasi, Kegiatan, KomentarKegiatan +from .permissions import UserPermission + +@api_view(['GET']) +@authentication_classes([]) +@permission_classes([]) +def list_komentar_kegiatan(request, place_id, kegiatan_id): + try: + queryset = KomentarKegiatan.objects.filter(kegiatan__lokasi__place_id=place_id, kegiatan__id=kegiatan_id) + serializer = KomentarKegiatanSerializer(queryset, many=True) + data_response = serializer.data + new_dict = {item['id']: dict(item) for item in data_response} + return JsonResponse(new_dict, status=HTTPStatus.OK) + except Exception as error: + return JsonResponse({'response': str(error)}, status=HTTPStatus.NOT_FOUND) + +@api_view(['GET']) +@authentication_classes([]) +@permission_classes([]) +def get_komentar_kegiatan(request, place_id, kegiatan_id, komentar_id): + try: + komentar = KomentarKegiatan.objects.get(kegiatan__lokasi__place_id=place_id, + kegiatan__id=kegiatan_id, id=komentar_id) + serializer = KomentarKegiatanSerializer(komentar, many=False) + return JsonResponse(serializer.data, status=HTTPStatus.OK) + except ObjectDoesNotExist: + return JsonResponse({'response': 'Komentar tidak ditemukan'}, status=HTTPStatus.NOT_FOUND) + +@api_view(['POST']) +@authentication_classes([TokenAuthentication]) +@permission_classes([IsAuthenticated]) +def add_komentar_kegiatan(request, place_id, kegiatan_id): + try: + kegiatan = Kegiatan.objects.get(lokasi__place_id=place_id, id=kegiatan_id) + deskripsi = request.POST['deskripsi'] + komentar = KomentarKegiatan.objects \ + .create( + kegiatan=kegiatan, + user=request.user, + deskripsi=deskripsi + ) + return JsonResponse({'response': 'komentar kegiatan added', 'id': komentar.id}, + status=HTTPStatus.CREATED) + except Exception as error: + return JsonResponse({'response': str(error)}, status=HTTPStatus.NOT_FOUND) + +@api_view(['DELETE']) +@authentication_classes([TokenAuthentication]) +@permission_classes([IsAuthenticated]) +def delete_komentar_kegiatan(request, place_id, kegiatan_id, komentar_id): + try: + komentar = KomentarKegiatan.objects.get(kegiatan__lokasi__place_id=place_id, kegiatan__id=kegiatan_id, id=komentar_id) + komentar.delete() + return JsonResponse({'response': 'komentar kegiatan deleted', 'id': komentar_id}, + status=HTTPStatus.OK) + except Exception as error: + return JsonResponse({'response': str(error)}, status=HTTPStatus.NOT_FOUND) diff --git a/layanan_khusus/tests.py b/layanan_khusus/tests.py index 2acae84edfdcdc716cc2dd3a8e3a8bf5d154211d..19c698d4697da053b2f97aac93905a10ba464bef 100644 --- a/layanan_khusus/tests.py +++ b/layanan_khusus/tests.py @@ -7,6 +7,7 @@ from django.contrib.auth.models import User from django.urls import path, include, reverse from .models import Sekolah, Penyandang, Komunitas from .serializers import SekolahSerializer, KomunitasSerializer +import django ID = 'id' NAME = 'name' diff --git a/new_rest_api/tests.py b/new_rest_api/tests.py index ef33fb25a06a89e99fa65c42023e0c40e73e2474..81b9256937ad637a0973d9bbbecd9d85ff15785a 100644 --- a/new_rest_api/tests.py +++ b/new_rest_api/tests.py @@ -7,6 +7,8 @@ from django.utils.http import urlsafe_base64_encode from django.utils.encoding import force_bytes from registrasi.models import BisaGoUser from .tokens import account_activation_token +import io +import requests class UserTests(APITestCase): urlpatterns = [ @@ -51,14 +53,14 @@ class UserTests(APITestCase): response = self.client.get(url, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) json_test = json.loads(response.content) - self.assertEqual(len(json_test), 10) #JSON Attribute + self.assertEqual(len(json_test), 12) #JSON Attribute def test_account_details(self): url = reverse('user-details', kwargs={'email':'astraykai@gmail.com'}) response = self.client.get(url, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) json_test = json.loads(response.content) - self.assertEqual(len(json_test), 10) #JSON Attribute + self.assertEqual(len(json_test), 12) #JSON Attribute def test_account_list(self): url = reverse('user-list') @@ -185,7 +187,48 @@ class UserTests(APITestCase): json_response = json.loads(response.content) self.assertEqual(json_response['response'], 'Internal server error') + def test_upload_foto_with_invalid_image(self): + ''' + Ensure that profile picture will not be updated if invalid image is sent + ''' + + url = reverse('update-user') + data = {'name': 'Astraykai', + 'email':'astraykai@gmail.com', + 'phone_number':'089892218567', + 'tanggal_lahir':'1990-05-05', + 'jenis_kelamin':'Laki-laki', + 'disabilitas':'', + 'pekerjaan':'Mahasiswa', + 'alamat':'Alamat Palsu', + 'foto':(io.BytesIO(b"this is a test"), 'test.pdf')} + response = self.client.post(url, data, headers={'Content-Type': "multipart/form-data"}) + json_response = json.loads(response.content) + self.assertEqual(json_response['response'], 'File is not image type') + + def test_all_user_information_can_be_seen_after_register(self): + ''' + Ensure that user information can be seen by others after registration + ''' + + url = reverse('create-user') + data = {'name': 'Astray', + 'email':'astrayyahoo@gmail.com', + 'password':'chingchenghanji', + 'phone_number':'08989221856', + 'tanggal_lahir':'1990-05-05', + 'jenis_kelamin':'Laki-laki', + 'disabilitas':'Yuhu', + 'pekerjaan':'Mahasiswa', + 'alamat':'Alamat Palsu', + 'is_active': True} + response = self.client.post(url, data) + url = reverse('user-details', kwargs={'email':'astrayyahoo@gmail.com'}) + response = self.client.get(url, format='json') + json_test = json.loads(response.content) + print(json_test) + self.assertEqual(json_test['seen'], True) class InfoTests(APITestCase, URLPatternsTestCase): pass diff --git a/new_rest_api/views.py b/new_rest_api/views.py index 3a19e782691489eb2922a5f25326656378cb32fe..4e6ec6268ecd1e67f0839b4ea9d7f25d8dfce0f0 100644 --- a/new_rest_api/views.py +++ b/new_rest_api/views.py @@ -18,6 +18,10 @@ from registrasi.models import BisaGoUser from registrasi.serializers import BisaGoUserSerializers from .tokens import account_activation_token +from django.core.files.storage import default_storage +from django.core.files.base import ContentFile +from django.conf import settings + def request_error_message(request_kind): return "get {} request instead".format(request_kind) @@ -80,6 +84,7 @@ def register_user(request): user.is_active = False user.save() data['user'] = user.pk + data['seen'] = True mail_subject = "Activate your account" message = render_to_string('acc_active_email.html', { 'user' : user, @@ -136,17 +141,23 @@ def update_user(request): name = request.POST['name'] email = request.POST['email'] data = dict(list(request.POST.dict().items())) + if request.FILES : + type = request.FILES['foto'].content_type.split("/")[0] + if type == "image" : + data['foto'] = request.FILES['foto'] + else : + return JsonResponse({'response': 'File is not image type'}, safe=False, + status=status.INTERNAL_SERVER_ERROR) user = User.objects.get(username=email) + data["user"] = user.pk bisa_go_user = BisaGoUser.objects.get(user=user) - user.last_name = name - data['user'] = user.pk data_query_dict = QueryDict('', mutable=True) data_query_dict.update(data) serializer = BisaGoUserSerializers(bisa_go_user, data=data_query_dict) if serializer.is_valid(): user.save() serializer.save() - else: + else: return JsonResponse({'response': 'Internal server error'}, safe=False, status=status.INTERNAL_SERVER_ERROR) return JsonResponse({'response': 'User updated'}, safe=False, status=status.OK) diff --git a/pplbackend/settings.py b/pplbackend/settings.py index 0c7eeda773f1cb7ad05b4656f12c3e3f061fdf95..1804a87c224195e2e824954edec195a212d1f154 100644 --- a/pplbackend/settings.py +++ b/pplbackend/settings.py @@ -200,6 +200,7 @@ SOCIALACCOUNT_PROVIDERS = { LOGIN_REDIRECT_URL = '/' REST_FRAMEWORK = { + 'DATETIME_FORMAT': "%Y-%m-%d %H:%M", 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE': 10, 'DEFAULT_AUTHENTICATION_CLASSES': [ diff --git a/pplbackend/utils.py b/pplbackend/utils.py index dac4c0a3b39418e85be45afac803d34fb7e2399f..1273caff9f5d28206030d7b79bef99432c260406 100644 --- a/pplbackend/utils.py +++ b/pplbackend/utils.py @@ -1,7 +1,7 @@ from rest_framework.test import APIClient from rest_framework_simplejwt.tokens import RefreshToken from rest_framework.authtoken.models import Token - +from rest_framework.test import APIClient from django.urls import reverse from django.test import Client @@ -9,7 +9,7 @@ import json def get_client_login_with_user(user): token, _ = Token.objects.get_or_create(user=user) - client = Client(HTTP_AUTHORIZATION=f'token {token.key}') + client = APIClient(HTTP_AUTHORIZATION=f'token {token.key}') return client diff --git a/registrasi/migrations/0005_auto_20210516_1734.py b/registrasi/migrations/0005_auto_20210516_1734.py new file mode 100644 index 0000000000000000000000000000000000000000..a627fce94b9cf352ffa8b50c5d3a9341f7ebe86b --- /dev/null +++ b/registrasi/migrations/0005_auto_20210516_1734.py @@ -0,0 +1,19 @@ +# Generated by Django 3.1.7 on 2021-05-16 17:34 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('registrasi', '0004_auto_20201210_1459'), + ] + + operations = [ + migrations.AlterField( + model_name='bisagouser', + name='tanggal_lahir', + field=models.DateField(default=datetime.date.today, max_length=15, verbose_name='Tanggal Lahir'), + ), + ] diff --git a/registrasi/migrations/0005_bisagouser_foto.py b/registrasi/migrations/0005_bisagouser_foto.py new file mode 100644 index 0000000000000000000000000000000000000000..a67db68417556a86ee35e0333d46b2dfe81d5387 --- /dev/null +++ b/registrasi/migrations/0005_bisagouser_foto.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.2 on 2021-05-10 07:28 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('registrasi', '0004_auto_20201210_1459'), + ] + + operations = [ + migrations.AddField( + model_name='bisagouser', + name='foto', + field=models.ImageField(blank=True, default='-', null=True, upload_to='', verbose_name='Foto'), + ), + ] diff --git a/registrasi/migrations/0006_bisagouser_seen.py b/registrasi/migrations/0006_bisagouser_seen.py new file mode 100644 index 0000000000000000000000000000000000000000..1884243e29c8c87efa2e481d8ca5ab63cad0499a --- /dev/null +++ b/registrasi/migrations/0006_bisagouser_seen.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.2 on 2021-05-10 20:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('registrasi', '0005_bisagouser_foto'), + ] + + operations = [ + migrations.AddField( + model_name='bisagouser', + name='seen', + field=models.BooleanField(blank=True, default=True, verbose_name='Seen'), + ), + ] diff --git a/registrasi/migrations/0006_merge_20210516_1820.py b/registrasi/migrations/0006_merge_20210516_1820.py new file mode 100644 index 0000000000000000000000000000000000000000..d6db4439e1fec3e1edc3a7be92cea376ba6977d4 --- /dev/null +++ b/registrasi/migrations/0006_merge_20210516_1820.py @@ -0,0 +1,14 @@ +# Generated by Django 3.1.7 on 2021-05-16 18:20 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('registrasi', '0005_bisagouser_foto'), + ('registrasi', '0005_auto_20210516_1734'), + ] + + operations = [ + ] diff --git a/registrasi/migrations/0007_merge_20210517_0447.py b/registrasi/migrations/0007_merge_20210517_0447.py new file mode 100644 index 0000000000000000000000000000000000000000..5760767c1a7e1e658dbf2cfe99ad5d456dcffb75 --- /dev/null +++ b/registrasi/migrations/0007_merge_20210517_0447.py @@ -0,0 +1,14 @@ +# Generated by Django 3.1.7 on 2021-05-17 04:47 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('registrasi', '0006_bisagouser_seen'), + ('registrasi', '0006_merge_20210516_1820'), + ] + + operations = [ + ] diff --git a/registrasi/models.py b/registrasi/models.py index 65bd41abc6989fdeb951703d4b31c500de47197d..3363a3fd043177f80ddca0161e7a0127e534872c 100644 --- a/registrasi/models.py +++ b/registrasi/models.py @@ -1,6 +1,7 @@ from django.db import models from django.core.mail import send_mail from django.contrib.auth.models import User +from datetime import date class BisaGoUser(models.Model): @@ -8,10 +9,12 @@ class BisaGoUser(models.Model): db_table = "BisaGoUser" user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="phone_number") phone_number = models.CharField('Nomor Telepon', max_length=15, unique=True) - tanggal_lahir = models.DateField('Tanggal Lahir', max_length=15, null=True) + tanggal_lahir = models.DateField('Tanggal Lahir', max_length=15, null=False, default=date.today) jenis_kelamin = models.CharField('Jenis Kelamin', max_length=20, default='-') disabilitas = models.CharField('Disabilitas', max_length=64, null=True, default='Belum memilih') pekerjaan = models.CharField('Pekerjaan', max_length=64, default='-') alamat = models.CharField('Alamat', max_length=255, default='-') + foto = models.ImageField('Foto', blank=True, default='-', null=True) + seen = models.BooleanField('Seen', blank=True, default=True) def __str__(self): - return self.user.username + return self.user.username \ No newline at end of file diff --git a/registrasi/serializers.py b/registrasi/serializers.py index bfa70ccf27f047487cae41802c941289b2f6b3e8..addcd1db33fde00526054fa7c342cc6070b633f6 100644 --- a/registrasi/serializers.py +++ b/registrasi/serializers.py @@ -12,5 +12,10 @@ class BisaGoUserSerializers(serializers.ModelSerializer): 'jenis_kelamin', 'disabilitas', 'pekerjaan', - 'alamat' - ) \ No newline at end of file + 'alamat', + 'foto', + 'seen', + ) + extra_kwargs = { + 'foto': {'required': False}, + } \ No newline at end of file diff --git a/test_file/test1.jpg b/test_file/test1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5521673831b4e2d02eed407942bbeda242fd6e2d Binary files /dev/null and b/test_file/test1.jpg differ diff --git a/test_file/test2.jpg b/test_file/test2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2247108904eaf243c6e0b77d58611aae4c0c8878 Binary files /dev/null and b/test_file/test2.jpg differ