Repository: bookwyrm-social/bookwyrm

Issue:
Reviews are duplicated when importing more than once
This is likely to happen when some book imports are failing and people try again (like I did).

Steps to reproduce the behavior:

1. [Log in](https://bookwyrm.social/login).
2. Go to the [import page](https://bookwyrm.social/import).
3. Import books with “Include reviews” checked.
4. Repeat the import.
5. Watch reviews appear twice in feeds. (exemple today: https://bookwyrm.social/user/arkhi)

**Expected behavior**

1. [Log in](https://bookwyrm.social/login).
2. Go to the [import page](https://bookwyrm.social/import).
3. Import books with “Include reviews” checked.
4. Repeat the import.
5. Reviews only appear once in feeds.


Discussion:
So what is the correct thing to do when book imports fail? I don't want to have a thousand duplicate things imported.

I got the TASK FAILED message from my import. Is this what you mean by 'import failed'?
@tootbrute I'll try and figure out why the task failed! That's not the normal "sorry, couldn't find the book" error state. Did any of your items import? If not, you can safely re-run the import without risk of duplicating reviews. 
> @tootbrute I'll try and figure out why the task failed! That's not the normal "sorry, couldn't find the book" error state. Did any of your items import? If not, you can safely re-run the import without risk of duplicating reviews.

Trying not to thread hijack here but...

I'm trying to import a goodreads.csv with 1999 entries in the spreadsheet.
Now it doesn't say TASK FAILED, but it says it's still in progress. It also says 679 failed to import, which is almost half my books :/

![Screenshot from 2021-11-08 18-55-40](https://user-images.githubusercontent.com/47593393/140730497-ce8b7986-a8a1-45bc-bd18-736e8edc2866.png)
 
![Screenshot from 2021-11-08 18-56-08](https://user-images.githubusercontent.com/47593393/140730508-37b8ef28-f761-49d9-bdd4-eea65da3ddb3.png)

1. Is there some documentation to read about how importing works?
2. What happens to the books that failed to import? Do I have to manually input them? If so, that is a major hurdle to jumping over from GoodReads
3. If I re-import the CSV file, will it create duplicate entries?
When your import finishes, there will be an option to re-try only the items that didn't import. I've temporarily disabled imports because it's causing some side issues, but your import data will still be there once it's back and you'll be able to fix the missing entries automatically where possible (which it should be in most cases, those look like common enough books that they should import on their own).

Resolving patch:
diff --git a/bookwyrm/importers/importer.py b/bookwyrm/importers/importer.py
--- a/bookwyrm/importers/importer.py
+++ b/bookwyrm/importers/importer.py
@@ -205,3 +205,5 @@ def handle_imported_book(item):
             )
         # only broadcast this review to other bookwyrm instances
         review.save(software="bookwyrm", priority=LOW)
+        item.linked_review = review
+        item.save()
diff --git a/bookwyrm/migrations/0115_importitem_linked_review.py b/bookwyrm/migrations/0115_importitem_linked_review.py
new file mode 100644
--- /dev/null
+++ b/bookwyrm/migrations/0115_importitem_linked_review.py
@@ -0,0 +1,24 @@
+# Generated by Django 3.2.5 on 2021-11-13 19:35
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("bookwyrm", "0114_importjob_source"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="importitem",
+            name="linked_review",
+            field=models.ForeignKey(
+                blank=True,
+                null=True,
+                on_delete=django.db.models.deletion.SET_NULL,
+                to="bookwyrm.review",
+            ),
+        ),
+    ]
diff --git a/bookwyrm/models/import_job.py b/bookwyrm/models/import_job.py
--- a/bookwyrm/models/import_job.py
+++ b/bookwyrm/models/import_job.py
@@ -60,6 +60,9 @@ class ImportItem(models.Model):
         related_name="book_guess",
     )
     fail_reason = models.TextField(null=True)
+    linked_review = models.ForeignKey(
+        "Review", on_delete=models.SET_NULL, null=True, blank=True
+    )
 
     def resolve(self):
         """try various ways to lookup a book"""


Test patch:
diff --git a/bookwyrm/tests/importers/test_importer.py b/bookwyrm/tests/importers/test_importer.py
--- a/bookwyrm/tests/importers/test_importer.py
+++ b/bookwyrm/tests/importers/test_importer.py
@@ -233,6 +233,9 @@ def test_handle_imported_book_review(self, *_):
         self.assertEqual(review.rating, 2.0)
         self.assertEqual(review.privacy, "unlisted")
 
+        import_item.refresh_from_db()
+        self.assertEqual(import_item.linked_review, review)
+
     @patch("bookwyrm.activitystreams.add_status_task.delay")
     def test_handle_imported_book_rating(self, *_):
         """rating import"""
@@ -250,6 +253,9 @@ def test_handle_imported_book_rating(self, *_):
         self.assertEqual(review.rating, 3.0)
         self.assertEqual(review.privacy, "unlisted")
 
+        import_item.refresh_from_db()
+        self.assertEqual(import_item.linked_review.id, review.id)
+
     def test_handle_imported_book_reviews_disabled(self, *_):
         """review import"""
         import_job = self.importer.create_job(