diff --git a/bookwyrm/migrations/0116_auto_20211114_1700.py b/bookwyrm/migrations/0116_auto_20211114_1700.py deleted file mode 100644 index ff71b89ce..000000000 --- a/bookwyrm/migrations/0116_auto_20211114_1700.py +++ /dev/null @@ -1,32 +0,0 @@ -# Generated by Django 3.2.5 on 2021-11-14 17:00 - -from django.db import migrations, models -import django.utils.timezone - - -class Migration(migrations.Migration): - - dependencies = [ - ('bookwyrm', '0115_importitem_linked_review'), - ] - - operations = [ - migrations.RemoveField( - model_name='importjob', - name='complete', - ), - migrations.RemoveField( - model_name='importjob', - name='task_id', - ), - migrations.AddField( - model_name='importjob', - name='completed_count', - field=models.IntegerField(default=0), - ), - migrations.AddField( - model_name='importjob', - name='updated_date', - field=models.DateTimeField(default=django.utils.timezone.now), - ), - ] diff --git a/bookwyrm/migrations/0116_auto_20211114_1734.py b/bookwyrm/migrations/0116_auto_20211114_1734.py new file mode 100644 index 000000000..1da001bdc --- /dev/null +++ b/bookwyrm/migrations/0116_auto_20211114_1734.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.5 on 2021-11-14 17:34 + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0115_importitem_linked_review"), + ] + + operations = [ + migrations.RemoveField( + model_name="importjob", + name="task_id", + ), + migrations.AddField( + model_name="importjob", + name="updated_date", + field=models.DateTimeField(default=django.utils.timezone.now), + ), + ] diff --git a/bookwyrm/models/import_job.py b/bookwyrm/models/import_job.py index 953ae3946..fbec88cae 100644 --- a/bookwyrm/models/import_job.py +++ b/bookwyrm/models/import_job.py @@ -38,13 +38,18 @@ class ImportJob(models.Model): include_reviews = models.BooleanField(default=True) mappings = models.JSONField() updated_date = models.DateTimeField(default=timezone.now) - completed_count = models.IntegerField(default=0) + complete = models.BooleanField(default=False) source = models.CharField(max_length=100) privacy = models.CharField( max_length=255, default="public", choices=PrivacyLevels.choices ) retry = models.BooleanField(default=False) + @property + def pending_items(self): + """items that haven't been processed yet""" + return self.items.filter(fail_reason__isnull=True, book__isnull=True) + class ImportItem(models.Model): """a single line of a csv being imported""" @@ -67,10 +72,13 @@ class ImportItem(models.Model): ) def update_job(self): - """this user is here! they are doing things!""" - self.job.completed_count += 1 - self.job.updated_date = timezone.now() - self.job.save() + """let the job know when the items get work done""" + job = self.job + job.updated_date = timezone.now() + job.save() + if not job.pending_items.exists() and not job.complete: + job.complete = True + job.save(update_fields=["complete"]) def resolve(self): """try various ways to lookup a book""" diff --git a/bookwyrm/models/notification.py b/bookwyrm/models/notification.py index 2f1aae4f3..417bf7591 100644 --- a/bookwyrm/models/notification.py +++ b/bookwyrm/models/notification.py @@ -157,9 +157,12 @@ def notify_user_on_unboost(sender, instance, *args, **kwargs): @receiver(models.signals.post_save, sender=ImportJob) # pylint: disable=unused-argument -def notify_user_on_import_complete(sender, instance, *args, **kwargs): +def notify_user_on_import_complete( + sender, instance, *args, update_fields=None, **kwargs +): """we imported your books! aren't you proud of us""" - if not instance.complete: + update_fields = update_fields or [] + if not instance.complete or "complete" not in update_fields: return Notification.objects.create( user=instance.user, diff --git a/bookwyrm/tests/importers/test_importer.py b/bookwyrm/tests/importers/test_importer.py index 6996a92b5..3fbfa2648 100644 --- a/bookwyrm/tests/importers/test_importer.py +++ b/bookwyrm/tests/importers/test_importer.py @@ -145,7 +145,40 @@ class GenericImporter(TestCase): self.assertEqual(kwargs["queue"], "low_priority") import_item.refresh_from_db() - self.assertEqual(import_item.book.id, self.book.id) + def test_complete_job(self, *_): + """test notification""" + import_job = self.importer.create_job( + self.local_user, self.csv, False, "unlisted" + ) + item = import_job.items[0] + item.update_job() + self.assertFalse( + models.Notification.objects.filter( + user=self.local_user, + related_import=import_job, + notification_type="IMPORT", + ).exists() + ) + + item = import_job.items[1] + item.update_job() + self.assertFalse( + models.Notification.objects.filter( + user=self.local_user, + related_import=import_job, + notification_type="IMPORT", + ).exists() + ) + + item = import_job.items[2] + item.update_job() + self.assertTrue( + models.Notification.objects.filter( + user=self.local_user, + related_import=import_job, + notification_type="IMPORT", + ).exists() + ) def test_handle_imported_book(self, *_): """import added a book, this adds related connections""" diff --git a/bookwyrm/views/imports/import_status.py b/bookwyrm/views/imports/import_status.py index 2d18d656a..7e7d51792 100644 --- a/bookwyrm/views/imports/import_status.py +++ b/bookwyrm/views/imports/import_status.py @@ -24,7 +24,6 @@ class ImportStatus(View): raise PermissionDenied() items = job.items.order_by("index") - pending_items = items.filter(fail_reason__isnull=True, book__isnull=True) item_count = items.count() or 1 paginated = Paginator(items, PAGE_LENGTH) @@ -41,9 +40,9 @@ class ImportStatus(View): "page_range": paginated.get_elided_page_range( page.number, on_each_side=2, on_ends=1 ), - "complete": not pending_items.exists(), + "complete": not job.pending_items.exists(), "percent": math.floor( # pylint: disable=c-extension-no-member - (item_count - pending_items.count()) / item_count * 100 + (item_count - job.pending_items.count()) / item_count * 100 ), }