diff --git a/administration/migrations/0001_initial.py b/administration/migrations/0001_initial.py
index e9366599d40d7e904ee324478b2256d478b5cfbb..de7061bb5b822b1bdb73537ed6f3ed02053028ff 100644
--- a/administration/migrations/0001_initial.py
+++ b/administration/migrations/0001_initial.py
@@ -1,9 +1,7 @@
-# Generated by Django 3.1 on 2020-10-30 15:29
+# Generated by Django 3.0.3 on 2020-05-08 14:42
 
-from django.conf import settings
+import django.contrib.postgres.fields.jsonb
 from django.db import migrations, models
-import django.db.models.deletion
-import django.utils.timezone
 
 
 class Migration(migrations.Migration):
@@ -11,40 +9,28 @@ class Migration(migrations.Migration):
     initial = True
 
     dependencies = [
-        ('app', '0001_initial'),
-        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
     ]
 
     operations = [
-        migrations.CreateModel(
-            name='VerificationSetting',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('title', models.CharField(max_length=250)),
-                ('description', models.TextField(default='')),
-                ('archived', models.BooleanField(default=False)),
-                ('archived_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
-            ],
-        ),
         migrations.CreateModel(
             name='VerificationReport',
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('report', models.JSONField()),
-                ('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
-                ('status', models.CharField(choices=[('PENDING', 'Diproses'), ('APPROVE', 'Diterima'), ('DISAPPROVE', 'Ditolak'), ('REVISION', 'Perbaikan'), ('BLOCKED', 'Diblokir')], default='PENDING', max_length=30)),
-                ('materi', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='app.materi')),
-                ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
+                ('id', models.AutoField(auto_created=True,
+                                        primary_key=True, serialize=False, verbose_name='ID')),
+                ('report', django.contrib.postgres.fields.jsonb.JSONField()),
+                ('timestamp', models.DateTimeField(auto_now_add=True)),
+                ('status', models.CharField(choices=[('PENDING', 'Diproses'), ('APPROVE', 'Diterima'), (
+                    'DISAPPROVE', 'Ditolak'), ('REVISION', 'Perbaikan')], default='PENDING', max_length=30)),
             ],
         ),
         migrations.CreateModel(
-            name='DeletionHistory',
+            name='VerificationSetting',
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('deleted_user_name', models.CharField(max_length=150)),
-                ('deleted_user_role', models.CharField(max_length=150)),
-                ('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
-                ('deletor_admin', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
+                ('id', models.AutoField(auto_created=True,
+                                        primary_key=True, serialize=False, verbose_name='ID')),
+                ('title', models.CharField(max_length=250)),
+                ('description', models.TextField(default='')),
+                ('archived', models.BooleanField(default=False)),
             ],
         ),
     ]
diff --git a/administration/migrations/0002_verificationreport_materi.py b/administration/migrations/0002_verificationreport_materi.py
new file mode 100644
index 0000000000000000000000000000000000000000..a1b8db8f58940d8965b879efd43c80f06b4bca72
--- /dev/null
+++ b/administration/migrations/0002_verificationreport_materi.py
@@ -0,0 +1,23 @@
+# Generated by Django 3.0.3 on 2020-05-08 14:42
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        ('app', '0001_initial'),
+        ('administration', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='verificationreport',
+            name='materi',
+            field=models.ForeignKey(
+                null=True, on_delete=django.db.models.deletion.SET_NULL, to='app.Materi'),
+        ),
+    ]
diff --git a/administration/migrations/0003_verificationreport_user.py b/administration/migrations/0003_verificationreport_user.py
new file mode 100644
index 0000000000000000000000000000000000000000..236da3cd510b6203fbca8812fbcf4a33dc0da15c
--- /dev/null
+++ b/administration/migrations/0003_verificationreport_user.py
@@ -0,0 +1,24 @@
+# Generated by Django 3.0.3 on 2020-05-08 14:42
+
+import django.db.models.deletion
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+        ('administration', '0002_verificationreport_materi'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='verificationreport',
+            name='user',
+            field=models.ForeignKey(
+                null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
+        ),
+    ]
diff --git a/administration/migrations/0004_auto_20200517_1713.py b/administration/migrations/0004_auto_20200517_1713.py
new file mode 100644
index 0000000000000000000000000000000000000000..8189cd965de7bc2ddf6453176ec3ec75c07fc7f9
--- /dev/null
+++ b/administration/migrations/0004_auto_20200517_1713.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.0.3 on 2020-05-17 10:13
+
+from django.db import migrations, models
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('administration', '0003_verificationreport_user'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='verificationreport',
+            name='timestamp',
+            field=models.DateTimeField(default=django.utils.timezone.now),
+        ),
+    ]
diff --git a/administration/migrations/0005_deletionhistory.py b/administration/migrations/0005_deletionhistory.py
new file mode 100644
index 0000000000000000000000000000000000000000..a23c37e1428e4b164cfbfa9b53a58b092cb63790
--- /dev/null
+++ b/administration/migrations/0005_deletionhistory.py
@@ -0,0 +1,27 @@
+# Generated by Django 3.0.3 on 2020-06-03 12:57
+
+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),
+        ('administration', '0004_auto_20200517_1713'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='DeletionHistory',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('deleted_user_name', models.CharField(max_length=150)),
+                ('deleted_user_role', models.CharField(max_length=150)),
+                ('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
+                ('deletor_admin', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
+            ],
+        ),
+    ]
diff --git a/administration/migrations/0005_verificationsetting_archived_by.py b/administration/migrations/0005_verificationsetting_archived_by.py
new file mode 100644
index 0000000000000000000000000000000000000000..dadfd72ea51694f051a7730b60c37bf32210d354
--- /dev/null
+++ b/administration/migrations/0005_verificationsetting_archived_by.py
@@ -0,0 +1,21 @@
+# Generated by Django 3.0.3 on 2020-06-04 00:09
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+        ('administration', '0004_auto_20200517_1713'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='verificationsetting',
+            name='archived_by',
+            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
+        ),
+    ]
diff --git a/administration/migrations/0006_merge_20200604_0718.py b/administration/migrations/0006_merge_20200604_0718.py
new file mode 100644
index 0000000000000000000000000000000000000000..92c7b037550593a95bfd8bdd25312fc5568f1bd3
--- /dev/null
+++ b/administration/migrations/0006_merge_20200604_0718.py
@@ -0,0 +1,14 @@
+# Generated by Django 3.0.3 on 2020-06-04 00:18
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('administration', '0005_deletionhistory'),
+        ('administration', '0005_verificationsetting_archived_by'),
+    ]
+
+    operations = [
+    ]
diff --git a/administration/migrations/0007_auto_20200929_1218.py b/administration/migrations/0007_auto_20200929_1218.py
new file mode 100644
index 0000000000000000000000000000000000000000..735e71572df51f52e11ffe98a319fdceb3f46ba7
--- /dev/null
+++ b/administration/migrations/0007_auto_20200929_1218.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.1 on 2020-09-29 05:18
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('administration', '0006_merge_20200604_0718'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='verificationreport',
+            name='report',
+            field=models.JSONField(),
+        ),
+    ]
diff --git a/administration/migrations/0008_auto_20201009_1829.py b/administration/migrations/0008_auto_20201009_1829.py
new file mode 100644
index 0000000000000000000000000000000000000000..0302d90c1ccf01e6a7a1b313ed4ce7ee95c79573
--- /dev/null
+++ b/administration/migrations/0008_auto_20201009_1829.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.1 on 2020-10-09 11:29
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('administration', '0007_auto_20200929_1218'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='verificationreport',
+            name='status',
+            field=models.CharField(choices=[('PENDING', 'Diproses'), ('APPROVE', 'Diterima'), ('DISAPPROVE', 'Ditolak'), ('REVISION', 'Perbaikan'), ('BLOCKED', 'Diblokir')], default='PENDING', max_length=30),
+        ),
+    ]
diff --git a/app/migrations/0001_initial.py b/app/migrations/0001_initial.py
index 2e76e78466a5b35f01834a00102bee3798f0b177..51a62f576bc233af8f04a305c6be41ee5073e1fe 100644
--- a/app/migrations/0001_initial.py
+++ b/app/migrations/0001_initial.py
@@ -1,12 +1,6 @@
-# Generated by Django 3.1 on 2020-10-30 15:28
+# Generated by Django 3.0.3 on 2020-05-08 14:42
 
-import app.models
-from django.conf import settings
-import django.contrib.postgres.search
-import django.core.validators
 from django.db import migrations, models
-import django.db.models.deletion
-import django.utils.timezone
 
 
 class Migration(migrations.Migration):
@@ -14,215 +8,44 @@ class Migration(migrations.Migration):
     initial = True
 
     dependencies = [
-        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
     ]
 
     operations = [
         migrations.CreateModel(
             name='Category',
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('id', models.AutoField(auto_created=True,
+                                        primary_key=True, serialize=False, verbose_name='ID')),
                 ('name', models.CharField(max_length=20)),
-                ('description', models.TextField(default='')),
-                ('archived', models.BooleanField(default=False)),
-                ('archived_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
+                ('description', models.CharField(max_length=20)),
             ],
         ),
         migrations.CreateModel(
             name='Comment',
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('id', models.AutoField(auto_created=True,
+                                        primary_key=True, serialize=False, verbose_name='ID')),
                 ('username', models.CharField(max_length=100)),
-                ('profile', models.CharField(default=app.models.getRandomColor, max_length=100)),
-                ('comment', models.CharField(default='comments', max_length=240)),
-                ('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
-            ],
-        ),
-        migrations.CreateModel(
-            name='DownloadStatistics',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
-                ('downloader', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='riwayat_unduh', to=settings.AUTH_USER_MODEL)),
+                ('profile', models.CharField(default='56acdf', max_length=100)),
+                ('comment', models.CharField(default='comments', max_length=150)),
             ],
         ),
         migrations.CreateModel(
             name='Materi',
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('deleted_at', models.DateTimeField(blank=True, null=True)),
+                ('id', models.AutoField(auto_created=True,
+                                        primary_key=True, serialize=False, verbose_name='ID')),
                 ('cover', models.ImageField(upload_to='')),
                 ('content', models.FileField(upload_to='')),
-                ('title', models.CharField(default='Judul', max_length=50)),
-                ('author', models.CharField(default='Penyusun', max_length=30)),
-                ('publisher', models.CharField(default='Penerbit', max_length=30)),
-                ('release_year', models.IntegerField(default=app.models.current_year)),
+                ('title', models.CharField(default='title', max_length=50)),
+                ('author', models.CharField(default='author', max_length=30)),
+                ('publisher', models.CharField(default='publiser', max_length=30)),
                 ('pages', models.IntegerField(default=0)),
-                ('descriptions', models.TextField(default='Deskripsi')),
-                ('status', models.CharField(choices=[('PENDING', 'Diproses'), ('APPROVE', 'Diterima'), ('DISAPPROVE', 'Ditolak'), ('REVISION', 'Perbaikan'), ('BLOCKED', 'Diblokir')], default='PENDING', max_length=30)),
-                ('date_created', models.DateTimeField(default=django.utils.timezone.now)),
-                ('date_modified', models.DateTimeField(auto_now=True)),
-                ('yt_video_id', models.CharField(blank=True, max_length=100, null=True)),
-                ('_search_vector', django.contrib.postgres.search.SearchVectorField(editable=False, null=True)),
+                ('descriptions', models.TextField(default='descriptions')),
+                ('status', models.CharField(choices=[('PENDING', 'Diproses'), ('APPROVE', 'Diterima'), (
+                    'DISAPPROVE', 'Ditolak'), ('REVISION', 'Perbaikan')], default='PENDING', max_length=30)),
+                ('date_added', models.DateTimeField(auto_now_add=True)),
                 ('categories', models.ManyToManyField(to='app.Category')),
-                ('uploader', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
-            ],
-            options={
-                'abstract': False,
-            },
-        ),
-        migrations.CreateModel(
-            name='ReqMaterial',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('title', models.CharField(max_length=100)),
-                ('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
-            ],
-        ),
-        migrations.CreateModel(
-            name='SubmitVisitor',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('user_id', models.CharField(max_length=50)),
-                ('email', models.CharField(max_length=50)),
-                ('msg', models.CharField(max_length=100)),
-                ('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
-            ],
-        ),
-        migrations.CreateModel(
-            name='SubscribeModel',
-            fields=[
-                ('sys_id', models.AutoField(primary_key=True, serialize=False)),
-                ('email', models.EmailField(blank=True, max_length=200, unique=True)),
-                ('status', models.CharField(blank=True, max_length=64)),
-                ('created_date', models.DateTimeField(blank=True)),
-                ('updated_date', models.DateTimeField(blank=True)),
-            ],
-            options={
-                'db_table': 'app_subscribe',
-            },
-        ),
-        migrations.CreateModel(
-            name='ViewStatistics',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
-                ('materi', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='baca', to='app.materi')),
-            ],
-        ),
-        migrations.CreateModel(
-            name='Review',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('username', models.CharField(max_length=100)),
-                ('profile', models.CharField(default=app.models.getRandomColor, max_length=100)),
-                ('review', models.TextField(default='review')),
-                ('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
-                ('materi', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='app.materi')),
-                ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
-            ],
-        ),
-        migrations.CreateModel(
-            name='RatingContributor',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('timestamp', models.DateTimeField(auto_now=True)),
-                ('score', models.PositiveIntegerField(validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(5)])),
-                ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
-            ],
-        ),
-        migrations.CreateModel(
-            name='LikeComment',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
-                ('session_id', models.CharField(max_length=32)),
-                ('comment', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='app.comment')),
-            ],
-        ),
-        migrations.CreateModel(
-            name='Like',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
-                ('session_id', models.CharField(max_length=32)),
-                ('materi', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='app.materi')),
-            ],
-        ),
-        migrations.CreateModel(
-            name='LaporanMateri',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('laporan', models.TextField(default='', validators=[django.core.validators.MinValueValidator(30), django.core.validators.MaxValueValidator(120)])),
-                ('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
-                ('is_rejected', models.BooleanField(default=False)),
-                ('materi', models.ForeignKey(max_length=120, on_delete=django.db.models.deletion.CASCADE, to='app.materi')),
-                ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
-            ],
-        ),
-        migrations.CreateModel(
-            name='DummyViewStatistics',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app.viewstatistics')),
-            ],
-        ),
-        migrations.CreateModel(
-            name='DummyLike',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app.like')),
-            ],
-        ),
-        migrations.CreateModel(
-            name='DummyDownloadStatistics',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app.downloadstatistics')),
-            ],
-        ),
-        migrations.CreateModel(
-            name='DummyComment',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app.comment')),
-            ],
-        ),
-        migrations.AddField(
-            model_name='downloadstatistics',
-            name='materi',
-            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='unduh', to='app.materi'),
-        ),
-        migrations.CreateModel(
-            name='DislikeComment',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
-                ('session_id', models.CharField(max_length=32)),
-                ('comment', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='app.comment')),
-            ],
-        ),
-        migrations.AddField(
-            model_name='comment',
-            name='materi',
-            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='app.materi'),
-        ),
-        migrations.AddField(
-            model_name='comment',
-            name='user',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
-        ),
-        migrations.CreateModel(
-            name='Rating',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
-                ('score', models.IntegerField()),
-                ('materi', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app.materi')),
-                ('user', models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
             ],
-            options={
-                'unique_together': {('materi', 'user')},
-            },
         ),
     ]
