forked from mirrors/bookwyrm
Merge pull request #1286 from bookwyrm-social/readthrough-dates
Adds database constraint for read-through dates
This commit is contained in:
commit
a9716f2fd8
5 changed files with 133 additions and 15 deletions
40
bookwyrm/migrations/0086_auto_20210827_1727.py
Normal file
40
bookwyrm/migrations/0086_auto_20210827_1727.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
# Generated by Django 3.2.4 on 2021-08-27 17:27
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.expressions
|
||||
|
||||
|
||||
def normalize_readthrough_dates(app_registry, schema_editor):
|
||||
"""Find any invalid dates and reset them"""
|
||||
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 = [
|
||||
("bookwyrm", "0085_user_saved_lists"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(normalize_readthrough_dates, reverse_func),
|
||||
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",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -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 = []
|
|
@ -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."""
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue