Add missing constraint.
[wolnelektury.git] / src / isbn / models.py
1 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
2 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
3 #
4 from django.db import models
5 from django.db.models import F
6
7
8 class ISBNPool(models.Model):
9     PURPOSE_WL = 'WL'
10     PURPOSE_FNP = 'FNP'
11     PURPOSE_CHOICES = (
12         (PURPOSE_WL, 'Wolne Lektury'),
13         (PURPOSE_FNP, 'Fundacja Nowoczesna Polska'),
14     )
15
16     prefix = models.CharField(max_length=10)
17     suffix_from = models.IntegerField()
18     suffix_to = models.IntegerField()
19     ref_from = models.IntegerField()
20     next_suffix = models.IntegerField()
21     purpose = models.CharField(max_length=4, choices=PURPOSE_CHOICES)
22
23     def __str__(self):
24         return self.prefix
25
26     @classmethod
27     def active_pool(cls, purpose):
28         pools = cls.objects.filter(purpose=purpose)
29         pools = pools.exclude(next_suffix__gt=F('suffix_to'))
30         if len(pools) == 1:
31             return pools.get()
32         else:
33             pools.exclude(next_suffix=F('suffix_from'))
34             return pools.get()
35
36     @staticmethod
37     def check_digit(prefix12):
38         digits = [int(d) for d in prefix12]
39         return str((-sum(digits[0::2]) + 7 * sum(digits[1::2])) % 10)
40
41     def isbn(self, suffix, dashes=False):
42         prefix_length = len(self.prefix)
43         suffix_length = 12 - prefix_length
44         suffix_str = ('%%0%dd' % suffix_length) % suffix
45         prefix12 = self.prefix + suffix_str
46         if dashes:
47             prefix12_final = '%s-%s-%s-%s-' % (self.prefix[:3], self.prefix[3:5], self.prefix[5:], suffix_str)
48         else:
49             prefix12_final = prefix12
50         return prefix12_final + self.check_digit(prefix12)
51
52
53 class ONIXRecord(models.Model):
54     isbn_pool = models.ForeignKey(ISBNPool, models.PROTECT)
55     datestamp = models.DateField(auto_now=True)
56     suffix = models.IntegerField()
57     product_form = models.CharField(max_length=4)
58     product_form_detail = models.CharField(max_length=8, blank=True)
59     title = models.CharField(max_length=256)
60     part_number = models.CharField(max_length=64, blank=True)
61     contributors = models.TextField()  # roles, names, optional: ISNI, date of birth/death
62     edition_type = models.CharField(max_length=4)
63     edition_number = models.IntegerField(default=1)
64     language = models.CharField(max_length=4)
65     imprint = models.CharField(max_length=256)
66     publishing_date = models.DateField()
67     dc_slug = models.CharField(max_length=256, default='', db_index=True)
68
69     class Meta:
70         ordering = ['isbn_pool__id', 'suffix']
71         unique_together = ['isbn_pool', 'suffix']
72
73     @classmethod
74     def new_record(cls, purpose, data):
75         pool = ISBNPool.active_pool(purpose)
76         fields = {
77             'isbn_pool': pool,
78             'suffix': pool.next_suffix,
79         }
80         fields_to_copy = [
81             'product_form',
82             'product_form_detail',
83             'title',
84             'part_number',
85             'contributors',  # ???
86             'edition_type',
87             'edition_number',
88             'language',
89             'imprint',
90             'publishing_date',
91             'dc_slug',
92         ]
93         for field in fields_to_copy:
94             if field in data:
95                 fields[field] = data[field]
96         cls.objects.create(**fields)
97         pool.next_suffix += 1
98         pool.save()
99
100     def isbn(self, dashes=False):
101         return self.isbn_pool.isbn(self.suffix, dashes=dashes)
102
103     def reference(self):
104         return 'pl-eisbn-%s' % (self.isbn_pool.ref_from + self.suffix)