diff --git a/app/migrations/0002_auto_20200508_2142.py b/app/migrations/0002_auto_20200508_2142.py
new file mode 100644
index 0000000000000000000000000000000000000000..dfeeb8495f7ea4ab0e77001b5dec910341522e0e
--- /dev/null
+++ b/app/migrations/0002_auto_20200508_2142.py
@@ -0,0 +1,36 @@
+# Generated by Django 3.0.3 on 2020-05-08 14:42
+
+import django.db.models.deletion
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+        ('app', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='materi',
+            name='uploader',
+            field=models.ForeignKey(
+                null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
+        ),
+        migrations.AddField(
+            model_name='comment',
+            name='materi',
+            field=models.ForeignKey(
+                null=True, on_delete=django.db.models.deletion.SET_NULL, to='app.Materi'),
+        ),
+        migrations.AddField(
+            model_name='comment',
+            name='user',
+            field=models.ForeignKey(
+                blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
+        ),
+    ]
diff --git a/app/migrations/0003_auto_20200509_2108.py b/app/migrations/0003_auto_20200509_2108.py
new file mode 100644
index 0000000000000000000000000000000000000000..844d9d85ad27f5f5b3102597c4e8e8ef6173f8fd
--- /dev/null
+++ b/app/migrations/0003_auto_20200509_2108.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.0.3 on 2020-05-09 14:08
+
+import app.models
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('app', '0002_auto_20200508_2142'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='comment',
+            name='profile',
+            field=models.CharField(default=app.models.getRandomColor, max_length=100),
+        ),
+    ]
diff --git a/app/migrations/0004_like.py b/app/migrations/0004_like.py
new file mode 100644
index 0000000000000000000000000000000000000000..7240ea7ac31c62b66b4ef2cdcd9790b2f6d2e143
--- /dev/null
+++ b/app/migrations/0004_like.py
@@ -0,0 +1,22 @@
+# Generated by Django 3.0.3 on 2020-05-12 08:34
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('app', '0003_auto_20200509_2108'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Like',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('timestamp', models.DateTimeField(auto_now_add=True)),
+                ('materi', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='app.Materi')),
+            ],
+        ),
+    ]
diff --git a/app/migrations/0005_like_session_id.py b/app/migrations/0005_like_session_id.py
new file mode 100644
index 0000000000000000000000000000000000000000..8520a4d3769e9bf68d9ed2fad52454391df55777
--- /dev/null
+++ b/app/migrations/0005_like_session_id.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.0.3 on 2020-05-12 09:24
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('app', '0004_like'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='like',
+            name='session_id',
+            field=models.CharField(default='', max_length=32),
+            preserve_default=False,
+        ),
+    ]
diff --git a/app/migrations/0006_downloadstatistics_viewstatistics.py b/app/migrations/0006_downloadstatistics_viewstatistics.py
new file mode 100644
index 0000000000000000000000000000000000000000..2b29fb125a53831e97d5888d6d878894dcd580d3
--- /dev/null
+++ b/app/migrations/0006_downloadstatistics_viewstatistics.py
@@ -0,0 +1,30 @@
+# Generated by Django 3.0.3 on 2020-05-13 10:34
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('app', '0005_like_session_id'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='ViewStatistics',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('timestamp', models.DateTimeField(auto_now_add=True)),
+                ('materi', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='baca', to='app.Materi')),
+            ],
+        ),
+        migrations.CreateModel(
+            name='DownloadStatistics',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('timestamp', models.DateTimeField(auto_now_add=True)),
+                ('materi', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='unduh', to='app.Materi')),
+            ],
+        ),
+    ]
diff --git a/app/migrations/0007_auto_20200516_1743.py b/app/migrations/0007_auto_20200516_1743.py
new file mode 100644
index 0000000000000000000000000000000000000000..5a0973432393117a5aa0435217f0244c49a9cfe3
--- /dev/null
+++ b/app/migrations/0007_auto_20200516_1743.py
@@ -0,0 +1,43 @@
+# Generated by Django 3.0.3 on 2020-05-16 10:43
+
+from django.db import migrations, models
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('app', '0006_downloadstatistics_viewstatistics'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='materi',
+            name='date_added',
+        ),
+        migrations.AddField(
+            model_name='materi',
+            name='date_created',
+            field=models.DateTimeField(default=django.utils.timezone.now),
+        ),
+        migrations.AddField(
+            model_name='materi',
+            name='date_modified',
+            field=models.DateTimeField(auto_now=True),
+        ),
+        migrations.AlterField(
+            model_name='downloadstatistics',
+            name='timestamp',
+            field=models.DateTimeField(default=django.utils.timezone.now),
+        ),
+        migrations.AlterField(
+            model_name='like',
+            name='timestamp',
+            field=models.DateTimeField(default=django.utils.timezone.now),
+        ),
+        migrations.AlterField(
+            model_name='viewstatistics',
+            name='timestamp',
+            field=models.DateTimeField(default=django.utils.timezone.now),
+        ),
+    ]
diff --git a/app/migrations/0008_auto_20200518_1919.py b/app/migrations/0008_auto_20200518_1919.py
new file mode 100644
index 0000000000000000000000000000000000000000..df20b16663a25a3d064ff3f30b01012f1ecf150c
--- /dev/null
+++ b/app/migrations/0008_auto_20200518_1919.py
@@ -0,0 +1,48 @@
+# Generated by Django 3.0.3 on 2020-05-18 12:19
+
+from django.db import migrations, models
+import django.db.models.deletion
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('app', '0007_auto_20200516_1743'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='comment',
+            name='timestamp',
+            field=models.DateTimeField(default=django.utils.timezone.now),
+        ),
+        migrations.CreateModel(
+            name='DummyViewStatistics',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app.ViewStatistics')),
+            ],
+        ),
+        migrations.CreateModel(
+            name='DummyLike',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app.Like')),
+            ],
+        ),
+        migrations.CreateModel(
+            name='DummyDownloadStatistics',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app.DownloadStatistics')),
+            ],
+        ),
+        migrations.CreateModel(
+            name='DummyComment',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app.Comment')),
+            ],
+        ),
+    ]
diff --git a/app/migrations/0009_auto_20200518_2245.py b/app/migrations/0009_auto_20200518_2245.py
new file mode 100644
index 0000000000000000000000000000000000000000..68785da21a33971eced0e5cf01c37c9e350a56d9
--- /dev/null
+++ b/app/migrations/0009_auto_20200518_2245.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.0.3 on 2020-05-18 15:45
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('app', '0008_auto_20200518_1919'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='comment',
+            name='comment',
+            field=models.CharField(default='comments', max_length=240),
+        ),
+    ]
diff --git a/app/migrations/0010_category_archived.py b/app/migrations/0010_category_archived.py
new file mode 100644
index 0000000000000000000000000000000000000000..a864e59965a382bdc242de2970ab9cc7b76de822
--- /dev/null
+++ b/app/migrations/0010_category_archived.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.0.3 on 2020-06-03 06:48
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('app', '0009_auto_20200518_2245'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='category',
+            name='archived',
+            field=models.BooleanField(default=False),
+        ),
+    ]
diff --git a/app/migrations/0011_auto_20200603_1350.py b/app/migrations/0011_auto_20200603_1350.py
new file mode 100644
index 0000000000000000000000000000000000000000..14c08847378c0a4a310c77303a176bd5182ba90b
--- /dev/null
+++ b/app/migrations/0011_auto_20200603_1350.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.0.3 on 2020-06-03 06:50
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('app', '0010_category_archived'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='category',
+            name='description',
+            field=models.TextField(default=''),
+        ),
+    ]
diff --git a/app/migrations/0012_category_archived_by.py b/app/migrations/0012_category_archived_by.py
new file mode 100644
index 0000000000000000000000000000000000000000..9919bf0538e111bef9794eeb7ab32517e3cb65e7
--- /dev/null
+++ b/app/migrations/0012_category_archived_by.py
@@ -0,0 +1,21 @@
+# Generated by Django 3.0.3 on 2020-06-04 00:09
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+        ('app', '0011_auto_20200603_1350'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='category',
+            name='archived_by',
+            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
+        ),
+    ]
diff --git a/app/migrations/0013_auto_20200919_2055.py b/app/migrations/0013_auto_20200919_2055.py
new file mode 100644
index 0000000000000000000000000000000000000000..7b7993c96f79f86abbf68a24f2c520e98ad3882a
--- /dev/null
+++ b/app/migrations/0013_auto_20200919_2055.py
@@ -0,0 +1,33 @@
+# Generated by Django 3.0.3 on 2020-09-19 13:55
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('app', '0012_category_archived_by'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='materi',
+            name='author',
+            field=models.CharField(default='Penyusun', max_length=30),
+        ),
+        migrations.AlterField(
+            model_name='materi',
+            name='descriptions',
+            field=models.TextField(default='Deskripsi'),
+        ),
+        migrations.AlterField(
+            model_name='materi',
+            name='publisher',
+            field=models.CharField(default='Penerbit', max_length=30),
+        ),
+        migrations.AlterField(
+            model_name='materi',
+            name='title',
+            field=models.CharField(default='Judul', max_length=50),
+        ),
+    ]
diff --git a/app/migrations/0014_rating.py b/app/migrations/0014_rating.py
new file mode 100644
index 0000000000000000000000000000000000000000..69ae6aa1e7dcd3345443a22672118f591ef8e680
--- /dev/null
+++ b/app/migrations/0014_rating.py
@@ -0,0 +1,30 @@
+# Generated by Django 3.0.3 on 2020-09-29 11:30
+
+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),
+        ('app', '0013_auto_20200919_2055'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Rating',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
+                ('score', models.IntegerField()),
+                ('materi', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app.Materi')),
+                ('user', models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+            ],
+            options={
+                'unique_together': {('materi', 'user')},
+            },
+        ),
+    ]
diff --git a/app/migrations/0015_downloadstatistics_downloader.py b/app/migrations/0015_downloadstatistics_downloader.py
new file mode 100644
index 0000000000000000000000000000000000000000..16780d0c070064f852acf2e180dfcb1ba5179afc
--- /dev/null
+++ b/app/migrations/0015_downloadstatistics_downloader.py
@@ -0,0 +1,21 @@
+# Generated by Django 3.0.4 on 2020-09-30 04:50
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+        ('app', '0014_rating'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='downloadstatistics',
+            name='downloader',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='riwayat_unduh', to=settings.AUTH_USER_MODEL),
+        ),
+    ]
diff --git a/app/migrations/0015_reqmaterial.py b/app/migrations/0015_reqmaterial.py
new file mode 100644
index 0000000000000000000000000000000000000000..197e5a18d1dbb8cc0daf3436660d9667ee421939
--- /dev/null
+++ b/app/migrations/0015_reqmaterial.py
@@ -0,0 +1,22 @@
+# Generated by Django 3.0.3 on 2020-10-01 04:23
+
+from django.db import migrations, models
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('app', '0014_rating'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='ReqMaterial',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('title', models.CharField(max_length=100)),
+                ('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
+            ],
+        ),
+    ]
diff --git a/app/migrations/0016_ratingcontributor.py b/app/migrations/0016_ratingcontributor.py
new file mode 100644
index 0000000000000000000000000000000000000000..86d787f0b6a357456c259f9842dfd7e3b7e49415
--- /dev/null
+++ b/app/migrations/0016_ratingcontributor.py
@@ -0,0 +1,25 @@
+# Generated by Django 3.1.1 on 2020-10-05 14:41
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+        ('app', '0015_reqmaterial'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='RatingContributor',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('timestamp', models.DateTimeField(auto_now=True)),
+                ('score', models.IntegerField()),
+                ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+            ],
+        ),
+    ]
diff --git a/app/migrations/0017_auto_20201005_2145.py b/app/migrations/0017_auto_20201005_2145.py
new file mode 100644
index 0000000000000000000000000000000000000000..732caef72a1b44acef70e15c4d29b91a5df106b2
--- /dev/null
+++ b/app/migrations/0017_auto_20201005_2145.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.1.1 on 2020-10-05 14:45
+
+import django.core.validators
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('app', '0016_ratingcontributor'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='ratingcontributor',
+            name='score',
+            field=models.PositiveIntegerField(validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(5)]),
+        ),
+    ]
diff --git a/app/migrations/0018_merge_20201009_0700.py b/app/migrations/0018_merge_20201009_0700.py
new file mode 100644
index 0000000000000000000000000000000000000000..2e5d56480fa1f304956819f4012e5e52c2100d5e
--- /dev/null
+++ b/app/migrations/0018_merge_20201009_0700.py
@@ -0,0 +1,14 @@
+# Generated by Django 3.1 on 2020-10-09 00:00
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('app', '0017_auto_20201005_2145'),
+        ('app', '0015_downloadstatistics_downloader'),
+    ]
+
+    operations = [
+    ]
diff --git a/app/migrations/0019_auto_20201009_1829.py b/app/migrations/0019_auto_20201009_1829.py
new file mode 100644
index 0000000000000000000000000000000000000000..15bec11ed71a0b3062e68aeceda2e7434ec804e8
--- /dev/null
+++ b/app/migrations/0019_auto_20201009_1829.py
@@ -0,0 +1,34 @@
+# Generated by Django 3.1 on 2020-10-09 11:29
+
+from django.conf import settings
+import django.core.validators
+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),
+        ('app', '0018_merge_20201009_0700'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='materi',
+            name='status',
+            field=models.CharField(choices=[('PENDING', 'Diproses'), ('APPROVE', 'Diterima'), ('DISAPPROVE', 'Ditolak'), ('REVISION', 'Perbaikan'), ('BLOCKED', 'Diblokir')], default='PENDING', max_length=30),
+        ),
+        migrations.CreateModel(
+            name='LaporanMateri',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('laporan', models.TextField(default='', validators=[django.core.validators.MinValueValidator(30), django.core.validators.MaxValueValidator(120)])),
+                ('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
+                ('is_rejected', models.BooleanField(default=False)),
+                ('materi', models.ForeignKey(max_length=120, on_delete=django.db.models.deletion.CASCADE, to='app.materi')),
+                ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+            ],
+        ),
+    ]
diff --git a/app/migrations/0019_materi__search_vector.py b/app/migrations/0019_materi__search_vector.py
new file mode 100644
index 0000000000000000000000000000000000000000..bd148040bd07b733963274efadcb1ad9995396c7
--- /dev/null
+++ b/app/migrations/0019_materi__search_vector.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.1 on 2020-10-09 11:19
+
+import django.contrib.postgres.search
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('app', '0018_merge_20201009_0700'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='materi',
+            name='_search_vector',
+            field=django.contrib.postgres.search.SearchVectorField(editable=False, null=True),
+        ),
+    ]
diff --git a/app/migrations/0019_materi_yt_video_id.py b/app/migrations/0019_materi_yt_video_id.py
new file mode 100644
index 0000000000000000000000000000000000000000..df8dc1afeba6a410f437c1ce8c29de0e0c947346
--- /dev/null
+++ b/app/migrations/0019_materi_yt_video_id.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.1 on 2020-10-09 13:48
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('app', '0018_merge_20201009_0700'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='materi',
+            name='yt_video_id',
+            field=models.CharField(blank=True, max_length=100, null=True),
+        ),
+    ]
diff --git a/app/migrations/0020_merge_20201009_2039.py b/app/migrations/0020_merge_20201009_2039.py
new file mode 100644
index 0000000000000000000000000000000000000000..80867b028075f48fb2cd1b5838561fe9b20aa4cc
--- /dev/null
+++ b/app/migrations/0020_merge_20201009_2039.py
@@ -0,0 +1,14 @@
+# Generated by Django 3.1 on 2020-10-09 13:39
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('app', '0019_materi__search_vector'),
+        ('app', '0019_auto_20201009_1829'),
+    ]
+
+    operations = [
+    ]
diff --git a/app/migrations/0021_dislikecomment_likecomment.py b/app/migrations/0021_dislikecomment_likecomment.py
new file mode 100644
index 0000000000000000000000000000000000000000..1ce9111268da53f8e2a88fdf877c4250fb354695
--- /dev/null
+++ b/app/migrations/0021_dislikecomment_likecomment.py
@@ -0,0 +1,33 @@
+# Generated by Django 3.1 on 2020-10-09 16:19
+
+from django.db import migrations, models
+import django.db.models.deletion
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('app', '0020_merge_20201009_2039'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='LikeComment',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
+                ('session_id', models.CharField(max_length=32)),
+                ('comment', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='app.comment')),
+            ],
+        ),
+        migrations.CreateModel(
+            name='DislikeComment',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
+                ('session_id', models.CharField(max_length=32)),
+                ('comment', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='app.comment')),
+            ],
+        ),
+    ]
diff --git a/app/migrations/0021_materi_release_year.py b/app/migrations/0021_materi_release_year.py
new file mode 100644
index 0000000000000000000000000000000000000000..8294e44629dc026ddff721b329e610946de3a7d5
--- /dev/null
+++ b/app/migrations/0021_materi_release_year.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.1 on 2020-10-09 16:13
+
+import app.models
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('app', '0020_merge_20201009_2039'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='materi',
+            name='release_year',
+            field=models.IntegerField(default=app.models.current_year),
+        ),
+    ]
diff --git a/app/migrations/0022_merge_20201011_1122.py b/app/migrations/0022_merge_20201011_1122.py
new file mode 100644
index 0000000000000000000000000000000000000000..4b0d5ebf263822713c41cced80792494eb749a21
--- /dev/null
+++ b/app/migrations/0022_merge_20201011_1122.py
@@ -0,0 +1,14 @@
+# Generated by Django 3.1 on 2020-10-11 04:22
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('app', '0021_dislikecomment_likecomment'),
+        ('app', '0021_materi_release_year'),
+    ]
+
+    operations = [
+    ]
diff --git a/app/migrations/0023_materi_deleted_at.py b/app/migrations/0023_materi_deleted_at.py
new file mode 100644
index 0000000000000000000000000000000000000000..2a695fcfe8cfa105ee5b2b04ba7b163460267b26
--- /dev/null
+++ b/app/migrations/0023_materi_deleted_at.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.1 on 2020-10-23 03:23
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('app', '0022_merge_20201011_1122'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='materi',
+            name='deleted_at',
+            field=models.DateTimeField(blank=True, null=True),
+        ),
+    ]
diff --git a/app/migrations/0023_merge_20201016_1713.py b/app/migrations/0023_merge_20201016_1713.py
new file mode 100644
index 0000000000000000000000000000000000000000..ecb8c7929320e2599b38912d405bce12532e23a5
--- /dev/null
+++ b/app/migrations/0023_merge_20201016_1713.py
@@ -0,0 +1,14 @@
+# Generated by Django 3.1 on 2020-10-16 10:13
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('app', '0022_merge_20201011_1122'),
+        ('app', '0019_materi_yt_video_id'),
+    ]
+
+    operations = [
+    ]
diff --git a/app/migrations/0024_merge_20201026_0812.py b/app/migrations/0024_merge_20201026_0812.py
new file mode 100644
index 0000000000000000000000000000000000000000..adc2f2f6bb36bb959b15608d753516fed53bf5df
--- /dev/null
+++ b/app/migrations/0024_merge_20201026_0812.py
@@ -0,0 +1,14 @@
+# Generated by Django 3.1 on 2020-10-26 01:12
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('app', '0023_merge_20201016_1713'),
+        ('app', '0023_materi_deleted_at'),
+    ]
+
+    operations = [
+    ]
diff --git a/app/migrations/0025_review.py b/app/migrations/0025_review.py
new file mode 100644
index 0000000000000000000000000000000000000000..79b7b89a4f655cf6851c7265539222047eef56e1
--- /dev/null
+++ b/app/migrations/0025_review.py
@@ -0,0 +1,30 @@
+# Generated by Django 3.1 on 2020-10-29 11:22
+
+import app.models
+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),
+        ('app', '0024_merge_20201026_0812'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Review',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('username', models.CharField(max_length=100)),
+                ('profile', models.CharField(default=app.models.getRandomColor, max_length=100)),
+                ('review', models.TextField(default='review')),
+                ('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
+                ('materi', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='app.materi')),
+                ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
+            ],
+        ),
+    ]
diff --git a/app/migrations/0026_submitvisitor.py b/app/migrations/0026_submitvisitor.py
new file mode 100644
index 0000000000000000000000000000000000000000..b8497c75b257983dd84ea6b3cbc8b5228f6cd29d
--- /dev/null
+++ b/app/migrations/0026_submitvisitor.py
@@ -0,0 +1,24 @@
+# Generated by Django 3.1 on 2020-10-29 13:45
+
+from django.db import migrations, models
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('app', '0025_review'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='SubmitVisitor',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('user_id', models.CharField(max_length=50)),
+                ('email', models.CharField(max_length=50)),
+                ('msg', models.CharField(max_length=100)),
+                ('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
+            ],
+        ),
+    ]
diff --git a/app/models.py b/app/models.py
index 661cde6be8d78d8b5d785ab31b34c8764c7ecd18..e531ad121c188ab50d73c93dfbedd3eafb464389 100644
--- a/app/models.py
+++ b/app/models.py
@@ -47,7 +47,7 @@ class MateriManager(models.Manager):
         if self.alive_only:
             return SoftDeletionQuerySet(self.model).filter(deleted_at=None)
         return SoftDeletionQuerySet(self.model)
