Commit 9e2d7930 authored by Thom Wiggers's avatar Thom Wiggers 📐
Browse files

Merge branch 'feature/import-events' into 'master'

Import events



See merge request !126
parents 6c17201c 23b55148
......@@ -15,6 +15,11 @@ This is taken care of during member migration.
## Events
Make sure that the API key is available as `EVENTS_MIGRATION_KEY` in settings.py.
To migrate the events, make sure that members, committees and boards
have been migrated. Then simply execute `python manage.py migrateevents`.
## Mailing lists
Make sure that the API key is available as `MIGRATION_KEY` in settings.py.
......
from django import forms
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import get_language, ugettext_lazy as _
from .models import RegistrationInformationField
class RegistrationInformationFieldForm(forms.ModelForm):
order = forms.IntegerField(label=_('order'), initial=0)
class Meta:
......@@ -36,8 +35,10 @@ class FieldsForm(forms.Form):
elif field.type == RegistrationInformationField.TEXT_FIELD:
self.fields[key] = forms.CharField()
self.fields[key].label = field.name
self.fields[key].help_text = field.description
self.fields[key].label = getattr(field, '{}_{}'.format(
'name', get_language()))
self.fields[key].help_text = getattr(field, '{}_{}'.format(
'description', get_language()))
self.fields[key].initial = information_field['value']
if not field.type == RegistrationInformationField.BOOLEAN_FIELD:
self.fields[key].required = field.required
......
import re
import json
import requests
from django.contrib.auth.models import User
from datetime import datetime
from django.core.management.base import BaseCommand
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.utils import timezone
import events.models as events_models
import members.models as members_models
FIELD_DATA_TYPES = {
'0': events_models.RegistrationInformationField.TEXT_FIELD,
'1': events_models.RegistrationInformationField.INTEGER_FIELD,
'2': events_models.RegistrationInformationField.BOOLEAN_FIELD,
}
def naive_to_aware(date_string):
"""Convert string of form '%Y-%m-%d %H:%M:%S'
to timezone aware datetime object"""
naive_datetime = datetime.strptime(date_string, '%Y-%m-%d %H:%M:%S')
return timezone.get_current_timezone().localize(naive_datetime)
class Command(BaseCommand):
help = 'Migrate the events from the old website.'
def handle(self, *args, **options):
if not settings.EVENTS_MIGRATION_KEY:
raise ImproperlyConfigured('EVENTS_MIGRATION_KEY not specified')
events_api_url = 'https://thalia.nu/events/api/?apikey={}'.format(
settings.EVENTS_MIGRATION_KEY)
print('[*]Getting events json data')
try:
response = requests.get(events_api_url,
headers={'User-Agent': 'The Donald'})
except requests.RequestException:
print('[!]Could not get {}'.format(events_api_url))
return
try:
data = response.json()
except json.decoder.JSONDecodeError:
print('[!]No json data found')
return
event_fields_translations = {
# name in data : name in model
'title': 'title',
'description': 'description',
'location': 'location',
'start_date': 'start',
'end_date': 'end',
'member_price': 'price',
'thalia_costs': 'cost',
'begin_registration': 'registration_start',
'end_registration': 'registration_end',
'end_cancel': 'cancel_deadline',
'registration_not_needed_message': 'no_registration_message',
}
activity_map = {}
registration_map = {}
information_field_map = {}
print('[*]Parsing event data.')
# Event
for event_data in data['events']:
new_event = events_models.Event(
published=bool(int(event_data['public'])),
max_participants=int(event_data['registration_limit']),
)
for concrete_field in event_fields_translations:
django_field = event_fields_translations[concrete_field]
concrete_data = event_data[concrete_field]
# MultilingualField
if django_field in (
'title', 'description', 'location',
'no_registration_message'):
for language_code in ('en', 'nl'):
django_multilingualfield = '{}_{}'.format(
django_field, language_code)
if not hasattr(new_event, django_multilingualfield):
print('[!]Could neither find {} nor {}'.format(
django_field, django_multilingualfield))
return
setattr(new_event, django_multilingualfield,
concrete_data)
# DateTimeField
elif concrete_data and django_field in (
'start', 'end', 'registration_start',
'registration_end',
'cancel_deadline'):
setattr(new_event, django_field,
naive_to_aware(concrete_data))
# DecimalField
elif django_field in ('price', 'cost'):
if re.match(r'[-+]?\d*\.?\d+$', concrete_data):
setattr(new_event, django_field, float(concrete_data))
else:
# TODO: is 0 the right value?
setattr(new_event, django_field, 0)
new_event.save()
activity_map[event_data['id']] = new_event.pk
print('[*]Parsing registration field data.')
# RegistrationInformationField
for field_data in data['extra_fields']:
new_registration_information_field = \
events_models.RegistrationInformationField(
# TODO: UGLY AF
name_en=field_data['field_name'],
name_nl=field_data['field_name'],
description_en=field_data['field_explanation'],
description_nl=field_data['field_explanation'],
type=FIELD_DATA_TYPES[field_data['data_type']],
required=True,
event=events_models.Event.objects.get(
pk=activity_map[field_data['activity_id']]
),
)
new_registration_information_field.save()
information_field_map[field_data['field_id']] = \
new_registration_information_field.pk
print('[*]Parsing registration data.')
# Registration
for registration_data in data['registrations']:
new_registration = events_models.Registration(
name=registration_data['name'],
date=naive_to_aware(registration_data['date']),
paid=bool(registration_data['paid']),
event=events_models.Event.objects.get(
pk=activity_map[registration_data['activity_id']]
),
)
username = registration_data['username']
if registration_data['username'] and User.objects.filter(
username=username).exists():
registration_user = User.objects.get(username=username)
new_registration.member = members_models.Member.objects.get(
user=registration_user)
cancelled_date = registration_data['canceled']
if cancelled_date:
new_registration.cancelled_date = naive_to_aware(
cancelled_date)
new_registration.save()
registration_map[registration_data['id']] = new_registration.pk
print('[*]Parsing registration field info data.')
# fields info
for field_info_data in data['extra_info']:
registration_field = events_models.RegistrationInformationField.\
objects.get(
pk=information_field_map[field_info_data['field_id']]
)
parameters = {
'registration': events_models.Registration.objects.get(
pk=registration_map[field_info_data['registration_id']]),
'field': registration_field,
}
if registration_field.type == events_models.\
RegistrationInformationField.TEXT_FIELD:
new_registration_information = events_models. \
TextRegistrationInformation(
value=field_info_data['value'],
**parameters
)
elif registration_field.type == events_models.\
RegistrationInformationField.BOOLEAN_FIELD:
value = False
if value and bool(int(field_info_data['value'])):
value = True
new_registration_information = \
events_models.BooleanRegistrationInformation(
value=value,
**parameters)
# registration_field.type == INTEGER_FIELD:
else:
new_registration_information = \
events_models.IntegerRegistrationInformation(
value=field_info_data['value'] or 0,
**parameters)
new_registration_information.save()
# -*- coding: utf-8 -*-
# Generated by Django 1.10 on 2016-10-22 09:42
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('events', '0007_auto_20161009_2352'),
]
operations = [
migrations.RenameField('registrationinformationfield',
'description', 'description_nl'),
migrations.RenameField('registrationinformationfield',
'name', 'name_nl'),
migrations.AddField(
model_name='registrationinformationfield',
name='description_en',
field=models.TextField(blank=True, null=True, verbose_name='description (EN)'),
),
migrations.AlterField(
model_name='registrationinformationfield',
name='description_nl',
field=models.TextField(blank=True, null=True, verbose_name='description (NL)'),
preserve_default=True,
),
migrations.AddField(
model_name='registrationinformationfield',
name='name_en',
field=models.CharField(default='', max_length=100,
verbose_name='field name (EN)'),
preserve_default=False,
),
migrations.AlterField(
model_name='registrationinformationfield',
name='name_nl',
field=models.CharField(max_length=100,
verbose_name='field name (NL)'),
preserve_default=True,
),
]
......@@ -118,7 +118,8 @@ class Event(models.Model, metaclass=ModelTranslateMeta):
return self.registrationinformationfield_set.count() > 0
def reached_participants_limit(self):
return self.max_participants <= self.registration_set.count()
return (self.max_participants is not None and
self.max_participants <= self.registration_set.count())
@property
def status(self):
......@@ -187,7 +188,7 @@ class Event(models.Model, metaclass=ModelTranslateMeta):
ordering = ('-start',)
class RegistrationInformationField(models.Model):
class RegistrationInformationField(models.Model, metaclass=ModelTranslateMeta):
"""Field description to ask for when registering"""
BOOLEAN_FIELD = 'boolean'
INTEGER_FIELD = 'integer'
......@@ -205,12 +206,14 @@ class RegistrationInformationField(models.Model):
max_length=10,
)
name = models.CharField(
name = MultilingualField(
models.CharField,
_('field name'),
max_length=100,
)
description = models.TextField(
description = MultilingualField(
models.TextField,
_('description'),
null=True,
blank=True,
......@@ -365,18 +368,16 @@ class AbstractRegistrationInformation(models.Model):
class BooleanRegistrationInformation(AbstractRegistrationInformation):
"""Checkbox information filled in by members when registring"""
"""Checkbox information filled in by members when registering"""
value = models.BooleanField()
class TextRegistrationInformation(AbstractRegistrationInformation):
"""Checkbox information filled in by members when registring"""
"""Checkbox information filled in by members when registering"""
value = models.TextField()
class IntegerRegistrationInformation(AbstractRegistrationInformation):
"""Checkbox information filled in by members when registring"""
"""Checkbox information filled in by members when registering"""
value = models.IntegerField()
......@@ -12,7 +12,7 @@ from django.utils import timezone
from django.utils.text import slugify
from django.utils.translation import ugettext_lazy as _, pgettext_lazy
from .models import Event, Registration
from .models import Event, Registration, RegistrationInformationField
from .forms import FieldsForm
......@@ -240,6 +240,12 @@ def registration(request, event_id, action=None):
obj.save()
form_field_values = form.field_values()
for field in form_field_values:
import pdb
pdb.set_trace()
if (field['field'].type ==
RegistrationInformationField.INTEGER_FIELD
and field['value'] is None):
field['value'] = 0
field['field'].set_value_for(obj,
field['value'])
else:
......
......@@ -50,10 +50,10 @@ class MultilingualField(object):
self.kwargs = kwargs
def _i18n_attr_accessor(attr):
def _i18n_attr_accessor(attr, lang):
def accessor(self):
return getattr(self, I18N_FIELD_FORMAT.format(attr, get_language()))
return getattr(self, I18N_FIELD_FORMAT.format(attr, lang))
return accessor
......@@ -95,7 +95,7 @@ class ModelTranslateMeta(models.base.ModelBase):
"by TranslateMeta.".format(attr_i18n))
dct[attr_i18n] = field.cls(*field.args, **field.kwargs)
fields.append(attr_i18n)
dct[attr] = property(_i18n_attr_accessor(attr))
dct[attr] = property(_i18n_attr_accessor(attr, get_language()))
default = I18N_FIELD_FORMAT.format(attr, settings.LANGUAGE_CODE)
if default not in dct:
raise ImproperlyConfigured("LANGUAGE_CODE not in LANGUAGES.")
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment