Notify when import completes
This commit is contained in:
parent
47b98ad0d9
commit
f92863ad3e
|
@ -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),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -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),
|
||||||
|
),
|
||||||
|
]
|
|
@ -38,13 +38,18 @@ class ImportJob(models.Model):
|
||||||
include_reviews = models.BooleanField(default=True)
|
include_reviews = models.BooleanField(default=True)
|
||||||
mappings = models.JSONField()
|
mappings = models.JSONField()
|
||||||
updated_date = models.DateTimeField(default=timezone.now)
|
updated_date = models.DateTimeField(default=timezone.now)
|
||||||
completed_count = models.IntegerField(default=0)
|
complete = models.BooleanField(default=False)
|
||||||
source = models.CharField(max_length=100)
|
source = models.CharField(max_length=100)
|
||||||
privacy = models.CharField(
|
privacy = models.CharField(
|
||||||
max_length=255, default="public", choices=PrivacyLevels.choices
|
max_length=255, default="public", choices=PrivacyLevels.choices
|
||||||
)
|
)
|
||||||
retry = models.BooleanField(default=False)
|
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):
|
class ImportItem(models.Model):
|
||||||
"""a single line of a csv being imported"""
|
"""a single line of a csv being imported"""
|
||||||
|
@ -67,10 +72,13 @@ class ImportItem(models.Model):
|
||||||
)
|
)
|
||||||
|
|
||||||
def update_job(self):
|
def update_job(self):
|
||||||
"""this user is here! they are doing things!"""
|
"""let the job know when the items get work done"""
|
||||||
self.job.completed_count += 1
|
job = self.job
|
||||||
self.job.updated_date = timezone.now()
|
job.updated_date = timezone.now()
|
||||||
self.job.save()
|
job.save()
|
||||||
|
if not job.pending_items.exists() and not job.complete:
|
||||||
|
job.complete = True
|
||||||
|
job.save(update_fields=["complete"])
|
||||||
|
|
||||||
def resolve(self):
|
def resolve(self):
|
||||||
"""try various ways to lookup a book"""
|
"""try various ways to lookup a book"""
|
||||||
|
|
|
@ -157,9 +157,12 @@ def notify_user_on_unboost(sender, instance, *args, **kwargs):
|
||||||
|
|
||||||
@receiver(models.signals.post_save, sender=ImportJob)
|
@receiver(models.signals.post_save, sender=ImportJob)
|
||||||
# pylint: disable=unused-argument
|
# 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"""
|
"""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
|
return
|
||||||
Notification.objects.create(
|
Notification.objects.create(
|
||||||
user=instance.user,
|
user=instance.user,
|
||||||
|
|
|
@ -145,7 +145,40 @@ class GenericImporter(TestCase):
|
||||||
self.assertEqual(kwargs["queue"], "low_priority")
|
self.assertEqual(kwargs["queue"], "low_priority")
|
||||||
import_item.refresh_from_db()
|
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, *_):
|
def test_handle_imported_book(self, *_):
|
||||||
"""import added a book, this adds related connections"""
|
"""import added a book, this adds related connections"""
|
||||||
|
|
|
@ -24,7 +24,6 @@ class ImportStatus(View):
|
||||||
raise PermissionDenied()
|
raise PermissionDenied()
|
||||||
|
|
||||||
items = job.items.order_by("index")
|
items = job.items.order_by("index")
|
||||||
pending_items = items.filter(fail_reason__isnull=True, book__isnull=True)
|
|
||||||
item_count = items.count() or 1
|
item_count = items.count() or 1
|
||||||
|
|
||||||
paginated = Paginator(items, PAGE_LENGTH)
|
paginated = Paginator(items, PAGE_LENGTH)
|
||||||
|
@ -41,9 +40,9 @@ class ImportStatus(View):
|
||||||
"page_range": paginated.get_elided_page_range(
|
"page_range": paginated.get_elided_page_range(
|
||||||
page.number, on_each_side=2, on_ends=1
|
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
|
"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
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue