From 44020b80d6652124efe5827ff1d3444f22c81cc6 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Tue, 27 Oct 2020 15:23:49 +0100 Subject: [PATCH] Add work rates. --- src/catalogue/admin.py | 17 ++++- .../migrations/0023_workrate_worktype.py | 36 +++++++++++ .../migrations/0024_workrate_rate.py | 19 ++++++ .../migrations/0025_auto_20201027_1450.py | 28 +++++++++ .../migrations/0026_auto_20201027_1459.py | 24 +++++++ .../migrations/0027_auto_20201027_1501.py | 43 +++++++++++++ src/catalogue/models.py | 62 +++++++++++++++++++ 7 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 src/catalogue/migrations/0023_workrate_worktype.py create mode 100644 src/catalogue/migrations/0024_workrate_rate.py create mode 100644 src/catalogue/migrations/0025_auto_20201027_1450.py create mode 100644 src/catalogue/migrations/0026_auto_20201027_1459.py create mode 100644 src/catalogue/migrations/0027_auto_20201027_1501.py diff --git a/src/catalogue/admin.py b/src/catalogue/admin.py index 90759b0f..35345216 100644 --- a/src/catalogue/admin.py +++ b/src/catalogue/admin.py @@ -43,7 +43,7 @@ class BookAdmin(WikidataAdminMixin, admin.ModelAdmin): autocomplete_fields = ["authors", "translators", "based_on", "collections", "epochs", "genres", "kinds"] prepopulated_fields = {"slug": ("title",)} list_filter = ["language", "pd_year", "collections"] - readonly_fields = ["wikidata_link"] + readonly_fields = ["wikidata_link", "estimated_costs"] actions = [export_as_csv_action()] fieldsets = [ (None, {"fields": [("wikidata", "wikidata_link")]}), @@ -80,6 +80,8 @@ class BookAdmin(WikidataAdminMixin, admin.ModelAdmin): "priority", "collections", "notes", + ("estimated_chars", "estimated_verses", "estimate_source"), + "estimated_costs", ] }, ), @@ -122,3 +124,16 @@ class CategoryAdmin(admin.ModelAdmin): admin.site.register(models.Epoch, CategoryAdmin) admin.site.register(models.Genre, CategoryAdmin) admin.site.register(models.Kind, CategoryAdmin) + + + +class WorkRateInline(admin.TabularInline): + model = models.WorkRate + autocomplete_fields = ['kinds', 'genres', 'epochs', 'collections'] + + +class WorkTypeAdmin(admin.ModelAdmin): + inlines = [WorkRateInline] + +admin.site.register(models.WorkType, WorkTypeAdmin) + diff --git a/src/catalogue/migrations/0023_workrate_worktype.py b/src/catalogue/migrations/0023_workrate_worktype.py new file mode 100644 index 00000000..88556961 --- /dev/null +++ b/src/catalogue/migrations/0023_workrate_worktype.py @@ -0,0 +1,36 @@ +# Generated by Django 3.0.4 on 2020-10-27 14:37 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('catalogue', '0022_auto_20201027_1424'), + ] + + operations = [ + migrations.CreateModel( + name='WorkType', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ], + ), + migrations.CreateModel( + name='WorkRate', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('priority', models.IntegerField(default=1)), + ('collections', models.ManyToManyField(to='catalogue.Collection')), + ('epochs', models.ManyToManyField(to='catalogue.Epoch')), + ('genres', models.ManyToManyField(to='catalogue.Genre')), + ('kinds', models.ManyToManyField(to='catalogue.Kind')), + ('work_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='catalogue.WorkType')), + ], + options={ + 'ordering': ('priority',), + }, + ), + ] diff --git a/src/catalogue/migrations/0024_workrate_rate.py b/src/catalogue/migrations/0024_workrate_rate.py new file mode 100644 index 00000000..7c1fd829 --- /dev/null +++ b/src/catalogue/migrations/0024_workrate_rate.py @@ -0,0 +1,19 @@ +# Generated by Django 3.0.4 on 2020-10-27 14:40 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('catalogue', '0023_workrate_worktype'), + ] + + operations = [ + migrations.AddField( + model_name='workrate', + name='rate', + field=models.DecimalField(decimal_places=2, default=0, max_digits=6), + preserve_default=False, + ), + ] diff --git a/src/catalogue/migrations/0025_auto_20201027_1450.py b/src/catalogue/migrations/0025_auto_20201027_1450.py new file mode 100644 index 00000000..d9ce0873 --- /dev/null +++ b/src/catalogue/migrations/0025_auto_20201027_1450.py @@ -0,0 +1,28 @@ +# Generated by Django 3.0.4 on 2020-10-27 14:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('catalogue', '0024_workrate_rate'), + ] + + operations = [ + migrations.AddField( + model_name='book', + name='estimate_source', + field=models.CharField(blank=True, max_length=2048), + ), + migrations.AddField( + model_name='book', + name='estimated_chars', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='book', + name='estimated_verses', + field=models.IntegerField(blank=True, null=True), + ), + ] diff --git a/src/catalogue/migrations/0026_auto_20201027_1459.py b/src/catalogue/migrations/0026_auto_20201027_1459.py new file mode 100644 index 00000000..28a375cd --- /dev/null +++ b/src/catalogue/migrations/0026_auto_20201027_1459.py @@ -0,0 +1,24 @@ +# Generated by Django 3.0.4 on 2020-10-27 14:59 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('catalogue', '0025_auto_20201027_1450'), + ] + + operations = [ + migrations.RenameField( + model_name='workrate', + old_name='rate', + new_name='per_normpage', + ), + migrations.AddField( + model_name='workrate', + name='per_verse', + field=models.DecimalField(decimal_places=2, default=0, max_digits=6), + preserve_default=False, + ), + ] diff --git a/src/catalogue/migrations/0027_auto_20201027_1501.py b/src/catalogue/migrations/0027_auto_20201027_1501.py new file mode 100644 index 00000000..c5c8ca8a --- /dev/null +++ b/src/catalogue/migrations/0027_auto_20201027_1501.py @@ -0,0 +1,43 @@ +# Generated by Django 3.0.4 on 2020-10-27 15:01 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('catalogue', '0026_auto_20201027_1459'), + ] + + operations = [ + migrations.AlterField( + model_name='workrate', + name='collections', + field=models.ManyToManyField(blank=True, to='catalogue.Collection'), + ), + migrations.AlterField( + model_name='workrate', + name='epochs', + field=models.ManyToManyField(blank=True, to='catalogue.Epoch'), + ), + migrations.AlterField( + model_name='workrate', + name='genres', + field=models.ManyToManyField(blank=True, to='catalogue.Genre'), + ), + migrations.AlterField( + model_name='workrate', + name='kinds', + field=models.ManyToManyField(blank=True, to='catalogue.Kind'), + ), + migrations.AlterField( + model_name='workrate', + name='per_normpage', + field=models.DecimalField(blank=True, decimal_places=2, max_digits=6, null=True), + ), + migrations.AlterField( + model_name='workrate', + name='per_verse', + field=models.DecimalField(blank=True, decimal_places=2, max_digits=6, null=True), + ), + ] diff --git a/src/catalogue/models.py b/src/catalogue/models.py index 682e97bc..bb738a26 100644 --- a/src/catalogue/models.py +++ b/src/catalogue/models.py @@ -1,3 +1,4 @@ +import decimal from django.apps import apps from django.db import models from django.urls import reverse @@ -77,6 +78,8 @@ class Category(WikidataMixin, models.Model): class Meta: abstract = True + def __str__(self): + return self.name class Epoch(Category): class Meta: @@ -123,6 +126,10 @@ class Book(WikidataMixin, models.Model): gazeta_link = models.CharField(max_length=255, blank=True) collections = models.ManyToManyField("Collection", blank=True) + estimated_chars = models.IntegerField(null=True, blank=True) + estimated_verses = models.IntegerField(null=True, blank=True) + estimate_source = models.CharField(max_length=2048, blank=True) + objects = UnrelatedManager() class Meta: @@ -161,6 +168,15 @@ class Book(WikidataMixin, models.Model): DBook = apps.get_model("documents", "Book") return DBook.objects.filter(dc_slug=self.slug) + def estimated_costs(self): + return "\n".join( + "{}: {} zł".format( + work_type.name, + work_type.calculate(self) or '—' + ) + for work_type in WorkType.objects.all() + ) + class Collection(models.Model): name = models.CharField(max_length=255) @@ -173,3 +189,49 @@ class Collection(models.Model): def __str__(self): return self.name + +class WorkType(models.Model): + name = models.CharField(max_length=255) + + def get_rate_for(self, book): + for workrate in self.workrate_set.all(): + if workrate.matches(book): + return workrate + + def calculate(self, book): + workrate = self.get_rate_for(book) + if workrate is not None: + return workrate.calculate(book) + + + +class WorkRate(models.Model): + priority = models.IntegerField(default=1) + per_normpage = models.DecimalField(decimal_places=2, max_digits=6, null=True, blank=True) + per_verse = models.DecimalField(decimal_places=2, max_digits=6, null=True, blank=True) + work_type = models.ForeignKey(WorkType, models.CASCADE) + epochs = models.ManyToManyField(Epoch, blank=True) + kinds = models.ManyToManyField(Kind, blank=True) + genres = models.ManyToManyField(Genre, blank=True) + collections = models.ManyToManyField(Collection, blank=True) + + class Meta: + ordering = ('priority',) + + def matches(self, book): + for category in 'epochs', 'kinds', 'genres', 'collections': + oneof = getattr(self, category).all() + if oneof: + if not set(oneof).intersection( + getattr(book, category).all()): + return False + return True + + def calculate(self, book): + if self.per_verse: + if book.estimated_verses: + return book.estimated_verses * self.per_verse + elif self.per_normpage: + if book.estimated_chars: + return (decimal.Decimal(book.estimated_chars) / 1800 * self.per_normpage).quantize(decimal.Decimal('1.00'), rounding=decimal.ROUND_HALF_UP) + -- 2.20.1