Repository: bookwyrm-social/bookwyrm

Issue:
CSV export does not include read date
**Describe the bug**
When exporting data into a CSV file, several fields are exported, but `read date` is not one of them, despite being exremelly valuable.

**To Reproduce**
Steps to reproduce the behavior:
1. Go to 'Profile'
2. Click on 'Export to CSV'
3. Download CSV file
4. Open CSV file

**Expected behavior**
A column containing read date should be included among the current ones

**Instance**
bookwyrm.social



---

**Desktop (please complete the following information):**
    - OS: KDE Neon
    - Browser Firefox, Chromium
    - Version 



Discussion:
I've been wanting to contribute o bookywrm for a while, and I suspect this could be a good first issue,

I believe here might be the problem: https://github.com/bookwyrm-social/bookwyrm/blob/e5f8e4babc3cc11ac7eb5b1bdbd5bdc9ced48fd2/bookwyrm/views/preferences/export.py#L32-L38

However,  I'm no very good at python and never worked with django, so I'm not sure what should I do next. I believe that with little guidance I'd be able to fix that myself.

Welcome @ccamara! I can help you with this.

The line you've pointed to is creating a `set` of books based on a series of searches. We're already bringing in `books_readthrough` so that tells us all the books the user has some kind of reading activity for. So we have the books, but we need the `ReadThrough` data.

The way to do that is probably to follow the pattern used for finding reviews and adding review data to the export: https://github.com/bookwyrm-social/bookwyrm/blob/e5f8e4babc3cc11ac7eb5b1bdbd5bdc9ced48fd2/bookwyrm/views/preferences/export.py#L67 There are more efficient ways to do this since not every book will have a ReadThrough, but most will and this is the easiest way to do it without rewriting half the export function.

Check out `models.ReadThroughs` to see what information is available. You can see we would get a number of different dates, and a `progress_mode`. Perhaps we want to export all of that so it's clear what the date relates to (i.e. "stopped" date is very different to "read" date). If you did that you would need to [add those to the `fields`](https://github.com/bookwyrm-social/bookwyrm/blob/e5f8e4babc3cc11ac7eb5b1bdbd5bdc9ced48fd2/bookwyrm/views/preferences/export.py#L48) so there's an appropriate header and column in the CSV

There is another issue here: https://github.com/bookwyrm-social/bookwyrm/issues/2846 which is about adding the shelf name in the export. Including the ReadThrough `progress_mode` would go some way to resolving this but not include custom shelves. You don't need to worry about this as I don't want to scope-creep your first contribution, I'm just mentioning it for completeness and so the issues get linked.

Resolving patch:
diff --git a/bookwyrm/views/preferences/export.py b/bookwyrm/views/preferences/export.py
--- a/bookwyrm/views/preferences/export.py
+++ b/bookwyrm/views/preferences/export.py
@@ -17,7 +17,7 @@
 from bookwyrm.models.bookwyrm_export_job import BookwyrmExportJob
 from bookwyrm.settings import PAGE_LENGTH
 
-# pylint: disable=no-self-use
+# pylint: disable=no-self-use,too-many-locals
 @method_decorator(login_required, name="dispatch")
 class Export(View):
     """Let users export data"""
@@ -54,6 +54,7 @@ def post(self, request):
         fields = (
             ["title", "author_text"]
             + deduplication_fields
+            + ["start_date", "finish_date", "stopped_date"]
             + ["rating", "review_name", "review_cw", "review_content"]
         )
         writer.writerow(fields)
@@ -70,6 +71,24 @@ def post(self, request):
 
             book.rating = review_rating.rating if review_rating else None
 
+            readthrough = (
+                models.ReadThrough.objects.filter(user=request.user, book=book)
+                .order_by("-start_date", "-finish_date")
+                .first()
+            )
+            if readthrough:
+                book.start_date = (
+                    readthrough.start_date.date() if readthrough.start_date else None
+                )
+                book.finish_date = (
+                    readthrough.finish_date.date() if readthrough.finish_date else None
+                )
+                book.stopped_date = (
+                    readthrough.stopped_date.date()
+                    if readthrough.stopped_date
+                    else None
+                )
+
             review = (
                 models.Review.objects.filter(
                     user=request.user, book=book, content__isnull=False


Test patch:
diff --git a/bookwyrm/tests/views/preferences/test_export.py b/bookwyrm/tests/views/preferences/test_export.py
--- a/bookwyrm/tests/views/preferences/test_export.py
+++ b/bookwyrm/tests/views/preferences/test_export.py
@@ -66,7 +66,7 @@ def test_export_file(self, *_):
         # pylint: disable=line-too-long
         self.assertEqual(
             export.content,
-            b"title,author_text,remote_id,openlibrary_key,inventaire_id,librarything_key,goodreads_key,bnf_id,viaf,wikidata,asin,aasin,isfdb,isbn_10,isbn_13,oclc_number,rating,review_name,review_cw,review_content\r\nTest Book,,"
+            b"title,author_text,remote_id,openlibrary_key,inventaire_id,librarything_key,goodreads_key,bnf_id,viaf,wikidata,asin,aasin,isfdb,isbn_10,isbn_13,oclc_number,start_date,finish_date,stopped_date,rating,review_name,review_cw,review_content\r\nTest Book,,"
             + self.book.remote_id.encode("utf-8")
-            + b",,,,,beep,,,,,,123456789X,9781234567890,,,,,\r\n",
+            + b",,,,,beep,,,,,,123456789X,9781234567890,,,,,,,,\r\n",
         )