-
+        
     def search(self, search_text):
         search_vector = search.SearchVector("title", weight="A")
         search_query = search.SearchQuery(search_text)
@@ -68,10 +68,10 @@ class SoftDeleteModel(models.Model):
     deleted_at = models.DateTimeField(blank=True, null=True)
 
     all_objects = MateriManager(alive_only=False)
-
+    
     class Meta:
         abstract = True
-
+    
     def soft_delete(self):
         self.deleted_at = timezone.now()
         self.save()
@@ -85,7 +85,7 @@ class Materi(SoftDeleteModel):
     publisher = models.CharField(max_length=30, default="Penerbit")
     release_year = models.IntegerField(default=current_year)
     pages = models.IntegerField(default=0)
-    descriptions = models.TextField(default="Deskripsi")
+    descriptions = models.TextField(default="Deskripsi")    
     status = models.CharField(max_length=30, choices=VERIFICATION_STATUS, default=VERIFICATION_STATUS[0][0])
     categories = models.ManyToManyField(Category)
     date_created = models.DateTimeField(default=timezone.now)
@@ -124,7 +124,7 @@ class Materi(SoftDeleteModel):
     def like_count(self):
         count = Like.objects.filter(materi=self).count()
         return count
-
+    
     @property
     def comment_count(self):
         count = Comment.objects.filter(materi=self).count()
@@ -157,7 +157,7 @@ class Comment(models.Model):
     def like_count(self):
         count = LikeComment.objects.filter(comment=self).count()
         return count
-
+    
     @property
     def dislike_count(self):
         count = DislikeComment.objects.filter(comment=self).count()
