diff --git a/server/users/licenses.py b/server/users/licenses.py index 57447d7c..4ec25f5c 100644 --- a/server/users/licenses.py +++ b/server/users/licenses.py @@ -9,7 +9,7 @@ MYSKILLBOX_LICENSES = { }, "978-3-0355-1860-3": { 'edition': STUDENT_KEY, - 'duration': 455, + 'duration': 365, 'name': 'Student 1 year' }, "978-3-0355-1862-7": { @@ -24,7 +24,7 @@ MYSKILLBOX_LICENSES = { }, "978-3-0355-1823-8": { 'edition': TEACHER_KEY, - 'duration': 455, + 'duration': 365, 'name': 'Teacher 1 year' } } diff --git a/server/users/management/commands/__init__.py b/server/users/management/commands/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/server/users/management/commands/reset_license_duration.py b/server/users/management/commands/reset_license_duration.py index 61f21402..9b66f3d5 100644 --- a/server/users/management/commands/reset_license_duration.py +++ b/server/users/management/commands/reset_license_duration.py @@ -1,11 +1,21 @@ +import json +from datetime import datetime, date + from django.utils.timezone import now from django.core.management.base import BaseCommand +from users.licenses import MYSKILLBOX_LICENSES from users.models import License +YEARLY_ISBNS = ["978-3-0355-1860-3", "978-3-0355-1823-8"] +LONGER_DURATION = 455 + class Command(BaseCommand): - help = 'Reset licenses that have a duration that is longer than the standard duration' + help = """ + Reset licenses that have a duration of one year + Uses the duration of MYSKILLBOX_LICENSES as reference. + """ def add_arguments(self, parser): parser.add_argument('--dry-run', action='store_true', dest='save', default=False, help='Make dry-run') @@ -14,4 +24,27 @@ class Command(BaseCommand): today = now().date() for license in License.objects.filter(expire_date__gte=today): - print(license) + isbn = license.get_isbn() + if isbn not in YEARLY_ISBNS: + continue + + defined_duration = MYSKILLBOX_LICENSES[isbn]['duration'] # use isbn from hep due to our bug + start_date = license.get_hep_start_date() + duration_in_days = (license.expire_date - start_date).days + if duration_in_days == defined_duration: + continue + + user_join_delta = (license.expire_date - license.licensee.date_joined.date()).days + + if self._is_change_candidate(user_join_delta, duration_in_days, start_date): + print(license.id, duration_in_days, defined_duration, license.expire_date, start_date, user_join_delta) + + def _is_change_candidate(self, user_join_delta: int, duration_in_days: int, start_date: date) -> bool: + """ + user_join_delta == LONGER_DURATION: user joined the same number of days as the old duration was + duration_in_days == LONGER_DURATION: delta from start date and expiry date is the same as the old duration + start_date == NO_DATE: license does not have a start date -> was created after moving to new api as + such it the longer duration was set as duration + """ + return user_join_delta == LONGER_DURATION or duration_in_days == LONGER_DURATION \ + or start_date == License.NO_DATE diff --git a/server/users/models.py b/server/users/models.py index a6877966..794999d5 100644 --- a/server/users/models.py +++ b/server/users/models.py @@ -1,3 +1,4 @@ +import json import random import re import string @@ -308,6 +309,8 @@ class License(models.Model): objects = LicenseManager() + NO_DATE = date(2011, 10, 7) # used to tag licenses without start date + def is_teacher_license(self): return self.for_role.key == RoleManager.TEACHER_KEY @@ -315,6 +318,27 @@ class License(models.Model): date = make_aware(datetime(self.expire_date.year, self.expire_date.month, self.expire_date.day)) return License.is_product_active(date, self.isbn) + def _read_as_json(self, raw_string: str) -> dict: + return json.loads(raw_string.replace("'", '"').replace('True', 'true').replace('False', 'false') + .replace('None', 'null')) + + def get_hep_start_date(self) -> date: + hep_data = self._read_as_json(self.raw) + if 'updated_at' in hep_data: # old key from Magento. Format: 2020-06-22 18:45:13 + date_string = hep_data['created_at'] + return datetime.strptime(date_string, '%Y-%m-%d %H:%M:%S').date() + + return License.NO_DATE + + def get_isbn(self) -> str: + hep_data = self._read_as_json(self.raw) + if 'sku' in hep_data: # Magento key + return hep_data['sku'] + elif 'isbn' in hep_data: # new shop key + return hep_data['isbn'] + else: + return '' + @staticmethod def is_product_active(expiry_date, isbn): now = timezone.now()