From 1be125fc1d9f0aa9193c80eac57603bf5a3dd9fe Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 11 Aug 2021 11:19:06 -0700 Subject: [PATCH 1/7] Adds database constraint for readthrough dates --- .../migrations/0083_auto_20210811_1817.py | 27 +++++++++++++++++++ bookwyrm/models/readthrough.py | 15 +++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 bookwyrm/migrations/0083_auto_20210811_1817.py diff --git a/bookwyrm/migrations/0083_auto_20210811_1817.py b/bookwyrm/migrations/0083_auto_20210811_1817.py new file mode 100644 index 000000000..2abc88b0a --- /dev/null +++ b/bookwyrm/migrations/0083_auto_20210811_1817.py @@ -0,0 +1,27 @@ +# Generated by Django 3.2.4 on 2021-08-11 18:17 + +from django.db import migrations, models +import django.db.models.expressions + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0082_auto_20210806_2324"), + ] + + operations = [ + migrations.AlterModelOptions( + name="readthrough", + options={"ordering": ("-start_date",)}, + ), + migrations.AddConstraint( + model_name="readthrough", + constraint=models.CheckConstraint( + check=models.Q( + ("finish_date__gte", django.db.models.expressions.F("start_date")) + ), + name="chronology", + ), + ), + ] diff --git a/bookwyrm/models/readthrough.py b/bookwyrm/models/readthrough.py index df341c8b2..343d3c115 100644 --- a/bookwyrm/models/readthrough.py +++ b/bookwyrm/models/readthrough.py @@ -1,7 +1,8 @@ """ progress in a book """ -from django.db import models -from django.utils import timezone from django.core import validators +from django.db import models +from django.db.models import F, Q +from django.utils import timezone from .base_model import BookWyrmModel @@ -41,6 +42,16 @@ class ReadThrough(BookWyrmModel): ) return None + class Meta: + """Don't let readthroughs end before they start""" + + constraints = [ + models.CheckConstraint( + check=Q(finish_date__gte=F("start_date")), name="chronology" + ) + ] + ordering = ("-start_date",) + class ProgressUpdate(BookWyrmModel): """Store progress through a book in the database.""" From 3f2f8f0e50e6d0359ce16bc4256769dfa0dbabfb Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 27 Aug 2021 10:31:39 -0700 Subject: [PATCH 2/7] Updates migrations --- ...{0083_auto_20210811_1817.py => 0086_auto_20210827_1727.py} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename bookwyrm/migrations/{0083_auto_20210811_1817.py => 0086_auto_20210827_1727.py} (86%) diff --git a/bookwyrm/migrations/0083_auto_20210811_1817.py b/bookwyrm/migrations/0086_auto_20210827_1727.py similarity index 86% rename from bookwyrm/migrations/0083_auto_20210811_1817.py rename to bookwyrm/migrations/0086_auto_20210827_1727.py index 2abc88b0a..a9c9c7a8e 100644 --- a/bookwyrm/migrations/0083_auto_20210811_1817.py +++ b/bookwyrm/migrations/0086_auto_20210827_1727.py @@ -1,4 +1,4 @@ -# Generated by Django 3.2.4 on 2021-08-11 18:17 +# Generated by Django 3.2.4 on 2021-08-27 17:27 from django.db import migrations, models import django.db.models.expressions @@ -7,7 +7,7 @@ import django.db.models.expressions class Migration(migrations.Migration): dependencies = [ - ("bookwyrm", "0082_auto_20210806_2324"), + ("bookwyrm", "0085_user_saved_lists"), ] operations = [ From 2c78eddbeb427a668b7aaeb70c29cf1e1e99d1f9 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 27 Aug 2021 10:47:56 -0700 Subject: [PATCH 3/7] Normalize readthrough dates in advance of migration --- bookwyrm/migrations/0086_auto_20210827_1727.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/bookwyrm/migrations/0086_auto_20210827_1727.py b/bookwyrm/migrations/0086_auto_20210827_1727.py index a9c9c7a8e..7632a5b48 100644 --- a/bookwyrm/migrations/0086_auto_20210827_1727.py +++ b/bookwyrm/migrations/0086_auto_20210827_1727.py @@ -4,6 +4,18 @@ from django.db import migrations, models import django.db.models.expressions +def normalize_readthrough_dates(app_registry, schema_editor): + """bih""" + db_alias = schema_editor.connection.alias + app_registry.get_model("bookwyrm", "Readthrough").objects.using(db_alias).filter( + start_date__gt=models.F("finish_date") + ).update(start_date=models.F("finish_date")) + + +def reverse_func(apps, schema_editor): + """nothing to do here""" + + class Migration(migrations.Migration): dependencies = [ @@ -11,6 +23,7 @@ class Migration(migrations.Migration): ] operations = [ + migrations.RunPython(normalize_readthrough_dates, reverse_func), migrations.AlterModelOptions( name="readthrough", options={"ordering": ("-start_date",)}, From e129b9c1f1787311cc94c33eb11e6f49d1d0f18a Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 27 Aug 2021 11:16:51 -0700 Subject: [PATCH 4/7] Adds more readthrough model tests --- .../tests/models/test_readthrough_model.py | 78 ++++++++++++++++--- 1 file changed, 66 insertions(+), 12 deletions(-) diff --git a/bookwyrm/tests/models/test_readthrough_model.py b/bookwyrm/tests/models/test_readthrough_model.py index 596753f79..2b6e4fdd2 100644 --- a/bookwyrm/tests/models/test_readthrough_model.py +++ b/bookwyrm/tests/models/test_readthrough_model.py @@ -1,7 +1,9 @@ """ testing models """ +import datetime from unittest.mock import patch from django.test import TestCase from django.core.exceptions import ValidationError +from django.utils import timezone from bookwyrm import models @@ -21,27 +23,79 @@ class ReadThrough(TestCase): title="Example Edition", parent_work=self.work ) - self.readthrough = models.ReadThrough.objects.create( - user=self.user, book=self.edition + def test_valid_date(self): + """can't finish a book before you start it""" + start = timezone.now() + finish = start + datetime.timedelta(days=1) + # just make sure there's no errors + models.ReadThrough.objects.create( + user=self.user, + book=self.edition, + start_date=start, + finish_date=finish, + ) + + def test_valid_date_null_start(self): + """can't finish a book before you start it""" + start = timezone.now() + finish = start + datetime.timedelta(days=1) + # just make sure there's no errors + models.ReadThrough.objects.create( + user=self.user, + book=self.edition, + finish_date=finish, + ) + + def test_valid_date_null_finish(self): + """can't finish a book before you start it""" + start = timezone.now() + # just make sure there's no errors + models.ReadThrough.objects.create( + user=self.user, + book=self.edition, + start_date=start, + ) + + def test_valid_date_null(self): + """can't finish a book before you start it""" + # just make sure there's no errors + models.ReadThrough.objects.create( + user=self.user, + book=self.edition, + ) + + def test_valid_date_same(self): + """can't finish a book before you start it""" + start = timezone.now() + # just make sure there's no errors + models.ReadThrough.objects.create( + user=self.user, + book=self.edition, + start_date=start, + finish_date=start, ) def test_progress_update(self): """Test progress updates""" - self.readthrough.create_update() # No-op, no progress yet - self.readthrough.progress = 10 - self.readthrough.create_update() - self.readthrough.progress = 20 - self.readthrough.progress_mode = models.ProgressMode.PERCENT - self.readthrough.create_update() + readthrough = models.ReadThrough.objects.create( + user=self.user, book=self.edition + ) - updates = self.readthrough.progressupdate_set.order_by("created_date").all() + readthrough.create_update() # No-op, no progress yet + readthrough.progress = 10 + readthrough.create_update() + readthrough.progress = 20 + readthrough.progress_mode = models.ProgressMode.PERCENT + readthrough.create_update() + + updates = readthrough.progressupdate_set.order_by("created_date").all() self.assertEqual(len(updates), 2) self.assertEqual(updates[0].progress, 10) self.assertEqual(updates[0].mode, models.ProgressMode.PAGE) self.assertEqual(updates[1].progress, 20) self.assertEqual(updates[1].mode, models.ProgressMode.PERCENT) - self.readthrough.progress = -10 - self.assertRaises(ValidationError, self.readthrough.clean_fields) - update = self.readthrough.create_update() + readthrough.progress = -10 + self.assertRaises(ValidationError, readthrough.clean_fields) + update = readthrough.create_update() self.assertRaises(ValidationError, update.clean_fields) From 497b54c014f15471a46373475a27a697c59724aa Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 27 Aug 2021 11:38:34 -0700 Subject: [PATCH 5/7] Updates test --- bookwyrm/tests/views/test_reading.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/tests/views/test_reading.py b/bookwyrm/tests/views/test_reading.py index bebd9f5a9..61464bc7f 100644 --- a/bookwyrm/tests/views/test_reading.py +++ b/bookwyrm/tests/views/test_reading.py @@ -107,7 +107,7 @@ class ReadingViews(TestCase): { "post-status": True, "privacy": "followers", - "finish_date": "2020-01-07", + "finish_date": timezone.now().isoformat(), "id": readthrough.id, }, ) From 66f8e9b4fc412b22fa905260a66d04a3f4d0a331 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sun, 29 Aug 2021 11:12:57 -0700 Subject: [PATCH 6/7] Fixes model name --- bookwyrm/migrations/0086_auto_20210827_1727.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/migrations/0086_auto_20210827_1727.py b/bookwyrm/migrations/0086_auto_20210827_1727.py index 7632a5b48..ef6af206b 100644 --- a/bookwyrm/migrations/0086_auto_20210827_1727.py +++ b/bookwyrm/migrations/0086_auto_20210827_1727.py @@ -5,9 +5,9 @@ import django.db.models.expressions def normalize_readthrough_dates(app_registry, schema_editor): - """bih""" + """Find any invalid dates and reset them""" db_alias = schema_editor.connection.alias - app_registry.get_model("bookwyrm", "Readthrough").objects.using(db_alias).filter( + app_registry.get_model("bookwyrm", "ReadThrough").objects.using(db_alias).filter( start_date__gt=models.F("finish_date") ).update(start_date=models.F("finish_date")) From e98ee64e2ba9e577f4cf118565c5fe81fa6bdc44 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sun, 29 Aug 2021 11:20:30 -0700 Subject: [PATCH 7/7] Merge migration --- ...86_auto_20210827_1727_0086_auto_20210828_1724.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 bookwyrm/migrations/0087_merge_0086_auto_20210827_1727_0086_auto_20210828_1724.py diff --git a/bookwyrm/migrations/0087_merge_0086_auto_20210827_1727_0086_auto_20210828_1724.py b/bookwyrm/migrations/0087_merge_0086_auto_20210827_1727_0086_auto_20210828_1724.py new file mode 100644 index 000000000..cd5311619 --- /dev/null +++ b/bookwyrm/migrations/0087_merge_0086_auto_20210827_1727_0086_auto_20210828_1724.py @@ -0,0 +1,13 @@ +# Generated by Django 3.2.4 on 2021-08-29 18:19 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0086_auto_20210827_1727"), + ("bookwyrm", "0086_auto_20210828_1724"), + ] + + operations = []