@@ -265,19 +265,6 @@ class RatingContributor(models.Model):
     class Meta:
         unique_together = ["contributor", "user"]
 
-class SubscribeModel(models.Model):
-    sys_id = models.AutoField(primary_key=True, null=False, blank=True)
-    email = models.EmailField(null=False, blank=True, max_length=200, unique=True)
-    status = models.CharField(max_length=64, null=False, blank=True)
-    created_date = models.DateTimeField(null=False, blank=True)
-    updated_date = models.DateTimeField(null=False, blank=True)
-
-    class Meta:
-        app_label = "app"
-        db_table = "app_subscribe"
-
-    def __str__(self):
-        return self.email
 
 class LaporanMateri(models.Model):
     materi = models.ForeignKey(Materi, on_delete=models.CASCADE, max_length=120)
diff --git a/app/static/images/sub-btn.png b/app/static/images/sub-btn.png
deleted file mode 100644
index 81b0489c7c988c9769980e0bca8698a24cc3851d..0000000000000000000000000000000000000000
Binary files a/app/static/images/sub-btn.png and /dev/null differ
diff --git a/app/templates/app/emails/subscription.html b/app/templates/app/emails/subscription.html
deleted file mode 100644
index 6a83c2d0a33ee439882c3b3008ce091db597ee62..0000000000000000000000000000000000000000
--- a/app/templates/app/emails/subscription.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<div style="padding: 20px; background: #fafafa;font-size:15px;">
-    Hi<br>
-    Thanks for subscribing to {{ project_name }} newsletter.<br>
-    We will be sending you latest published articles on <a href="{{ site_url }}">{{ site_url }}</a>. Mail frequency won't be more than twice a month.<br>
-    We hate spamming as much as you do.<br>
-    <br>
-    To confirm your subscription, please click on the link given below. If clicking doesn't work, copy paste the URL in browser.<br>
-    If you think this is a mistake, just ignore this email and we won't bother you again.
-    <br>
-    <br>
-    <a href="{{ confirmation_url }}">{{ confirmation_url }}</a>
-
-    <br>
-    <br>
-    <p>
-        Note:<br>
-        This is notification only email. Please do not reply on this email.<br>
-        You can <a href="{{ contact_us_url }}">contact us here</a>.
-    </p>
-</div>
\ No newline at end of file
diff --git a/app/templates/app/katalog_materi.html b/app/templates/app/katalog_materi.html
index 93c719b560ad93d582913d20205b0d125f799565..224232c1a609e82a1004dd0183bd6ac83059cd48 100644
--- a/app/templates/app/katalog_materi.html
+++ b/app/templates/app/katalog_materi.html
@@ -48,7 +48,7 @@
 </head>
 
 <body style="background-color: #f8f8f8;">
-
+    
 
 <!-- Page Content -->
     <div class="container">
@@ -76,14 +76,14 @@
                 </div>
             </div>
         </header>
-
+        
         <a href="/download-history/" class="btn-history">Riwayat Unduh</a><br><br>
 
         <div id="container-materi-ordering">
             <a href="?random=1" class="btn-materi-ordering">Acak Materi</a><br><br>
             <a href="?recommendation=1" class="btn-materi-ordering">Rekomendasi</a><br><br>
         </div>
-
+		
         <div class="container">
             <div class="row content">
                 <div class="col-3 sidebar">
@@ -209,4 +209,4 @@
 
 </html>
 
-{% endblock %}
+{% endblock %}
\ No newline at end of file
diff --git a/app/templates/subscribe.html b/app/templates/subscribe.html
deleted file mode 100644
index 566776b36cbc0b63a6e9c57cd980f7a8220b6cec..0000000000000000000000000000000000000000
--- a/app/templates/subscribe.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<div style="border: 1px solid darkgreen; border-radius: 2px; padding:10px; text-align: center;">
-    <div><strong>SUBSCRIBE</strong></div>
-    <div style="margin-bottom: 10px;">Please subscribe to get the latest articles in your mailbox.</div>
-    <div>
-        <form action="{% url 'subscribe' %}" method="post" class="form-horizontal">
-            {% csrf_token %}
-            <input type="email" name="email" class="form-control" placeholder="Your Email ID Please" required>
-            <br>
-            <input type="submit" value="Subscribe" class="btn btn-primary btn-sm">
-        </form>
-    </div>
-</div>
\ No newline at end of file
diff --git a/app/tests.py b/app/tests.py
index 2a0a6e069a9d9297915b0907ee1b1b932c5b6e6a..9f10c73f27f528bd814fb834b1084391f60514d9 100644
--- a/app/tests.py
+++ b/app/tests.py
@@ -67,9 +67,6 @@ from .views import (
 )
 from app.forms import SuntingProfilForm, year_choices
 from app.utils.fileManagementUtil import get_random_filename, remove_image_exifdata
-import pandas as pd
-from django.core import mail
-from app.utils.email_utility import send_gmail
 from app.utils.PasswordValidator import PasswordPolicyValidator
 
 ERROR_403_MESSAGE = "Kamu harus login untuk mengakses halaman ini"
@@ -229,7 +226,7 @@ class DaftarKatalogSortingByJumlahTampilanTest(TestCase):
         self.client.get(self.url)
         response = self.client.get("/?sort=jumlah_tampilan")
         self.assertRegex(str(response.content), rf'.*Materi 2.*Materi 1.*')
-
+    
 class DaftarKatalogPerKontributorTest(TestCase):
     def setUp(self):
         self.client = Client()
@@ -325,13 +322,13 @@ class DetailMateriTest(TestCase):
             "ExampleCover921.jpg", b"Test file")
         self.content = SimpleUploadedFile("ExampleFile921.pdf", b"Test file")
 
