Add sellable flag for audiobooks.
authorRadek Czajka <rczajka@rczajka.pl>
Fri, 24 Apr 2026 11:44:08 +0000 (13:44 +0200)
committerRadek Czajka <rczajka@rczajka.pl>
Fri, 24 Apr 2026 11:44:08 +0000 (13:44 +0200)
src/catalogue/migrations/0057_book_can_sell_mp3.py [new file with mode: 0644]
src/catalogue/models/book.py
src/partners/api/views.py

diff --git a/src/catalogue/migrations/0057_book_can_sell_mp3.py b/src/catalogue/migrations/0057_book_can_sell_mp3.py
new file mode 100644 (file)
index 0000000..900053d
--- /dev/null
@@ -0,0 +1,18 @@
+# Generated by Django 4.0.8 on 2026-04-24 11:40
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('catalogue', '0056_book_isbn_mp3'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='book',
+            name='can_sell_mp3',
+            field=models.BooleanField(default=True, verbose_name='do sprzedaży mp3'),
+        ),
+    ]
index fddce42..d0487cd 100644 (file)
@@ -7,6 +7,7 @@ from datetime import date, timedelta
 from random import randint
 import os.path
 import re
 from random import randint
 import os.path
 import re
+import requests
 from slugify import slugify
 from sortify import sortify
 from urllib.request import urlretrieve
 from slugify import slugify
 from sortify import sortify
 from urllib.request import urlretrieve
@@ -62,6 +63,7 @@ class Book(models.Model):
     preview_key = models.CharField(max_length=32, blank=True, null=True)
     findable = models.BooleanField('wyszukiwalna', default=True, db_index=True)
     can_sell = models.BooleanField('do sprzedaży', default=True)
     preview_key = models.CharField(max_length=32, blank=True, null=True)
     findable = models.BooleanField('wyszukiwalna', default=True, db_index=True)
     can_sell = models.BooleanField('do sprzedaży', default=True)
+    can_sell_mp3 = models.BooleanField('do sprzedaży mp3', default=True)
     isbn_mp3 = models.CharField('ISBN audiobooka', max_length=32, blank=True)
 
     # files generated during publication
     isbn_mp3 = models.CharField('ISBN audiobooka', max_length=32, blank=True)
 
     # files generated during publication
@@ -909,6 +911,18 @@ class Book(models.Model):
             narrators.append(t)
         self.narrators.set(narrators)
 
             narrators.append(t)
         self.narrators.set(narrators)
 
+    def update_can_sell_mp3(self):
+        ret = True
+        for child in self.get_children():
+            child.update_can_sell_mp3()
+            if not child.can_sell_mp3:
+                ret = False
+        if self.has_mp3_file():
+            audio_items = requests.get(f'https://audio.wolnelektury.pl/archive/book/{self.slug}.json').json()['items']
+            if not all(x['project']['can_sell'] for x in audio_items):
+                ret = False
+        self.can_sell_audio = ret
+
     @classmethod
     @transaction.atomic
     def repopulate_ancestors(cls):
     @classmethod
     @transaction.atomic
     def repopulate_ancestors(cls):
index a2e1de5..5309380 100644 (file)
@@ -75,10 +75,10 @@ class PartnerAudiobookSerializer(BookSerializer2):
             for c in b.get_children():
                 fs.extend(get_for_single(c))
             return fs
             for c in b.get_children():
                 fs.extend(get_for_single(c))
             return fs
-        return get_for_single(b)
+        return get_for_single(obj)
 
     def get_price(self, obj):
 
     def get_price(self, obj):
-        duration = obj.get_audiobooks(True)[2]
+        duration = obj.get_audiobooks(True, True)[2]
         if not duration:
             return None
         duration /= 60
         if not duration:
             return None
         duration /= 60
@@ -108,4 +108,4 @@ class PartnerAudiobooksView(ListAPIView):
         return ctx
 
     def get_queryset(self):
         return ctx
 
     def get_queryset(self):
-        return Book.objects.exclude(isbn_mp3='')
+        return Book.objects.filter(parent=None, can_sell_mp3=True).exclude(isbn_mp3='')