-        self.materi1 = Materi.objects.create(title="Materi 1", author="Agas",
-                        uploader=self.contributor, publisher="Kelas SC",
-                        descriptions="Deskripsi Materi 1", status="APPROVE",
+        self.materi1 = Materi.objects.create(title="Materi 1", author="Agas", 
+                        uploader=self.contributor, publisher="Kelas SC", 
+                        descriptions="Deskripsi Materi 1", status="APPROVE", 
                         cover=self.cover, content=self.content)
-        self.materi2 = Materi.objects.create(title="Materi 2", author="Agad",
-                        uploader=self.contributor, publisher="Kelas SM",
-                        descriptions="Deskripsi Materi 2", status="APPROVE",
+        self.materi2 = Materi.objects.create(title="Materi 2", author="Agad", 
+                        uploader=self.contributor, publisher="Kelas SM", 
+                        descriptions="Deskripsi Materi 2", status="APPROVE", 
                         cover=self.cover, content=self.content)
         self.url = "/materi/" + str(self.materi1.id) + "/"
         self.download_url1 = self.url + "unduh"
@@ -459,10 +456,10 @@ class DetailMateriTest(TestCase):
         comment = Comment.objects.get(comment="This is new comment by Anonymous")
         response = self.client.get(url_materi)
         session_id = response.context["session_id"]
-
+        
         payload = {"comment": comment, "session_id": session_id}
         self.client.post("/comment/dislike/", payload)
-
+        
         self.client.post("/comment/dislike/", payload)
         num_of_comment_dislikes = DislikeComment.objects.filter(comment=comment, session_id=session_id).count()
         self.assertEqual(num_of_comment_dislikes, 0)
@@ -476,10 +473,10 @@ class DetailMateriTest(TestCase):
         comment = Comment.objects.get(comment="This is new comment by Anonymous")
         response = self.client.get(url_materi)
         session_id = response.context["session_id"]
-
+        
         payload = {"comment": comment, "session_id": session_id}
         self.client.post("/comment/like/", payload)
-
+        
         self.client.post("/comment/like/", payload)
         num_of_comment_likes = LikeComment.objects.filter(comment=comment, session_id=session_id).count()
         self.assertEqual(num_of_comment_likes, 0)
@@ -519,9 +516,9 @@ class DetailMateriTest(TestCase):
             is_subscribing_to_material_comments=True
         )
 
-        material = Materi.objects.create(title="Materi-subscribed", author="Tester",
-                                uploader=contributor_subscribed, publisher="Kelas PMPL",
-                                descriptions="Deskripsi Materi subscribed", status="APPROVE",
+        material = Materi.objects.create(title="Materi-subscribed", author="Tester", 
+                                uploader=contributor_subscribed, publisher="Kelas PMPL", 
+                                descriptions="Deskripsi Materi subscribed", status="APPROVE", 
                                 cover=self.cover, content=self.content)
         url = "/materi/" + str(material.id) + "/"
         self.client.login(**self.contributor_credential) # comment with other user
@@ -546,9 +543,9 @@ class DetailMateriTest(TestCase):
             is_subscribing_to_material_comments=False
         )
 
-        material = Materi.objects.create(title="Materi-not-subscribed", author="Tester",
-                                uploader=contributor_not_subscribed, publisher="Kelas PMPL",
-                                descriptions="Deskripsi Materi non-subscribed", status="APPROVE",
+        material = Materi.objects.create(title="Materi-not-subscribed", author="Tester", 
+                                uploader=contributor_not_subscribed, publisher="Kelas PMPL", 
+                                descriptions="Deskripsi Materi non-subscribed", status="APPROVE", 
                                 cover=self.cover, content=self.content)
         url = "/materi/" + str(material.id) + "/"
         self.client.login(**self.contributor_credential) # comment with other user
@@ -576,9 +573,9 @@ class DetailMateriTest(TestCase):
             is_subscribing_to_material_comments=True
         )
 
-        material = Materi.objects.create(title="Materi-subscribed", author="Tester",
-                                uploader=contributor_subscribed, publisher="Kelas PMPL",
-                                descriptions="Deskripsi Materi subscribed", status="APPROVE",
+        material = Materi.objects.create(title="Materi-subscribed", author="Tester", 
+                                uploader=contributor_subscribed, publisher="Kelas PMPL", 
+                                descriptions="Deskripsi Materi subscribed", status="APPROVE", 
                                 cover=self.cover, content=self.content)
         url = "/materi/" + str(material.id) + "/"
         self.client.login(**contributor_subscribed_credentials) # comment with the same user
@@ -656,7 +653,7 @@ class DetailMateriTest(TestCase):
         count = Comment.objects.all().filter(comment="This is new comment by Anonymous").count()
         self.assertEqual(count, 1)
 
-
+    
     def test_review_models_can_create_new_object(self):
         test = Review.objects.create(
             username="saul", profile="121212", review="232323")
@@ -703,7 +700,7 @@ class DetailMateriTest(TestCase):
         self.client.post(url, {"review": "This is new review by Anonymous"})
         response = self.client.get(url)
         self.assertContains(response, "Anonymous")
-
+    
     def test_detail_materi_contains_review_count(self):
         url = self.url
         self.client.login(**self.contributor_credential)
@@ -734,25 +731,25 @@ class DetailMateriTest(TestCase):
 
     def test_hasil_citasi_APA_materi_has_no_published_date(self):
         response = self.client.get(self.url)
-        expected = self.materi1.author + " . (n.d) . " + self.materi1.title + " . " + self.materi1.publisher
+        expected = self.materi1.author + " . (n.d) . " + self.materi1.title + " . " + self.materi1.publisher	
         self.assertIn(expected, response.context["citationAPA"])
         self.assertIn(expected,
                       response.context["citationAPA"])
 
     def test_hasil_citasi_APA_materi_has_published_date(self):
         response = self.client.get(self.materi_with_published_date_url)
-        published_date = self.materi_with_published_date.published_date.strftime("%Y-%m-%d %H:%M")
-        expected = (
-            self.materi_with_published_date.author
-            + " . ("
-            + published_date
-            + ") . "
-            + self.materi_with_published_date.title
-            + " . "
-            + self.materi_with_published_date.publisher
-        )
+        published_date = self.materi_with_published_date.published_date.strftime("%Y-%m-%d %H:%M")	
+        expected = (	
+            self.materi_with_published_date.author	
+            + " . ("	
+            + published_date	
+            + ") . "	
+            + self.materi_with_published_date.title	
+            + " . "	
+            + self.materi_with_published_date.publisher	
+        )	
         self.assertIn(expected, response.context["citationAPA"])
-
+    
     def test_citation_IEEE_button(self):
         response = self.client.get(self.url)
         self.assertContains(response, "Citate IEEE")
@@ -764,19 +761,19 @@ class DetailMateriTest(TestCase):
         current_month = current_date.strftime("%b")
         current_year = str(current_date.year)
 
-        expected = (
-            "Agas, "
-            + "Materi 1. "
-            + "Kelas SC, n.d. "
-            + "Accessed on: "
-            + current_month
-            + ". "
-            + current_day
-            + ", "
-            + current_year
-            + ". [Online]. "
-            + "Available: http://testserver"
-            + self.url
+        expected = (	
+            "Agas, "	
+            + "Materi 1. "	
+            + "Kelas SC, n.d. "	
+            + "Accessed on: "	
+            + current_month	
+            + ". "	
+            + current_day	
+            + ", "	
+            + current_year	
+            + ". [Online]. "	
+            + "Available: http://testserver"	
+            + self.url	
         )
         self.assertIn(expected, response.context["citationIEEE"])
 
@@ -859,7 +856,7 @@ class DetailMateriTest(TestCase):
         self.assertNotEqual(context1['materi_download_count'], context2['materi_download_count'])
         self.assertEqual(context1['materi_download_count'], 3)
         self.assertEqual(context2['materi_download_count'], 2)
-
+    
     def test_download_count_displayed_on_template_when_no_download(self):
         response = self.client.get(self.url)
         html = response.content.decode("utf-8")
@@ -904,12 +901,12 @@ class DetailMateriTest(TestCase):
         self.check_materi_info_not_in_html(self.dcount_info_name, dcount_materi2, html)
         self.check_materi_info_in_html(self.dcount_info_name, dcount_materi2, html2)
         self.check_materi_info_not_in_html(self.dcount_info_name, dcount_materi1, html2)
-
+    
     def test_like_count_displayed_on_template_when_no_like(self):
         response = self.client.get(self.url)
         html = response.content.decode("utf-8")
         self.check_materi_info_in_html(self.lcount_info_name, 0, html)
-
+    
     def test_like_count_displayed_on_template_when_single_like(self):
         payload = {
             'materi_id': self.materi1.id,
@@ -919,8 +916,8 @@ class DetailMateriTest(TestCase):
 
         response = self.client.get(self.url)
         html = response.content.decode("utf-8")
-        self.check_materi_info_in_html(self.lcount_info_name, 1, html)
-
+        self.check_materi_info_in_html(self.lcount_info_name, 1, html)        
+        
     def test_like_count_displayed_on_template_when_multiple_like(self):
         payload1 = {
             'materi_id': self.materi1.id,
@@ -932,17 +929,17 @@ class DetailMateriTest(TestCase):
         }
         self.client.post(self.like_url, payload1)
         self.client.post(self.like_url, payload2)
-
+        
         response = self.client.get(self.url)
         html = response.content.decode("utf-8")
         self.check_materi_info_in_html(self.lcount_info_name, 2, html)
-
+    
     def test_like_count_displayed_on_template_when_unlike(self):
         payload = {
             'materi_id': self.materi1.id,
             'session_id': "dummysession"
         }
-
+        
         # Like materi once
         self.client.post(self.like_url, payload)
         response = self.client.get(self.url)
@@ -984,11 +981,11 @@ class PostsViewTest(TestCase):
 
             for j in range (LIKES_COUNT_PER_POST[i]):
                 Like.objects.create(
-                    timestamp=datetime.now(),
-                    materi=post,
+                    timestamp=datetime.now(), 
+                    materi=post, 
                     session_id=("dummysession-" + str(i) + '-' + str(j))
                 )
-
+            
         for i, post_id in enumerate(post_comment_group_dict):
             post = post_comment_group_dict[post_id]["data"]
 
@@ -1130,13 +1127,13 @@ class UploadPageTest(TestCase):
         response = Client().get("/fake/")
         self.assertEqual(response.status_code, 404)
 
-    def test_upload_page_url_admin_doesnt_exist(self):
+    def test_upload_page_url_admin_doesnt_exist(self):        
         self.client.login(email="admin@gov.id",
                           password="admin")
         response = self.client.get("/unggah/")
         self.assertEqual(response.status_code, 403)
 
-    def test_upload_page_url_admin_cant_upload(self):
+    def test_upload_page_url_admin_cant_upload(self):        
         self.client.login(email="admin@gov.id",
                           password="admin")
         response = self.client.post("/unggah/")
@@ -1274,7 +1271,7 @@ class UploadExcelPageTest(TestCase):
 
         with open(file_name, 'rb') as fp:
             response = self.client.post("/unggah_excel/", {'excel': fp})
-
+        
         messages = list(dj_messages.get_messages(response.wsgi_request))
         msg_text = messages[0].message
 
@@ -1292,7 +1289,7 @@ class UploadExcelPageTest(TestCase):
 
         with open(file_name, 'rb') as fp:
             response = self.client.post("/unggah_excel/", {'excel': fp})
-
+        
         messages = list(dj_messages.get_messages(response.wsgi_request))
         msg_text = messages[0].message
 
@@ -1311,7 +1308,7 @@ class UploadExcelPageTest(TestCase):
 
         with open(file_name, 'rb') as fp:
             response = self.client.post("/unggah_excel/", {'excel': fp})
-
+        
         messages = list(dj_messages.get_messages(response.wsgi_request))
         msg_text = messages[0].message
 
@@ -1330,7 +1327,7 @@ class UploadExcelPageTest(TestCase):
 
         with open(file_name, 'rb') as fp:
             response = self.client.post("/unggah_excel/", {'excel': fp})
-
+        
         messages = list(dj_messages.get_messages(response.wsgi_request))
         msg_text = messages[0].message
 
@@ -1351,12 +1348,12 @@ class UploadExcelPageTest(TestCase):
         }
 
         categories = ['Computer Science','Machine Learning','Deep Learning']
-
+        
         file_name, data_frame = self.create_dummy_excel(field_lengths=field_lengths, categories=categories)
 
         with open(file_name, 'rb') as fp:
             self.client.post("/unggah_excel/", {'excel': fp})
-
+        
         title = data_frame['Title'][0]
         materi = Materi.objects.get(title=title)
         default_path = 'book-cover-placeholder.png'
@@ -1370,11 +1367,11 @@ class UploadExcelPageTest(TestCase):
                           password="kontributor")
 
         response = self.client.get("/unggah_excel/?template=1")
-
+        
         self.assertEquals(response['Content-Type'],'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
         self.assertEquals(response['Content-Disposition'],'attachment; filename=template.xlsx')
 
-
+        
 
 
 
@@ -1481,14 +1478,14 @@ class DeleteMateriTest(TestCase):
         self.client.login(**self.contributor_credential)
         response = self.client.get(self.url)
         self.assertEqual(response.status_code, 302)
-
+    
     def test_url_soft_delete_materi_is_success_as_admin(self):
         self.client.login(**self.admin_credential)
         response = self.client.get(self.url)
-        self.assertEqual(response.status_code, 302)
+        self.assertEqual(response.status_code, 302) 
         self.materi1.refresh_from_db()
         self.assertNotEqual(self.materi1.deleted_at, None)
-
+    
     def test_url_soft_delete_materi_is_success_as_superuser(self):
         self.client.login(**self.superuser_credential)
         response = self.client.get(self.url)
@@ -1515,7 +1512,7 @@ class ProfilViewTest(TestCase):
         self.assertEqual(found.func.__name__, self.view.as_view().__name__)
 
     def _request_as_user(self, credentials):
-        self.client = Client()
+        self.client = Client() 
         self.client.login(**credentials)
         return self.client.get(self.url)
 
@@ -1557,7 +1554,7 @@ class SuntingProfilViewTest(TestCase):
         self.assertEqual(found.func.__name__, self.view.as_view().__name__)
 
     def _request_as_user(self, credentials):
-        self.client = Client()
+        self.client = Client() 
         self.client.login(**credentials)
         return self.client.get(self.url)
 
@@ -1938,7 +1935,7 @@ class RevisiMateriTest(TestCase):
         # Logout
         self.client.logout()
 
-
+    
 class GenerateDummyCommandTest(TestCase):
 
     def setUp(self):
@@ -2422,7 +2419,7 @@ class RatingContributorTest(TransactionTestCase):
         response = self.client.get(self.url)
         self.assertContains(response=response, text=f"Rating: {mean(avg)}", count=1)
         self.assertContains(response=response, text=f"oleh: {len(avg)} orang", count=1)
-
+    
     def test_not_authenticated_user_should_not_able_to_add_rating(self):
         response_post = self.client.post(self.url, data={
             "contributor":self.contributor.id,
@@ -2432,11 +2429,11 @@ class RatingContributorTest(TransactionTestCase):
         response_get = self.client.get(self.url)
         self.assertEqual(response_post.status_code, 403)
         self.assertContains(response_get, "Kamu harus login untuk memberi rating")
-
+    
     def test_not_authenticated_user_should_not_able_to_delete_rating(self):
         response_post = self.client.post(self.url, data={"delete":True})
         self.assertEqual(response_post.status_code, 403)
-
+    
     def test_authenticated_user_should_not_delete_rating_if_has_not_been_rated(self):
         self.client.login(**self.admin_credential)
         self.client.post(self.url, data={
@@ -2444,15 +2441,15 @@ class RatingContributorTest(TransactionTestCase):
             "user":self.admin.id,
             "score":3
         })
-
+        
         self.assertEqual(1, RatingContributor.objects.filter(contributor=self.contributor).count())
         self.client.logout()
 
         self.client.login(**self.anonymous_credential)
         self.client.post(self.url, data={"delete":True})
-
+        
         self.assertEqual(1, RatingContributor.objects.filter(contributor=self.contributor).count())
-
+    
     def test_authenticated_user_should_delete_rating_if_has_been_rated(self):
         self.client.login(**self.admin_credential)
         self.client.post(self.url, data={
@@ -2470,7 +2467,7 @@ class RatingContributorTest(TransactionTestCase):
         self.assertContains(response, 'Rating: 0')
         self.assertContains(response, 'oleh: 0 orang')
         self.assertEqual(0, RatingContributor.objects.filter(contributor=self.contributor).count())
-
+    
     def test_average_still_be_correct_when_rating_was_deleted(self):
         scores = [2,4]
         self.client.login(**self.admin_credential)
@@ -2495,7 +2492,7 @@ class RatingContributorTest(TransactionTestCase):
         response = self.client.get(self.url)
         self.assertContains(response, f'Rating: {scores[0]}')
         self.assertContains(response, 'oleh: 1 orang')
-
+    
     def test_authenticated_user_should_update_rating_if_has_been_rated(self):
         self.client.login(**self.anonymous_credential)
         self.client.post(self.url, data={
@@ -2511,7 +2508,7 @@ class RatingContributorTest(TransactionTestCase):
         response = self.client.get(self.url)
         self.assertContains(response, 'Rating: 3')
         self.assertContains(response, 'oleh: 1 orang')
-
+    
     def test_authenticated_user_should_not_update_rating_if_has_not_been_rated(self):
         self.client.login(**self.anonymous_credential)
         response = self.client.get(self.url)
@@ -2522,7 +2519,7 @@ class RatingContributorTest(TransactionTestCase):
         response = self.client.get(self.url)
         self.assertContains(response, 'Rating: 0')
         self.assertContains(response, 'oleh: 0 orang')
-
+    
 
 class UserDownloadHistoryTest(TestCase):
     def setUp(self):
@@ -2561,25 +2558,25 @@ class UserDownloadHistoryTest(TestCase):
         self.materi1 = Materi.objects.first()
         self.download_url = f"/materi/{self.materi1.id}/unduh"
         self.history_url = "/download-history/"
-
+	
     def test_multiple_insert_download_statistic_with_user(self):
         DownloadStatistics(materi=self.materi1, downloader=self.user1_anonim).save()
         num_of_downloads = self.user1_anonim.riwayat_unduh.all().count()
         self.assertEqual(num_of_downloads, 1)
-
+		
         DownloadStatistics(materi=self.materi1, downloader=self.user1_anonim).save()
         num_of_downloads = self.user1_anonim.riwayat_unduh.all().count()
         self.assertEqual(num_of_downloads, 2)
-
+		
     def test_download_statistics_bound_to_specific_user(self):
         DownloadStatistics(materi=self.materi1, downloader=self.user1_anonim).save()
         num_of_downloads = self.user1_anonim.riwayat_unduh.all().count()
         self.assertEqual(num_of_downloads, 1)
-
+		
         DownloadStatistics(materi=self.materi1).save()
         num_of_downloads = self.user1_anonim.riwayat_unduh.all().count()
         self.assertEqual(num_of_downloads, 1)
-
+		
         DownloadStatistics(materi=self.materi1, downloader=self.user2_anonim).save()
         user1_num_of_downloads = self.user1_anonim.riwayat_unduh.all().count()
         user2_num_of_downloads = self.user2_anonim.riwayat_unduh.all().count()
@@ -2589,14 +2586,14 @@ class UserDownloadHistoryTest(TestCase):
     def test_registered_user_download(self):
         # Login
         self.client.login(**self.user1_credential)
-
+		
         self.client.get(self.download_url)
         num_of_downloads = self.user1_anonim.riwayat_unduh.all().count()
         self.assertEqual(num_of_downloads, 1)
-
+		
         # Logout
         self.client.logout()
-
+		
     def test_unregistered_user_download(self):
         self.client.get(self.download_url)
         downloaded_materi = self.client.session['downloaded_materi']
@@ -2614,10 +2611,10 @@ class UserDownloadHistoryTest(TestCase):
         self.client.get(self.download_url)
         num_of_downloads = self.user1_anonim.riwayat_unduh.all().count()
         self.assertEqual(num_of_downloads, 2)
-
+		
         # Logout
         self.client.logout()
-
+		
     def test_unregistered_user_multiple_download(self):
         self.client.get(self.download_url)
         downloaded_materi = self.client.session['downloaded_materi']
@@ -2630,27 +2627,27 @@ class UserDownloadHistoryTest(TestCase):
         num_of_downloads = DownloadStatistics.objects.filter(
                             pk__in=downloaded_materi).count()
         self.assertEqual(num_of_downloads, 2)
-
+		
     def test_registered_user_doesnt_use_session_when_download(self):
         # Login
         self.client.login(**self.user1_credential)
-
+		
         self.client.get(self.download_url)
         self.assertFalse('downloaded_materi' in self.client.session)
-
+		
         # Logout
         self.client.logout()
-
+	
     def test_download_history_bound_to_specific_user(self):
         # Login Anonym 1
         self.client.login(**self.user1_credential)
         self.client.get(self.download_url)
         num_of_downloads = self.user1_anonim.riwayat_unduh.all().count()
         self.assertEqual(num_of_downloads, 1)
-
+		
         # Logout Anonym 1
         self.client.logout()
-
+		
 		# Unregistered User download
         self.client.get(self.download_url)
         user1_num_of_downloads = self.user1_anonim.riwayat_unduh.all().count()
@@ -2659,7 +2656,7 @@ class UserDownloadHistoryTest(TestCase):
                             pk__in=downloaded_materi).count()
         self.assertEqual(user1_num_of_downloads, 1)
         self.assertEqual(guest_num_of_downloads, 1)
-
+		
 		# Login Anonym 2
         self.client.login(**self.user2_credential)
         self.client.get(self.download_url)
@@ -2668,7 +2665,7 @@ class UserDownloadHistoryTest(TestCase):
         self.assertEqual(user1_num_of_downloads, 1)
         self.assertEqual(guest_num_of_downloads, 1)
         self.assertEqual(user2_num_of_downloads, 1)
-
+		
         # Logout Anonym 2
         self.client.logout()
 
@@ -2688,42 +2685,42 @@ class DownloadHistoryViewTest(TestCase):
             **self.contributor_credential, name="Kontributor", is_contributor=True
         )
         self.client = Client()
-
+		
         content1 = b"Test file"
         content2 = b"File Test"
-
+		
         self.cover1 = SimpleUploadedFile("cover1.jpg",content1)
         self.content1 = SimpleUploadedFile("content1.txt",content1)
-
+		
         self.cover2 = SimpleUploadedFile("cover2.jpg",content2)
         self.content2 = SimpleUploadedFile("content2.txt",content2)
-
+		
         self.materi1 = Materi.objects.create(title="Materi 1", author="Agas", uploader=self.contributor,
                publisher="Kelas SC", descriptions="Deskripsi Materi 1",
                status="PENDING", cover=self.cover1, content=self.content1)
         self.materi2 = Materi.objects.create(title="Materi 2", author="Danin", uploader=self.contributor,
                publisher="Kelas DDP", descriptions="Deskripsi Materi 2",
                status="PENDING", cover=self.cover2, content=self.content2)
-
+			   
         self.download_url1 = f"/materi/{self.materi1.id}/unduh"
         self.download_url2 = f"/materi/{self.materi2.id}/unduh"
         self.history_url = "/download-history/"
-
+		
         # Login
         self.client.login(**self.user_credential)
 
     def tearDown(self):
         # Logout
         self.client.logout()
-
+		
     def test_allow_registered_user(self):
         response = self.client.get(self.history_url)
         self.assertEqual(response.status_code, 200)
-
+	
     def test_allow_unregistered_user(self):
 	    # Forced Logout
         self.client.logout()
-
+		
         response = self.client.get(self.history_url)
         self.assertEqual(response.status_code, 200)
 
@@ -2735,14 +2732,14 @@ class DownloadHistoryViewTest(TestCase):
         response = self.client.get(self.history_url)
         resp_html = response.content.decode('utf8')
         self.assertIn(self.user_anonim.name, resp_html)
-
+		
     def test_registered_user_download_history_correctly_displayed(self):
         self.client.get(self.download_url1)
         self.client.get(self.download_url2)
         self.client.get(self.download_url1)
-
+		
         jkt_timezone = timezone(TIME_ZONE)
-
+		
         download_history = self.user_anonim.riwayat_unduh.all()
         response = self.client.get(self.history_url)
         resp_html = response.content.decode('utf8')
@@ -2750,19 +2747,19 @@ class DownloadHistoryViewTest(TestCase):
             downloaded_materi = riwayat.materi
             self.assertIn(downloaded_materi.title, resp_html)
             self.assertIn(downloaded_materi.author, resp_html)
-
+			
             jkt_timestamp = riwayat.timestamp.astimezone(jkt_timezone)
             self.assertIn(jkt_timestamp.strftime("%d %B %Y %H:%M:%S"), resp_html)
-
+			
     def test_unregistered_user_download_history_correctly_displayed(self):
         self.client.logout()
 
         self.client.get(self.download_url1)
         self.client.get(self.download_url2)
         self.client.get(self.download_url1)
-
+		
         jkt_timezone = timezone(TIME_ZONE)
-
+		
         response = self.client.get(self.history_url)
         resp_html = response.content.decode('utf8')
         for riwayat_id in self.client.session['downloaded_materi']:
@@ -2770,19 +2767,19 @@ class DownloadHistoryViewTest(TestCase):
             downloaded_materi = riwayat.materi
             self.assertIn(downloaded_materi.title, resp_html)
             self.assertIn(downloaded_materi.author, resp_html)
-
+			
             jkt_timestamp = riwayat.timestamp.astimezone(jkt_timezone)
             self.assertIn(jkt_timestamp.strftime("%d %B %Y %H:%M:%S"), resp_html)
-
+			
     def test_download_history_not_display_if_user_changed(self):
         self.client.get(self.download_url1)
         self.client.get(self.download_url2)
         self.client.get(self.download_url1)
 
         self.client.logout()
-
+		
         jkt_timezone = timezone(TIME_ZONE)
-
+		
         download_history = self.user_anonim.riwayat_unduh.all()
         response = self.client.get(self.history_url)
         resp_html = response.content.decode('utf8')
@@ -2790,23 +2787,23 @@ class DownloadHistoryViewTest(TestCase):
             downloaded_materi = riwayat.materi
             self.assertNotIn(downloaded_materi.title, resp_html)
             self.assertNotIn(downloaded_materi.author, resp_html)
-
+			
             jkt_timestamp = riwayat.timestamp.astimezone(jkt_timezone)
             self.assertNotIn(jkt_timestamp.strftime("%d %B %Y %H:%M:%S"), resp_html)
-
+			
     def test_unregistered_user_download_history_wont_be_saved_if_user_changes(self):
         self.client.logout()
 
         self.client.get(self.download_url1)
         self.client.get(self.download_url2)
         self.client.get(self.download_url1)
-
+		
         self.client.get(self.history_url)
 
         self.client.login(**self.user_credential)
         self.client.logout()
         self.assertFalse('downloaded_materi' in self.client.session)
-
+			
     def test_download_history_sorted_by_download_time(self):
 		# download with 1 second interval to differ download time
         self.client.get(self.download_url1)
@@ -2816,15 +2813,15 @@ class DownloadHistoryViewTest(TestCase):
         self.client.get(self.download_url1)
         sleep(1)
         self.client.get(self.download_url2)
-
+		
         response = self.client.get(self.history_url)
         resp_html = response.content.decode('utf8')
-
+		
         table_html = ("<table" + resp_html.split("<table")[1]).split("</table>")[0] + "</table>"
         soup = BeautifulSoup(table_html, 'html.parser')
         histories_html = soup.find('tbody').find_all('tr')
         prev_timestamp = None
-
+		
         for riwayat_html in histories_html:
             materi_data = riwayat_html.find_all("td")
             date_format = "%d %B %Y %H:%M:%S"
@@ -2832,7 +2829,7 @@ class DownloadHistoryViewTest(TestCase):
             if prev_timestamp:
                 self.assertTrue(prev_timestamp > materi_timestamp)
             prev_timestamp = materi_timestamp
-
+			
     def test_no_history_display_message(self):
         no_history_msg = "Anda belum mengunduh materi. Silahkan unduh materi yang anda butuhkan"
         response = self.client.get(self.history_url)
@@ -2841,9 +2838,9 @@ class DownloadHistoryViewTest(TestCase):
 
 
 class MateriModelTest(TestCase):
-
+    
     def setUp(self):
-        self.contributor = User.objects.create(
+        self.contributor = User.objects.create( 
             email="kontributor@gov.id",
             password="passwordtest",
             name="kontributor",
@@ -2930,7 +2927,7 @@ class RandomizedMateriTest(TestCase):
         response = Client().get("/?random=1")
         self.assertIn("Materi 1", response.content.decode())
         self.assertIn("Materi 2", response.content.decode())
-
+    
 class YearChoicesTest(TestCase):
     def test_release_year_contains_the_right_current_year(self):
         now = dt.date.today().year
@@ -2996,7 +2993,7 @@ class YTUrlVideoTest(TestCase):
         self.setUpImage()
         self.content = SimpleUploadedFile("ExampleFile221.pdf", b"Test file")
         self.category = Category.objects.create(id="1", name="medis", description="kategori medis")
-
+    
     @override_settings(MEDIA_ROOT=tempfile.gettempdir())
     def setUpImage(self):
         from django.core.files.uploadedfile import InMemoryUploadedFile
@@ -3029,7 +3026,7 @@ class YTUrlVideoTest(TestCase):
                                 "yt_video_id":"jNwz4L9MGVY"}
         )
         self.assertTrue(Materi.objects.get(title="Materi 1"))
-
+    
     def test_upload_materi_with_invalid_yt_video_id(self):
         self.client.login(**self.contributor_credential)
         self.client.post(
@@ -3039,7 +3036,7 @@ class YTUrlVideoTest(TestCase):
                                 "yt_video_id":"randomId"}
         )
         self.assertEqual(Materi.objects.filter(title="Materi 2").count(), 0)
-
+    
     def test_detail_materi_has_video_if_yt_video_id_not_empty(self):
         self.test_upload_materi_with_valid_yt_video_id()
         pk = Materi.objects.get(title="Materi 1").pk
@@ -3090,7 +3087,7 @@ class ChangePasswordTest(TestCase):
         # Logout
         self.client.logout()
 
-
+    
 class SeeRatedMateriByUser(TestCase):
     def setUp(self):
         self.client = Client()
@@ -3265,28 +3262,28 @@ class PasswordValidatorPolicyTest(TestCase):
         self.password_length_lower_than_8 = "P4ss!"
         self.password_enforcing_policy = "Passw0rd!"
         self.validator = PasswordPolicyValidator()
-
+    
     def test_using_password_no_lowercase(self):
         self.assertRaises(ValidationError, self.validator.validate, self.password_no_lowercase)
 
     def test_using_password_no_upprcase(self):
         self.assertRaises(ValidationError, self.validator.validate, self.password_no_uppercase)
-
+    
     def test_using_password_no_digit(self):
         self.assertRaises(ValidationError, self.validator.validate, self.password_no_digit)
 
     def test_using_password_no_special_char(self):
         self.assertRaises(ValidationError, self.validator.validate, self.password_no_special_char)
-
+    
     def test_using_password_with_length_less_than_8(self):
         self.assertRaises(ValidationError, self.validator.validate, self.password_length_lower_than_8)
-
+    
     def test_using_password_using_correct_policy(self):
         self.assertEquals(self.validator.validate(self.password_enforcing_policy), None)
-
+    
 
 class LandingPageNavbarTest(TestCase):
-
+    
     def setUp(self):
         self.client = Client()
         self.contributor_credential = {
@@ -3445,3 +3442,4 @@ class MateriRecommendationTest(TestCase):
         response = Client().get("/?recommendation=1")
         list = [int(id) for id in re.findall(r"Materi\s(\d+)[^\d]", response.content.decode())]
         self.assertEqual(list, [1, 2])
+    
diff --git a/app/urls.py b/app/urls.py
index 06e7d42410e9289b3f1342eb6cf58d6daa10e202..a8c7281cbdd6821bf7eace5f939520e099f53ad5 100644
--- a/app/urls.py
+++ b/app/urls.py
@@ -41,7 +41,4 @@ urlpatterns = [
     path("password_success/", views.password_success, name="password_success"),
     path("given-rating/", views.see_given_rating, name="see_given_rating"),
     path("submit-visitor/", SubmitVisitorView.as_view(), name="submit-visitor"),
-    path(r'subscribe/', views.subscribe, name='subscribe'),
-    path(r'subscribeform/', views.subscribeform, name='subscribeform'),
-    path(r'subscription_confirmation/', views.subscription_confirmation, name='subscription_confirmation'),
 ]
diff --git a/app/utils/email_utility.py b/app/utils/email_utility.py
deleted file mode 100644
index bc720758597e59a51e26a060f58838a2a17ef60d..0000000000000000000000000000000000000000
--- a/app/utils/email_utility.py
+++ /dev/null
@@ -1,90 +0,0 @@
-import logging, traceback
-from django.urls import reverse
-import requests
-from django.template.loader import get_template
-from django.utils.html import strip_tags
-from django.conf import settings
-import smtplib
-from email.mime.multipart import MIMEMultipart
-from email.mime.text import MIMEText
-import email
-import email.mime.application
-from django.utils.html import strip_tags
-
-
-def send_email(data):
-    try:
-        url = "https://api.mailgun.net/v3/<domain-name>/messages"
-        status = requests.post(
-            url,
-            auth=("api", settings.MAILGUN_API_KEY),
-            data={"from": "OKI  <https://app.mailgun.com/app/sending/domains/sandbox34675edbad2a4ab08e896c3bd80524ec.mailgun.org>",
-                  "to": [data["email"]],
-                  "subject": data["subject"],
-                  "text": data["plain_text"],
-                  "html": data["html_text"]}
-        )
-        logging.getLogger("info").info("Mail sent to " + data["email"] + ". status: " + str(status))
-        return status
-    except Exception as e:
-        logging.getLogger("error").error(traceback.format_exc())
-        return False
-
-
-def send_subscription_email(email, subscription_confirmation_url):
-    data = dict()
-    data["confirmation_url"] = subscription_confirmation_url
-    data["subject"] = "Please Confirm The Subscription"
-    data["email"] = email
-    template = get_template("app/emails/subscription.html")
-    data["html_text"] = template.render(data)
-    data["plain_text"] = strip_tags(data["html_text"])
-    return send_email(data)
-    
-
-def send_gmail(email, subscription_confirmation_url):
-    # create message
-    msg = MIMEMultipart('alternative')
-    msg['Subject'] = "Please verify your mail"
-    msg['From'] = "pmplmailer@gmail.com"
-    msg['To'] = email
-
-    # create body
-    html_text = '<div style="border:1px solid black">Thanks for subscribing to Us. Please click this link to activate your subscription : ' + subscription_confirmation_url + '</div>'
-    plain_text = strip_tags(html_text)
-
-    # Create the body of the message (a plain-text and an HTML version).
-    # Record the MIME types of both parts - text/plain and text/html.
-    part1 = MIMEText(plain_text, 'plain')
-    part2 = MIMEText(html_text, 'html')
-
-    # Attach image if any
-
-    # Attach parts into message container.
-    # According to RFC 2046, the last part of a multipart message, in this case
-    # the HTML message, is best and preferred.
-    msg.attach(part1)
-    msg.attach(part2)
-
-    # Send the message via local SMTP server.
-    host = "smtp.gmail.com"
-    port = 587
-    mail = smtplib.SMTP(host, port, timeout=60)
-    mail.ehlo()
-    mail.starttls()
-
-    # Add recepiens, cc or bcc if any
-    recepient = [msg["To"]]
-
-    # username and password of gmail id which will be used to send email
-    username = "pmplmailer@gmail.com"
-    password = "asdf1234$"
-
-    # login using credentials
-    mail.login(username, password)
-
-    # send email
-    mail.sendmail(msg["From"], recepient, msg.as_string())
-    mail.quit()
-
-    return "\nSent\n"
\ No newline at end of file
diff --git a/app/utils/encryption_util.py b/app/utils/encryption_util.py
deleted file mode 100644
index a448767e066acceda561a4a48cc602628db41148..0000000000000000000000000000000000000000
--- a/app/utils/encryption_util.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from cryptography.fernet import Fernet
-import base64
-import logging
-import traceback
-from django.conf import settings
-
-#this is your "password/ENCRYPT_KEY". keep it in settings.py file
-#key = Fernet.generate_key() 
-
-def encrypt(txt):
-    try:
-        # convert integer etc to string first
-        txt = str(txt)
-        # get the key from settings
-        cipher_suite = Fernet(settings.ENCRYPT_KEY) # key should be byte
-        # #input should be byte, so convert the text to byte
-        encrypted_text = cipher_suite.encrypt(txt.encode('ascii'))
-        # encode to urlsafe base64 format
-        encrypted_text = base64.urlsafe_b64encode(encrypted_text).decode("ascii") 
-        return encrypted_text
-    except Exception as e:
-        # log the error if any
-        logging.getLogger("error_logger").error(traceback.format_exc())
-        return None
-
-
-def decrypt(txt):
-    try:
-        # base64 decode
-        txt = base64.urlsafe_b64decode(txt)
-        cipher_suite = Fernet(settings.ENCRYPT_KEY)
-        decoded_text = cipher_suite.decrypt(txt).decode("ascii")     
-        return decoded_text
-    except Exception as e:
-        # log the error
-        logging.getLogger("error_logger").error(traceback.format_exc())
-        return None
\ No newline at end of file
diff --git a/app/views.py b/app/views.py
index 306e84073b13dea436e90faa2952bafcb618f81c..a0062ed070c2065cc77c3e37757c749b70f470d1 100644
--- a/app/views.py
+++ b/app/views.py
@@ -1,9 +1,5 @@
 import mimetypes
 import os
-import re
-import time
-import logging
-import traceback
 from io import BytesIO
 
 import django
@@ -19,7 +15,8 @@ from django.core.paginator import Paginator
 from django.db.models import Q, Avg
 from django.http import (Http404, HttpResponse, HttpResponseRedirect,
                          JsonResponse)
-from django.shortcuts import get_object_or_404, redirect, render
+from django.shortcuts import get_object_or_404, redirect
+from django.shortcuts import render
 from django.template import loader
 from django.urls import reverse
 from django.urls import reverse_lazy
@@ -37,10 +34,6 @@ from app.models import (
     SubmitVisitor
 )
 from authentication.models import User
-from app.utils.encryption_util import encrypt, decrypt
-from app.utils.email_utility import send_subscription_email, send_gmail
-from app.models import SubscribeModel
-from datetime import datetime
 from .services import DafterKatalogService, DetailMateriService, LikeDislikeService, MateriFieldValidationHelperService, \
     DownloadViewMateriHelperService, UploadMateriService, EditProfileService, RevisiMateriService, \
     DownloadHistoryService, GoogleDriveUploadService
@@ -212,7 +205,7 @@ class DetailMateri(TemplateView):
                         from_email = getattr(settings, 'EMAIL_HOST_USER'),
                         recipient_list = [materi_uploader.email,],
                         fail_silently = False,
-                    )
+                    ) 
             elif (review_text != None):
                 review = Review.objects.create(
                     review=review_text, username=DetailMateriService.get_user_name(request), materi=materi, user=user_obj
@@ -292,98 +285,6 @@ def add_rating_materi(request):
         )
     return JsonResponse({"success": False, "msg": "Forbidden"}, status=403)
 
-def subscribeform(request):
-    return render(request, 'subscribe.html', )
-
-def subscribe(request):
-    post_data = request.POST.copy()
-    email = post_data.get("email", None)
-
-    error_msg = validate_email(email)
-    if error_msg:
-        messages.error(request, error_msg)
-        return HttpResponseRedirect(reverse('subscribe'))
-
-    token = encrypt(email + "_" + str(time.time()))
-    subscription_confirmation_url = request.build_absolute_uri( reverse('subscription_confirmation')) + "?token=" + token
-    status = send_gmail(email, subscription_confirmation_url)
-    save_status = save_email(email)
-
-    if save_status:
-        token = encrypt(email + "_" + str(time.time()))
-        subscription_confirmation_url = request.build_absolute_uri(reverse('subscription_confirmation')) + "?token=" + token
-        status = send_gmail(email, subscription_confirmation_url)
-        if not status:
-            SubscribeModel.objects.get(email=email).delete()
-            logging.getLogger("info").info(
-                "Deleted the record from Subscribe table for " + email + " as email sending failed. status: " + str(
-                    status))
-        else:
-            msg = "Mail sent to email Id '" + email + "'. Please confirm your subscription by clicking on " \
-                                                      "confirmation link provided in email. " \
-                                                      "Please check your spam folder as well."
-            messages.success(request, msg)
-            return HttpResponse(msg)
-    else:
-        msg = "Some error occurred. Please try in some time. Meanwhile we are looking into it."
-        messages.error(request, msg)
-        return HttpResponse(msg)
-    return  HttpResponseRedirect(reverse('subscribeform'))
-
-def subscription_confirmation(request):
-    if "POST" == request.method:
-        raise Http404
-
-    token = request.GET.get("token", None)
-
-    if not token:
-        logging.getLogger("warning").warning("Invalid Link ")
-        messages.error(request, "Invalid Link")
-        return HttpResponseRedirect(reverse('subscribeform'))
-
-    token = decrypt(token)
-    if token:
-        token = token.split("_")
-        email = token[0]
-        print(email)
-        initiate_time = token[1]  # time when email was sent , in epoch format. can be used for later calculations
-        try:
-            subscribe_model_instance = SubscribeModel.objects.get(email=email)
-            subscribe_model_instance.status = "CONFIRMED"
-            subscribe_model_instance.updated_date = datetime.today()
-            subscribe_model_instance.save()
-            messages.success(request, "Subscription Confirmed. Thank you.")
-        except Exception as e:
-            logging.getLogger("warning").warning(traceback.format_exc())
-            messages.error(request, "Invalid Link")
-    else:
-        logging.getLogger("warning").warning("Invalid token ")
-        messages.error(request, "Invalid Link")
-
-    return HttpResponse('<h1>Thank you for subscribing us</h1>')
-
-def validate_email(email):
-    if email is None:
-        return "Email is required."
-    elif not re.match(r"^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$", email):
-        return "Invalid Email Address."
-    else:
-        return None
-
-def save_email(email):
-    try:
-        subscribe_model_instance = SubscribeModel.objects.get(email=email)
-    except Exception as e:
-        subscribe_model_instance = SubscribeModel()
-
-
-    # does not matter if already subscribed or not...resend the email
-    subscribe_model_instance.email = email
-    subscribe_model_instance.status = "SUBSCRIBED"
-    subscribe_model_instance.created_date = datetime.today()
-    subscribe_model_instance.updated_date = datetime.today()
-    subscribe_model_instance.save()
-    return True
 
 
 def download_materi(request, pk):
@@ -751,7 +652,6 @@ class RevisiMateriView(TemplateView):
             return self.render_to_response(context)
 
 
-
 def pages(request):
     context = {}
     # All resource paths end in .html.
diff --git a/authentication/migrations/0001_initial.py b/authentication/migrations/0001_initial.py
index 8dd6568cd24f5cf72e9aba257659da57907aa573..b28fe9c3d35bef40e5c1a2e04b5c1acbc47333fd 100644
--- a/authentication/migrations/0001_initial.py
+++ b/authentication/migrations/0001_initial.py
@@ -1,8 +1,9 @@
-# Generated by Django 3.1 on 2020-10-30 15:29
+# Generated by Django 3.0.3 on 2020-05-08 14:42
 
-import authentication.models
-from django.db import migrations, models
 import django.utils.timezone
+from django.db import migrations, models
+
+import authentication.models
 
 
 class Migration(migrations.Migration):
@@ -10,41 +11,53 @@ class Migration(migrations.Migration):
     initial = True
 
     dependencies = [
-        ('auth', '0012_alter_user_first_name_max_length'),
+        ('auth', '0011_update_proxy_permissions'),
     ]
 
     operations = [
         migrations.CreateModel(
             name='User',
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('password', models.CharField(max_length=128, verbose_name='password')),
-                ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
-                ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
-                ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
-                ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
-                ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
-                ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
-                ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
+                ('id', models.AutoField(auto_created=True,
+                                        primary_key=True, serialize=False, verbose_name='ID')),
+                ('password', models.CharField(
+                    max_length=128, verbose_name='password')),
+                ('last_login', models.DateTimeField(
+                    blank=True, null=True, verbose_name='last login')),
+                ('is_superuser', models.BooleanField(default=False,
+                                                     help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
+                ('first_name', models.CharField(blank=True,
+                                                max_length=30, verbose_name='first name')),
+                ('last_name', models.CharField(blank=True,
+                                               max_length=150, verbose_name='last name')),
+                ('is_staff', models.BooleanField(default=False,
+                                                 help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
+                ('is_active', models.BooleanField(
+                    default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
+                ('date_joined', models.DateTimeField(
+                    default=django.utils.timezone.now, verbose_name='date joined')),
                 ('email', models.EmailField(max_length=254, unique=True)),
-                ('username', models.CharField(blank=True, default='', max_length=150)),
+                ('username', models.CharField(
+                    blank=True, default='', max_length=150)),
                 ('name', models.CharField(max_length=150)),
                 ('is_admin', models.BooleanField(default=False)),
                 ('is_contributor', models.BooleanField(default=False)),
                 ('instansi', models.CharField(max_length=240)),
-                ('nik', models.CharField(max_length=16)),
+                ('nik', models.CharField(max_length=240)),
                 ('alamat', models.CharField(max_length=240)),
                 ('nomor_telpon', models.CharField(max_length=240)),
                 ('linkedin', models.URLField(blank=True, default='')),
                 ('facebook', models.URLField(blank=True, default='')),
                 ('twitter', models.URLField(blank=True, default='')),
                 ('instagram', models.URLField(blank=True, default='')),
-                ('biography', models.TextField(blank=True, default='', max_length=200)),
-                ('default_profile_picture', models.BooleanField(blank=True, default=False)),
-                ('profile_picture', models.ImageField(default='default-image.jpg', upload_to='')),
-                ('is_subscribing_to_material_comments', models.BooleanField(default=True)),
-                ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
-                ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
+                ('biography', models.TextField(
+                    blank=True, default='', max_length=200)),
+                ('profile_picture', models.ImageField(
+                    default='https://ibb.co/gv9YHt4', upload_to='profile_picture/')),
+                ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.',
+                                                  related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
+                ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.',
+                                                            related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
             ],
             options={
                 'verbose_name': 'user',
diff --git a/authentication/migrations/0002_auto_20200518_1752.py b/authentication/migrations/0002_auto_20200518_1752.py
new file mode 100644
index 0000000000000000000000000000000000000000..8e88a1b0ce600471b466fc503131e56fd6defd54
--- /dev/null
+++ b/authentication/migrations/0002_auto_20200518_1752.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.0.3 on 2020-05-18 10:52
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('authentication', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='user',
+            name='profile_picture',
+            field=models.ImageField(default='https://i.ibb.co/9wgPzyZ/default-image.png', upload_to='profile_picture/'),
+        ),
+    ]
diff --git a/authentication/migrations/0003_auto_20200519_1012.py b/authentication/migrations/0003_auto_20200519_1012.py
new file mode 100644
index 0000000000000000000000000000000000000000..b705ff097ac330024e85c1b8c97daf8890e7a54e
--- /dev/null
+++ b/authentication/migrations/0003_auto_20200519_1012.py
@@ -0,0 +1,23 @@
+# Generated by Django 3.0.3 on 2020-05-19 03:12
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('authentication', '0002_auto_20200518_1752'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='user',
+            name='default_profile_picture',
+            field=models.URLField(blank=True, default="https://i.ibb.co/9wgPzyZ/default-image.png'"),
+        ),
+        migrations.AlterField(
+            model_name='user',
+            name='profile_picture',
+            field=models.ImageField(upload_to='', verbose_name=models.URLField(blank=True, default="https://i.ibb.co/9wgPzyZ/default-image.png'")),
+        ),
+    ]
diff --git a/authentication/migrations/0004_auto_20200519_1020.py b/authentication/migrations/0004_auto_20200519_1020.py
new file mode 100644
index 0000000000000000000000000000000000000000..255dcf75f6a117a94a61e45177b7e4f257a1afc3
--- /dev/null
+++ b/authentication/migrations/0004_auto_20200519_1020.py
@@ -0,0 +1,23 @@
+# Generated by Django 3.0.3 on 2020-05-19 03:20
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('authentication', '0003_auto_20200519_1012'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='user',
+            name='default_profile_picture',
+            field=models.BooleanField(blank=True, default=False),
+        ),
+        migrations.AlterField(
+            model_name='user',
+            name='profile_picture',
+            field=models.ImageField(upload_to='', verbose_name=models.BooleanField(blank=True, default=False)),
+        ),
+    ]
diff --git a/authentication/migrations/0005_auto_20200519_1021.py b/authentication/migrations/0005_auto_20200519_1021.py
new file mode 100644
index 0000000000000000000000000000000000000000..05bf864c6833afd6496877d76da9a976f7add55f
--- /dev/null
+++ b/authentication/migrations/0005_auto_20200519_1021.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.0.3 on 2020-05-19 03:21
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('authentication', '0004_auto_20200519_1020'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='user',
+            name='profile_picture',
+            field=models.ImageField(default='default-image.jpg', upload_to=''),
+        ),
+    ]
diff --git a/authentication/migrations/0006_auto_20200929_2125.py b/authentication/migrations/0006_auto_20200929_2125.py
new file mode 100644
index 0000000000000000000000000000000000000000..a2c2da4f14cc46dadd6f038686ae09c7205e6c72
--- /dev/null
+++ b/authentication/migrations/0006_auto_20200929_2125.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.1 on 2020-09-29 14:25
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('authentication', '0005_auto_20200519_1021'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='user',
+            name='first_name',
+            field=models.CharField(blank=True, max_length=150, verbose_name='first name'),
+        ),
+    ]
diff --git a/authentication/migrations/0007_auto_20201009_1415.py b/authentication/migrations/0007_auto_20201009_1415.py
new file mode 100644
index 0000000000000000000000000000000000000000..012a5c89e717087a23903de27bbadbdf8798d63e
--- /dev/null
+++ b/authentication/migrations/0007_auto_20201009_1415.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.1 on 2020-10-09 07:15
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('authentication', '0006_auto_20200929_2125'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='user',
+            name='nik',
+            field=models.CharField(max_length=16),
+        ),
+    ]
diff --git a/authentication/migrations/0008_user_is_subscribing_to_material_comments.py b/authentication/migrations/0008_user_is_subscribing_to_material_comments.py
new file mode 100644
index 0000000000000000000000000000000000000000..2348d49d3ce1c3cbe3b11628b81dde0ad5be4478
--- /dev/null
+++ b/authentication/migrations/0008_user_is_subscribing_to_material_comments.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.1 on 2020-10-29 12:52
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('authentication', '0007_auto_20201009_1415'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='user',
+            name='is_subscribing_to_material_comments',
+            field=models.BooleanField(default=True),
+        ),
+    ]
diff --git a/digipus/settings.py b/digipus/settings.py
index 3fc4cad5a64dc14ba4badf26c09479b5dc7be212..884c3e67cf7924e4165161d8d50a3ce04361a306 100644
--- a/digipus/settings.py
+++ b/digipus/settings.py
@@ -189,5 +189,4 @@ EMAIL_PORT = config('EMAIL_PORT', default=587) # use Google Mail SMTP as default
 EMAIL_HOST_USER = config('EMAIL_HOST_USER', default="pmplclass2020@gmail.com")
 EMAIL_HOST_PASSWORD = config('EMAIL_HOST_PASSWORD', default="pmpldigipusemail")
 EMAIL_USE_TLS = True
-EMAIL_USE_SSL = False
-ENCRYPT_KEY = b'YVLSFH4WgxkLgCOmCBchVmahU_VIF2xPFdD7GUTsvgY='
+EMAIL_USE_SSL = False
\ No newline at end of file
diff --git a/forum/migrations/0001_initial.py b/forum/migrations/0001_initial.py
index 652260331742b31ca6bacb8926451651385c17b3..09be1531345689e50d9940908018970274ada73f 100644
--- a/forum/migrations/0001_initial.py
+++ b/forum/migrations/0001_initial.py
@@ -1,4 +1,4 @@
-# Generated by Django 3.1 on 2020-10-30 15:30
+# Generated by Django 3.1 on 2020-10-06 14:39
 
 from django.conf import settings
 from django.db import migrations, models
@@ -11,7 +11,6 @@ class Migration(migrations.Migration):
 
     dependencies = [
         migrations.swappable_dependency(settings.AUTH_USER_MODEL),
-        ('app', '0001_initial'),
     ]
 
     operations = [
@@ -20,10 +19,7 @@ class Migration(migrations.Migration):
             fields=[
                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                 ('title', models.TextField()),
-                ('description', models.TextField(blank=True, default='')),
-                ('created_at', models.DateTimeField(auto_now_add=True)),
-                ('updated_at', models.DateTimeField(auto_now=True)),
-                ('materi', models.ManyToManyField(blank=True, to='app.Materi')),
+                ('description', models.TextField(default='')),
                 ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
             ],
         ),
@@ -32,10 +28,7 @@ class Migration(migrations.Migration):
             fields=[
                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                 ('description', models.TextField(default='')),
-                ('created_at', models.DateTimeField(auto_now_add=True)),
-                ('updated_at', models.DateTimeField(auto_now=True)),
                 ('discussion', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='forum.discussion')),
-                ('materi', models.ManyToManyField(blank=True, to='app.Materi')),
                 ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
             ],
         ),
diff --git a/forum/migrations/0002_auto_20201007_1903.py b/forum/migrations/0002_auto_20201007_1903.py
new file mode 100644
index 0000000000000000000000000000000000000000..f26c6bac7c379bbb8dc5bb85ecbb59bb0e4b8e0c
--- /dev/null
+++ b/forum/migrations/0002_auto_20201007_1903.py
@@ -0,0 +1,24 @@
+# Generated by Django 3.1 on 2020-10-07 12:03
+
+from django.db import migrations, models
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('forum', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='discussion',
+            name='created_at',
+            field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
+            preserve_default=False,
+        ),
+        migrations.AddField(
+            model_name='discussion',
+            name='updated_at',
+            field=models.DateTimeField(auto_now=True),
+        ),
+    ]
diff --git a/forum/migrations/0003_auto_20201008_2056.py b/forum/migrations/0003_auto_20201008_2056.py
new file mode 100644
index 0000000000000000000000000000000000000000..dab5b854233c101e4563576f554eacb33b0365e9
--- /dev/null
+++ b/forum/migrations/0003_auto_20201008_2056.py
@@ -0,0 +1,24 @@
+# Generated by Django 3.1 on 2020-10-08 13:56
+
+from django.db import migrations, models
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('forum', '0002_auto_20201007_1903'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='discussioncomment',
+            name='created_at',
+            field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
+            preserve_default=False,
+        ),
+        migrations.AddField(
+            model_name='discussioncomment',
+            name='updated_at',
+            field=models.DateTimeField(auto_now=True),
+        ),
+    ]
diff --git a/forum/migrations/0004_discussion_materi.py b/forum/migrations/0004_discussion_materi.py
new file mode 100644
index 0000000000000000000000000000000000000000..8cbd9bd33e85ad3e50b4021d38ecc61d6afeebed
--- /dev/null
+++ b/forum/migrations/0004_discussion_materi.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.1 on 2020-10-08 18:37
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('app', '0015_reqmaterial'),
+        ('forum', '0003_auto_20201008_2056'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='discussion',
+            name='materi',
+            field=models.ManyToManyField(blank=True, null=True, to='app.Materi'),
+        ),
+    ]
diff --git a/forum/migrations/0005_auto_20201009_0138.py b/forum/migrations/0005_auto_20201009_0138.py
new file mode 100644
index 0000000000000000000000000000000000000000..c4fc40216dcc5203cd5f094eac30a507e281ea11
--- /dev/null
+++ b/forum/migrations/0005_auto_20201009_0138.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.1 on 2020-10-08 18:38
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('app', '0015_reqmaterial'),
+        ('forum', '0004_discussion_materi'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='discussion',
+            name='materi',
+            field=models.ManyToManyField(blank=True, to='app.Materi'),
+        ),
+    ]
diff --git a/forum/migrations/0006_auto_20201009_0625.py b/forum/migrations/0006_auto_20201009_0625.py
new file mode 100644
index 0000000000000000000000000000000000000000..3e59801201877f0ae3fa0d9ca0972d8aad393c17
--- /dev/null
+++ b/forum/migrations/0006_auto_20201009_0625.py
@@ -0,0 +1,23 @@
+# Generated by Django 3.1 on 2020-10-08 23:25
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('app', '0015_reqmaterial'),
+        ('forum', '0005_auto_20201009_0138'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='discussioncomment',
+            name='materi',
+            field=models.ManyToManyField(blank=True, to='app.Materi'),
+        ),
+        migrations.AlterField(
+            model_name='discussion',
+            name='description',
+            field=models.TextField(blank=True, default=''),
+        ),
+    ]
diff --git a/news/migrations/0001_initial.py b/news/migrations/0001_initial.py
index ed7921e164b76563aa96c5b5d43cf0260e5f7b1a..7c584641a29f5191a19848e13e52ed48722d8ff4 100644
--- a/news/migrations/0001_initial.py
+++ b/news/migrations/0001_initial.py
@@ -1,4 +1,4 @@
-# Generated by Django 3.1 on 2020-10-30 15:30
+# Generated by Django 3.1 on 2020-10-03 07:47
 
 from django.db import migrations, models