diff --git a/crm/templates/crm/event_form.html b/bizdev/templates/bizdev/event_form.html
similarity index 85%
rename from crm/templates/crm/event_form.html
rename to bizdev/templates/bizdev/event_form.html
index 534b611..74f2a10 100644
--- a/crm/templates/crm/event_form.html
+++ b/bizdev/templates/bizdev/event_form.html
@@ -1,4 +1,4 @@
-{% extends "crm/base.html" %} {% block content %}
+{% extends "bizdev/base.html" %} {% block content %}
@@ -14,7 +14,7 @@
Save Event
Cancel
diff --git a/crm/templates/crm/event_row.html b/bizdev/templates/bizdev/event_row.html
similarity index 71%
rename from crm/templates/crm/event_row.html
rename to bizdev/templates/bizdev/event_row.html
index 2042fef..a37fc7b 100644
--- a/crm/templates/crm/event_row.html
+++ b/bizdev/templates/bizdev/event_row.html
@@ -7,9 +7,9 @@
{{ event.date|date:"d/m/Y H:i" }}
-
Edit
+
Edit
diff --git a/crm/templates/crm/events.html b/bizdev/templates/bizdev/events.html
similarity index 66%
rename from crm/templates/crm/events.html
rename to bizdev/templates/bizdev/events.html
index 372ff23..feda717 100644
--- a/crm/templates/crm/events.html
+++ b/bizdev/templates/bizdev/events.html
@@ -1,23 +1,23 @@
-{% extends "crm/base.html" %}
-{% load crm_tags %}
+{% extends "bizdev/base.html" %}
+{% load bizdev_tags %}
{% block content %}
-{% if request.user|is_crm_manager %}
+{% if request.user|is_bizdev_manager %}
@@ -31,7 +31,7 @@
{% for event in completed_events %}
- {% include "crm/event_row.html" with event=event %}
+ {% include "bizdev/event_row.html" with event=event %}
{% empty %}
No completed events.
{% endfor %}
@@ -47,7 +47,7 @@
{% for event in planned_events %}
- {% include "crm/event_row.html" with event=event %}
+ {% include "bizdev/event_row.html" with event=event %}
{% empty %}
No planned events.
{% endfor %}
diff --git a/crm/templates/crm/prospect_form.html b/bizdev/templates/bizdev/prospect_form.html
similarity index 93%
rename from crm/templates/crm/prospect_form.html
rename to bizdev/templates/bizdev/prospect_form.html
index 334e8bf..c22dcd0 100644
--- a/crm/templates/crm/prospect_form.html
+++ b/bizdev/templates/bizdev/prospect_form.html
@@ -1,4 +1,4 @@
-{% extends "crm/base.html" %}
+{% extends "bizdev/base.html" %}
{% block head_title %}{{ first_title }}{% endblock %}
{% block first_title %}{{ first_title }}{% endblock %}
diff --git a/crm/templates/crm/prospect_list.html b/bizdev/templates/bizdev/prospect_list.html
similarity index 81%
rename from crm/templates/crm/prospect_list.html
rename to bizdev/templates/bizdev/prospect_list.html
index 0068867..7ccf716 100644
--- a/crm/templates/crm/prospect_list.html
+++ b/bizdev/templates/bizdev/prospect_list.html
@@ -1,4 +1,4 @@
-{% extends "crm/base.html" %}
+{% extends "bizdev/base.html" %}
{% load static %}
@@ -18,15 +18,15 @@
{% endfor %}
{{ filter.qs|length }} résultats
@@ -60,11 +60,11 @@
{% endfor %}
-
+
Edit
-
+
+ Event
@@ -77,5 +77,5 @@
{% endblock %}
{% block extra_js %}
-
+
{% endblock %}
diff --git a/crm/templates/crm/send_bulk_email.html b/bizdev/templates/bizdev/send_bulk_email.html
similarity index 91%
rename from crm/templates/crm/send_bulk_email.html
rename to bizdev/templates/bizdev/send_bulk_email.html
index 53bdfac..f1b9200 100644
--- a/crm/templates/crm/send_bulk_email.html
+++ b/bizdev/templates/bizdev/send_bulk_email.html
@@ -1,4 +1,4 @@
-{% extends "crm/base.html" %}
+{% extends "bizdev/base.html" %}
{% block content %}
@@ -41,7 +41,7 @@
Send Email
-
Cancel
+
Cancel
{% endblock %}
diff --git a/crm/templatetags/__init__.py b/bizdev/templatetags/__init__.py
similarity index 100%
rename from crm/templatetags/__init__.py
rename to bizdev/templatetags/__init__.py
diff --git a/bizdev/templatetags/crm_tags.py b/bizdev/templatetags/crm_tags.py
new file mode 100644
index 0000000..4b0ee8e
--- /dev/null
+++ b/bizdev/templatetags/crm_tags.py
@@ -0,0 +1,7 @@
+from django import template
+
+register = template.Library()
+
+@register.filter(name='is_bizdev_manager')
+def is_bizdev_manager(user):
+ return user.groups.filter(name='bizdev Manager').exists()
diff --git a/crm/tests.py b/bizdev/tests.py
similarity index 100%
rename from crm/tests.py
rename to bizdev/tests.py
diff --git a/crm/urls.py b/bizdev/urls.py
similarity index 97%
rename from crm/urls.py
rename to bizdev/urls.py
index adbd5e6..beceab4 100644
--- a/crm/urls.py
+++ b/bizdev/urls.py
@@ -1,7 +1,7 @@
from django.urls import path
from . import views
-app_name = 'crm'
+app_name = 'bizdev'
urlpatterns = [
path('', views.EventListView.as_view(), name='planned_events'),path('', views.EventListView.as_view(), name='events'),
diff --git a/bizdev/views.py b/bizdev/views.py
new file mode 100644
index 0000000..c170a71
--- /dev/null
+++ b/bizdev/views.py
@@ -0,0 +1,284 @@
+# views.py
+from django.views.generic import FormView, ListView, DetailView, CreateView, UpdateView
+from django.views.generic.edit import FormView, BaseUpdateView
+from django.contrib.auth.mixins import LoginRequiredMixin
+from django.contrib.auth.decorators import permission_required
+from django.contrib import messages
+from django.shortcuts import render, redirect, get_object_or_404
+from django.urls import reverse_lazy
+from django.http import HttpResponse, HttpResponseRedirect
+from django.views import View
+from django.utils import timezone
+from django.contrib.sites.shortcuts import get_current_site
+from django.template.loader import render_to_string
+from django.core.mail import send_mail
+from django.conf import settings
+from django.db import IntegrityError
+
+from .models import Event, Prospect, ActivityType
+from .filters import ProspectFilter
+from .forms import CSVImportForm
+
+from .mixins import bizdevAccessMixin
+
+import csv
+from io import TextIOWrapper
+from datetime import datetime
+
+# @permission_required('bizdev.view_bizdev', raise_exception=True)
+# def prospect_form(request, pk=None):
+# # Get the prospect instance if pk is provided (edit mode)
+# prospect = get_object_or_404(Prospect, pk=pk) if pk else None
+
+# if request.method == 'POST':
+# form = ProspectForm(request.POST, instance=prospect)
+# if form.is_valid():
+# prospect = form.save(commit=False)
+# if not pk: # New prospect
+# prospect.created_by = request.user
+# prospect.modified_by = request.user
+# prospect.save()
+
+# action = 'updated' if pk else 'added'
+# messages.success(request,
+# f'Prospect {prospect.entity_name} has been {action} successfully!')
+# return redirect('bizdev:events')
+# else:
+# form = ProspectForm(instance=prospect)
+
+# context = {
+# 'form': form,
+# 'is_edit': prospect is not None,
+# 'first_title': prospect.entity_name if prospect else 'Add Prospect',
+# 'second_title': prospect.full_name() if prospect else None
+# }
+# return render(request, 'bizdev/prospect_form.html', context)
+
+# # @permission_required('bizdev.view_bizdev', raise_exception=True)
+# # def add_prospect(request):
+# # if request.method == 'POST':
+# # entity_name = request.POST.get('entity_name')
+# # first_name = request.POST.get('first_name')
+# # last_name = request.POST.get('last_name')
+# # email = request.POST.get('email')
+# # phone = request.POST.get('phone')
+# # address = request.POST.get('address')
+# # zip_code = request.POST.get('zip_code')
+# # city = request.POST.get('city')
+# # # region = request.POST.get('region')
+
+# # try:
+# # prospect = Prospect.objects.create(
+# # entity_name=entity_name,
+# # first_name=first_name,
+# # last_name=last_name,
+# # email=email,
+# # phone=phone,
+# # address=address,
+# # zip_code=zip_code,
+# # city=city,
+# # # region=region,
+# # created_by=request.user,
+# # modified_by=request.user
+# # )
+# # messages.success(request, f'Prospect {name} has been added successfully!')
+# # return redirect('bizdev:events') # or wherever you want to redirect after success
+# # except Exception as e:
+# # messages.error(request, f'Error adding prospect: {str(e)}')
+
+# # return render(request, 'bizdev/add_prospect.html')
+
+# class EventCreateView(bizdevAccessMixin, CreateView):
+# model = Event
+# form_class = EventForm
+# template_name = 'bizdev/event_form.html'
+# success_url = reverse_lazy('bizdev:planned_events')
+
+# def get_initial(self):
+# initial = super().get_initial()
+# prospect_id = self.kwargs.get('prospect_id')
+# if prospect_id:
+# initial['prospects'] = [prospect_id]
+# return initial
+
+# def form_valid(self, form):
+# form.instance.created_by = self.request.user
+# form.instance.modified_by = self.request.user
+# return super().form_valid(form)
+
+# class EditEventView(bizdevAccessMixin, UpdateView):
+# model = Event
+# form_class = EventForm
+# template_name = 'bizdev/event_form.html'
+# success_url = reverse_lazy('bizdev:planned_events')
+
+# def form_valid(self, form):
+# form.instance.modified_by = self.request.user
+# response = super().form_valid(form)
+# messages.success(self.request, 'Event updated successfully!')
+# return response
+
+# class StartEventView(bizdevAccessMixin, BaseUpdateView):
+# model = Event
+# http_method_names = ['post', 'get']
+
+# def get(self, request, *args, **kwargs):
+# return self.post(request, *args, **kwargs)
+
+# def post(self, request, *args, **kwargs):
+# event = get_object_or_404(Event, pk=kwargs['pk'], status='PLANNED')
+# event.status = 'ACTIVE'
+# event.save()
+
+# if event.type == 'MAIL':
+# return HttpResponseRedirect(
+# reverse_lazy('bizdev:setup_email_campaign', kwargs={'event_id': event.id})
+# )
+# elif event.type == 'SMS':
+# return HttpResponseRedirect(
+# reverse_lazy('bizdev:setup_sms_campaign', kwargs={'event_id': event.id})
+# )
+# elif event.type == 'PRESS':
+# return HttpResponseRedirect(
+# reverse_lazy('bizdev:setup_press_release', kwargs={'event_id': event.id})
+# )
+
+# messages.success(request, 'Event started successfully!')
+# return HttpResponseRedirect(reverse_lazy('bizdev:planned_events'))
+
+# class EventListView(bizdevAccessMixin, ListView):
+# model = Event
+# template_name = 'bizdev/events.html'
+# context_object_name = 'events' # We won't use this since we're providing custom context
+
+# def get_context_data(self, **kwargs):
+# context = super().get_context_data(**kwargs)
+# context['planned_events'] = Event.objects.filter(
+# status='PLANNED'
+# ).order_by('date')
+# context['completed_events'] = Event.objects.filter(
+# status='COMPLETED'
+# ).order_by('-date')
+# return context
+
+# class ProspectListView(bizdevAccessMixin, ListView):
+# model = Prospect
+# template_name = 'bizdev/prospect_list.html'
+# context_object_name = 'prospects'
+# filterset_class = ProspectFilter
+
+# def get_queryset(self):
+# return super().get_queryset().prefetch_related('prospectstatus_set__status')
+
+# def get_context_data(self, **kwargs):
+# context = super().get_context_data(**kwargs)
+# context['filter'] = self.filterset_class(
+# self.request.GET,
+# queryset=self.get_queryset()
+# )
+# return context
+
+# class CSVImportView(bizdevAccessMixin, FormView):
+# template_name = 'bizdev/csv_import.html'
+# form_class = CSVImportForm
+# success_url = reverse_lazy('prospect-list')
+
+# def form_valid(self, form):
+# csv_file = TextIOWrapper(
+# form.cleaned_data['csv_file'].file,
+# encoding='utf-8-sig' # Handle potential BOM in CSV
+# )
+# reader = csv.reader(csv_file, delimiter=';') # Using semicolon delimiter
+
+# # Skip header if exists
+# next(reader, None)
+
+# created_count = 0
+# updated_count = 0
+# error_count = 0
+
+# for row in reader:
+# try:
+# if len(row) < 10: # Ensure we have enough columns
+# continue
+
+# # Extract data from correct columns
+# entity_name = row[0].strip()
+# last_name = row[1].strip()
+# first_name = row[2].strip()
+# email = row[3].strip()
+# phone = row[4].strip()
+# zip_code = row[8].strip()
+# city = row[9].strip()
+
+# # Try to update existing prospect or create new one
+# prospect, created = Prospect.objects.update_or_create(
+# email=email, # Use email as unique identifier
+# defaults={
+# 'entity_name': entity_name,
+# 'first_name': first_name,
+# 'last_name': last_name,
+# 'phone': phone,
+# 'zip_code': zip_code,
+# 'city': city,
+# 'modified_by': self.request.user,
+# }
+# )
+
+# if created:
+# prospect.created_by = self.request.user
+# prospect.save()
+# created_count += 1
+# else:
+# updated_count += 1
+
+# except Exception as e:
+# error_count += 1
+# messages.error(
+# self.request,
+# f"Error processing row with email {email}: {str(e)}"
+# )
+
+# # Add success message
+# messages.success(
+# self.request,
+# f"Import completed: {created_count} created, {updated_count} updated, {error_count} errors"
+# )
+
+# return super().form_valid(form)
+
+# class SendBulkEmailView(bizdevAccessMixin, FormView):
+# template_name = 'bizdev/send_bulk_email.html'
+# form_class = BulkEmailForm
+# success_url = reverse_lazy('bizdev:prospect-list')
+
+# def form_valid(self, form):
+# prospects = form.cleaned_data['prospects']
+# subject = form.cleaned_data['subject']
+# content = form.cleaned_data['content']
+
+# # Create Event for this email campaign
+# event = Event.objects.create(
+# date=datetime.now(),
+# type=EventType.MAILING,
+# description=f"Bulk email: {subject}",
+# status='COMPLETED',
+# created_by=self.request.user,
+# modified_by=self.request.user
+# )
+# event.prospects.set(prospects)
+
+# # Send emails
+# success_count, error_count = send_bulk_email(
+# subject=subject,
+# content=content,
+# prospects=prospects
+# )
+
+# # Show result message
+# messages.success(
+# self.request,
+# f"Sent {success_count} emails successfully. {error_count} failed."
+# )
+
+# return super().form_valid(form)
diff --git a/crm/_instructions/base.md b/crm/_instructions/base.md
deleted file mode 100644
index a45abd0..0000000
--- a/crm/_instructions/base.md
+++ /dev/null
@@ -1 +0,0 @@
-This is a django customer relationship managemement (CRM) app.
diff --git a/crm/admin.py b/crm/admin.py
deleted file mode 100644
index 819de9a..0000000
--- a/crm/admin.py
+++ /dev/null
@@ -1,96 +0,0 @@
-from django.contrib import admin
-from django.utils.html import format_html
-from .models import (
- Prospect,
- Status,
- ProspectStatus,
- Event,
- EmailCampaign,
- EmailTracker
-)
-
-@admin.register(Prospect)
-class ProspectAdmin(admin.ModelAdmin):
- list_display = ('entity_name', 'first_name', 'last_name', 'email', 'address', 'zip_code', 'city', 'created_at')
- list_filter = ('zip_code', 'created_at')
- search_fields = ('entity_name', 'first_name', 'last_name', 'email', 'zip_code', 'city')
- filter_horizontal = ('users',)
- date_hierarchy = 'created_at'
-
-@admin.register(Status)
-class StatusAdmin(admin.ModelAdmin):
- list_display = ('name', 'created_at')
- search_fields = ('name',)
-
-@admin.register(ProspectStatus)
-class ProspectStatusAdmin(admin.ModelAdmin):
- list_display = ('prospect', 'status', 'created_at')
- list_filter = ('status', 'created_at')
- search_fields = ('prospect__name', 'prospect__email')
- date_hierarchy = 'created_at'
-
-@admin.register(Event)
-class EventAdmin(admin.ModelAdmin):
- list_display = ('get_event_display', 'type', 'date', 'status', 'created_at')
- list_filter = ('type', 'status', 'date')
- search_fields = ('description',)
- filter_horizontal = ('prospects',)
- date_hierarchy = 'date'
-
- def get_event_display(self, obj):
- return str(obj)
- get_event_display.short_description = 'Event'
-
-@admin.register(EmailCampaign)
-class EmailCampaignAdmin(admin.ModelAdmin):
- list_display = ('subject', 'event', 'sent_at')
- list_filter = ('sent_at',)
- search_fields = ('subject', 'content')
- date_hierarchy = 'sent_at'
- readonly_fields = ('sent_at',)
-
-@admin.register(EmailTracker)
-class EmailTrackerAdmin(admin.ModelAdmin):
- list_display = (
- 'campaign',
- 'prospect',
- 'tracking_id',
- 'sent_status',
- 'opened_status',
- 'clicked_status'
- )
- list_filter = ('sent', 'opened', 'clicked')
- search_fields = (
- 'prospect__name',
- 'prospect__email',
- 'campaign__subject'
- )
- readonly_fields = (
- 'tracking_id', 'sent', 'sent_at',
- 'opened', 'opened_at',
- 'clicked', 'clicked_at'
- )
- date_hierarchy = 'sent_at'
-
- def sent_status(self, obj):
- return self._get_status_html(obj.sent, obj.sent_at)
- sent_status.short_description = 'Sent'
- sent_status.allow_tags = True
-
- def opened_status(self, obj):
- return self._get_status_html(obj.opened, obj.opened_at)
- opened_status.short_description = 'Opened'
- opened_status.allow_tags = True
-
- def clicked_status(self, obj):
- return self._get_status_html(obj.clicked, obj.clicked_at)
- clicked_status.short_description = 'Clicked'
- clicked_status.allow_tags = True
-
- def _get_status_html(self, status, date):
- if status:
- return format_html(
- '
✓ {}',
- date.strftime('%Y-%m-%d %H:%M') if date else ''
- )
- return format_html('
✗ ')
diff --git a/crm/filters.py b/crm/filters.py
deleted file mode 100644
index 97e433b..0000000
--- a/crm/filters.py
+++ /dev/null
@@ -1,23 +0,0 @@
-import django_filters
-from django.db.models import Q
-
-from .models import Event, Status, Prospect
-
-
-class ProspectFilter(django_filters.FilterSet):
- zip_code = django_filters.CharFilter(lookup_expr='istartswith', label='Code postal')
- events = django_filters.ModelMultipleChoiceFilter(
- queryset=Event.objects.all(),
- field_name='events',
- )
- city = django_filters.CharFilter(lookup_expr='icontains', label='Ville')
- name = django_filters.CharFilter(method='filter_name', label='Nom')
-
- def filter_name(self, queryset, name, value):
- return queryset.filter(
- Q(first_name__icontains=value) | Q(last_name__icontains=value) | Q(entity_name__icontains=value)
- )
-
- class Meta:
- model = Prospect
- fields = ['name', 'city', 'events', 'zip_code']
diff --git a/crm/forms.py b/crm/forms.py
deleted file mode 100644
index 10edf6c..0000000
--- a/crm/forms.py
+++ /dev/null
@@ -1,46 +0,0 @@
-from django import forms
-from .models import Prospect, Event
-import datetime
-
-class SmallTextArea(forms.Textarea):
- def __init__(self, *args, **kwargs):
- kwargs.setdefault('attrs', {})
- kwargs['attrs'].update({
- 'rows': 2,
- 'cols': 100,
- 'style': 'height: 80px; width: 800px;'
- })
- super().__init__(*args, **kwargs)
-
-class ProspectForm(forms.ModelForm):
- class Meta:
- model = Prospect
- fields = ['entity_name', 'first_name', 'last_name', 'email',
- 'phone', 'address', 'zip_code', 'city']
-
-class BulkEmailForm(forms.Form):
- prospects = forms.ModelMultipleChoiceField(
- queryset=Prospect.objects.all(),
- widget=forms.CheckboxSelectMultiple
- )
- subject = forms.CharField(max_length=200)
- content = forms.CharField(widget=forms.Textarea)
-
-class EventForm(forms.ModelForm):
- prospects = forms.ModelMultipleChoiceField(
- queryset=Prospect.objects.all(),
- widget=forms.SelectMultiple(attrs={'class': 'select2'}),
- required=False
- )
- description = forms.CharField(widget=SmallTextArea)
- attachment_text = forms.CharField(widget=SmallTextArea)
-
- class Meta:
- model = Event
- fields = ['date', 'type', 'description', 'attachment_text', 'prospects', 'status']
- widgets = {
- 'date': forms.DateTimeInput(attrs={'type': 'datetime-local'}),
- }
-
-class CSVImportForm(forms.Form):
- csv_file = forms.FileField()
diff --git a/crm/migrations/0001_initial.py b/crm/migrations/0001_initial.py
deleted file mode 100644
index 66531fe..0000000
--- a/crm/migrations/0001_initial.py
+++ /dev/null
@@ -1,94 +0,0 @@
-# Generated by Django 4.2.11 on 2024-12-08 15:10
-
-from django.conf import settings
-from django.db import migrations, models
-import django.db.models.deletion
-import uuid
-
-
-class Migration(migrations.Migration):
-
- initial = True
-
- dependencies = [
- migrations.swappable_dependency(settings.AUTH_USER_MODEL),
- ]
-
- operations = [
- migrations.CreateModel(
- name='Prospect',
- fields=[
- ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('email', models.EmailField(max_length=254, unique=True)),
- ('name', models.CharField(max_length=200)),
- ('region', models.CharField(max_length=100)),
- ('created_at', models.DateTimeField(auto_now_add=True)),
- ('users', models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL)),
- ],
- ),
- migrations.CreateModel(
- name='Status',
- fields=[
- ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('name', models.CharField(max_length=100, unique=True)),
- ('created_at', models.DateTimeField(auto_now_add=True)),
- ],
- ),
- migrations.CreateModel(
- name='ProspectStatus',
- fields=[
- ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('created_at', models.DateTimeField(auto_now_add=True)),
- ('prospect', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='crm.prospect')),
- ('status', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='crm.status')),
- ],
- options={
- 'ordering': ['-created_at'],
- },
- ),
- migrations.CreateModel(
- name='Event',
- fields=[
- ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('date', models.DateTimeField()),
- ('type', models.CharField(choices=[('MAIL', 'Mailing List'), ('SMS', 'SMS Campaign'), ('PRESS', 'Press Release')], max_length=10)),
- ('description', models.TextField()),
- ('attachment_text', models.TextField(blank=True)),
- ('status', models.CharField(choices=[('PLANNED', 'Planned'), ('ACTIVE', 'Active'), ('COMPLETED', 'Completed')], max_length=20)),
- ('created_at', models.DateTimeField(auto_now_add=True)),
- ('prospects', models.ManyToManyField(related_name='events', to='crm.prospect')),
- ],
- options={
- 'ordering': ['-created_at'],
- },
- ),
- migrations.CreateModel(
- name='EmailCampaign',
- fields=[
- ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('subject', models.CharField(max_length=200)),
- ('content', models.TextField()),
- ('sent_at', models.DateTimeField(blank=True, null=True)),
- ('event', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='crm.event')),
- ],
- ),
- migrations.CreateModel(
- name='EmailTracker',
- fields=[
- ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('tracking_id', models.UUIDField(default=uuid.uuid4, editable=False)),
- ('sent', models.BooleanField(default=False)),
- ('sent_at', models.DateTimeField(blank=True, null=True)),
- ('opened', models.BooleanField(default=False)),
- ('opened_at', models.DateTimeField(blank=True, null=True)),
- ('clicked', models.BooleanField(default=False)),
- ('clicked_at', models.DateTimeField(blank=True, null=True)),
- ('error_message', models.TextField(blank=True)),
- ('campaign', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='crm.emailcampaign')),
- ('prospect', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='crm.prospect')),
- ],
- options={
- 'unique_together': {('campaign', 'prospect')},
- },
- ),
- ]
diff --git a/crm/migrations/0002_alter_event_options_alter_prospect_options_and_more.py b/crm/migrations/0002_alter_event_options_alter_prospect_options_and_more.py
deleted file mode 100644
index 92b7621..0000000
--- a/crm/migrations/0002_alter_event_options_alter_prospect_options_and_more.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# Generated by Django 4.2.11 on 2024-12-08 20:58
-
-from django.conf import settings
-from django.db import migrations, models
-import django.db.models.deletion
-import django.utils.timezone
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- migrations.swappable_dependency(settings.AUTH_USER_MODEL),
- ('crm', '0001_initial'),
- ]
-
- operations = [
- migrations.AlterModelOptions(
- name='event',
- options={'ordering': ['-created_at'], 'permissions': [('manage_events', 'Can manage events'), ('view_events', 'Can view events')]},
- ),
- migrations.AlterModelOptions(
- name='prospect',
- options={'permissions': [('manage_prospects', 'Can manage prospects'), ('view_prospects', 'Can view prospects')]},
- ),
- migrations.AddField(
- model_name='event',
- name='created_by',
- field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_events', to=settings.AUTH_USER_MODEL),
- ),
- migrations.AddField(
- model_name='event',
- name='modified_at',
- field=models.DateTimeField(auto_now=True),
- ),
- migrations.AddField(
- model_name='event',
- name='modified_by',
- field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='modified_events', to=settings.AUTH_USER_MODEL),
- ),
- migrations.AddField(
- model_name='prospect',
- name='created_by',
- field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_prospects', to=settings.AUTH_USER_MODEL),
- ),
- migrations.AddField(
- model_name='prospect',
- name='modified_at',
- field=models.DateTimeField(auto_now=True),
- ),
- migrations.AddField(
- model_name='prospect',
- name='modified_by',
- field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='modified_prospects', to=settings.AUTH_USER_MODEL),
- ),
- migrations.AlterField(
- model_name='event',
- name='date',
- field=models.DateTimeField(default=django.utils.timezone.now),
- ),
- ]
diff --git a/crm/migrations/0003_remove_prospect_region_prospect_address_and_more.py b/crm/migrations/0003_remove_prospect_region_prospect_address_and_more.py
deleted file mode 100644
index 7ed0884..0000000
--- a/crm/migrations/0003_remove_prospect_region_prospect_address_and_more.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# Generated by Django 5.1 on 2024-12-16 15:43
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('crm', '0002_alter_event_options_alter_prospect_options_and_more'),
- ]
-
- operations = [
- migrations.RemoveField(
- model_name='prospect',
- name='region',
- ),
- migrations.AddField(
- model_name='prospect',
- name='address',
- field=models.CharField(blank=True, max_length=200, null=True),
- ),
- migrations.AddField(
- model_name='prospect',
- name='city',
- field=models.CharField(blank=True, max_length=500, null=True),
- ),
- migrations.AddField(
- model_name='prospect',
- name='zip_code',
- field=models.CharField(blank=True, max_length=20, null=True),
- ),
- ]
diff --git a/crm/migrations/0004_remove_prospect_name_prospect_entity_name_and_more.py b/crm/migrations/0004_remove_prospect_name_prospect_entity_name_and_more.py
deleted file mode 100644
index 47776b9..0000000
--- a/crm/migrations/0004_remove_prospect_name_prospect_entity_name_and_more.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# Generated by Django 5.1 on 2024-12-16 16:24
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('crm', '0003_remove_prospect_region_prospect_address_and_more'),
- ]
-
- operations = [
- migrations.RemoveField(
- model_name='prospect',
- name='name',
- ),
- migrations.AddField(
- model_name='prospect',
- name='entity_name',
- field=models.CharField(blank=True, max_length=200, null=True),
- ),
- migrations.AddField(
- model_name='prospect',
- name='first_name',
- field=models.CharField(blank=True, max_length=200, null=True),
- ),
- migrations.AddField(
- model_name='prospect',
- name='last_name',
- field=models.CharField(blank=True, max_length=200, null=True),
- ),
- ]
diff --git a/crm/migrations/0005_prospect_phone.py b/crm/migrations/0005_prospect_phone.py
deleted file mode 100644
index 1b5a25f..0000000
--- a/crm/migrations/0005_prospect_phone.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Generated by Django 5.1 on 2024-12-16 16:49
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('crm', '0004_remove_prospect_name_prospect_entity_name_and_more'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='prospect',
- name='phone',
- field=models.CharField(blank=True, max_length=25, null=True),
- ),
- ]
diff --git a/crm/models.py b/crm/models.py
deleted file mode 100644
index 5028da6..0000000
--- a/crm/models.py
+++ /dev/null
@@ -1,120 +0,0 @@
-from django.db import models
-from django.contrib.auth import get_user_model
-from django.utils import timezone
-import uuid
-
-User = get_user_model()
-
-class EventType(models.TextChoices):
- MAILING = 'MAIL', 'Mailing List'
- SMS = 'SMS', 'SMS Campaign'
- PRESS = 'PRESS', 'Press Release'
-
-class Prospect(models.Model):
- email = models.EmailField(unique=True)
- entity_name = models.CharField(max_length=200, null=True, blank=True)
- first_name = models.CharField(max_length=200, null=True, blank=True)
- last_name = models.CharField(max_length=200, null=True, blank=True)
- address = models.CharField(max_length=200, null=True, blank=True)
- zip_code = models.CharField(max_length=20, null=True, blank=True)
- city = models.CharField(max_length=500, null=True, blank=True)
- phone = models.CharField(max_length=25, null=True, blank=True)
- users = models.ManyToManyField(get_user_model(), blank=True)
- created_at = models.DateTimeField(auto_now_add=True)
- created_by = models.ForeignKey(
- User,
- on_delete=models.SET_NULL,
- null=True,
- related_name='created_prospects'
- )
- modified_by = models.ForeignKey(
- User,
- on_delete=models.SET_NULL,
- null=True,
- related_name='modified_prospects'
- )
- modified_at = models.DateTimeField(auto_now=True)
-
- class Meta:
- permissions = [
- ("manage_prospects", "Can manage prospects"),
- ("view_prospects", "Can view prospects"),
- ]
-
- def full_name(self):
- return f'{self.first_name} {self.last_name}'
-
- def __str__(self):
- return ' - '.join(filter(None, [self.entity_name, self.first_name, self.last_name, f"({self.email})"]))
-
-class Status(models.Model):
- name = models.CharField(max_length=100, unique=True)
- created_at = models.DateTimeField(auto_now_add=True)
-
- def __str__(self):
- return self.name
-
-class ProspectStatus(models.Model):
- prospect = models.ForeignKey(Prospect, on_delete=models.CASCADE)
- status = models.ForeignKey(Status, on_delete=models.PROTECT)
- created_at = models.DateTimeField(auto_now_add=True)
-
- class Meta:
- ordering = ['-created_at']
-
-class Event(models.Model):
- date = models.DateTimeField(default=timezone.now)
- type = models.CharField(max_length=10, choices=EventType.choices)
- description = models.TextField()
- attachment_text = models.TextField(blank=True)
- prospects = models.ManyToManyField(Prospect, related_name='events')
- status = models.CharField(max_length=20, choices=[
- ('PLANNED', 'Planned'),
- ('ACTIVE', 'Active'),
- ('COMPLETED', 'Completed'),
- ])
- created_at = models.DateTimeField(auto_now_add=True)
- created_by = models.ForeignKey(
- User,
- on_delete=models.SET_NULL,
- null=True,
- related_name='created_events'
- )
- modified_by = models.ForeignKey(
- User,
- on_delete=models.SET_NULL,
- null=True,
- related_name='modified_events'
- )
- modified_at = models.DateTimeField(auto_now=True)
-
- class Meta:
- ordering = ['-created_at']
- permissions = [
- ("manage_events", "Can manage events"),
- ("view_events", "Can view events"),
- ]
-
- def __str__(self):
- return f"{self.get_type_display()} - {self.date.date()}"
-
-class EmailCampaign(models.Model):
- event = models.OneToOneField(Event, on_delete=models.CASCADE)
- subject = models.CharField(max_length=200)
- content = models.TextField()
- sent_at = models.DateTimeField(null=True, blank=True)
-
-class EmailTracker(models.Model):
- campaign = models.ForeignKey(EmailCampaign, on_delete=models.CASCADE)
- prospect = models.ForeignKey(Prospect, on_delete=models.CASCADE)
- tracking_id = models.UUIDField(default=uuid.uuid4, editable=False)
- sent = models.BooleanField(default=False)
- sent_at = models.DateTimeField(null=True, blank=True)
- opened = models.BooleanField(default=False)
- opened_at = models.DateTimeField(null=True, blank=True)
- clicked = models.BooleanField(default=False)
- clicked_at = models.DateTimeField(null=True, blank=True)
- error_message = models.TextField(blank=True)
-
- class Meta:
- unique_together = ['campaign', 'prospect']
diff --git a/crm/templatetags/crm_tags.py b/crm/templatetags/crm_tags.py
deleted file mode 100644
index 9c39ee3..0000000
--- a/crm/templatetags/crm_tags.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from django import template
-
-register = template.Library()
-
-@register.filter(name='is_crm_manager')
-def is_crm_manager(user):
- return user.groups.filter(name='CRM Manager').exists()
diff --git a/crm/views.py b/crm/views.py
deleted file mode 100644
index 5cd72c6..0000000
--- a/crm/views.py
+++ /dev/null
@@ -1,284 +0,0 @@
-# views.py
-from django.views.generic import FormView, ListView, DetailView, CreateView, UpdateView
-from django.views.generic.edit import FormView, BaseUpdateView
-from django.contrib.auth.mixins import LoginRequiredMixin
-from django.contrib.auth.decorators import permission_required
-from django.contrib import messages
-from django.shortcuts import render, redirect, get_object_or_404
-from django.urls import reverse_lazy
-from django.http import HttpResponse, HttpResponseRedirect
-from django.views import View
-from django.utils import timezone
-from django.contrib.sites.shortcuts import get_current_site
-from django.template.loader import render_to_string
-from django.core.mail import send_mail
-from django.conf import settings
-from django.db import IntegrityError
-
-from .models import Event, Prospect, EmailTracker, EmailCampaign, EventType
-from .filters import ProspectFilter
-from .forms import ProspectForm, CSVImportForm, BulkEmailForm, EventForm
-
-from .mixins import CRMAccessMixin
-
-import csv
-from io import TextIOWrapper
-from datetime import datetime
-
-@permission_required('crm.view_crm', raise_exception=True)
-def prospect_form(request, pk=None):
- # Get the prospect instance if pk is provided (edit mode)
- prospect = get_object_or_404(Prospect, pk=pk) if pk else None
-
- if request.method == 'POST':
- form = ProspectForm(request.POST, instance=prospect)
- if form.is_valid():
- prospect = form.save(commit=False)
- if not pk: # New prospect
- prospect.created_by = request.user
- prospect.modified_by = request.user
- prospect.save()
-
- action = 'updated' if pk else 'added'
- messages.success(request,
- f'Prospect {prospect.entity_name} has been {action} successfully!')
- return redirect('crm:events')
- else:
- form = ProspectForm(instance=prospect)
-
- context = {
- 'form': form,
- 'is_edit': prospect is not None,
- 'first_title': prospect.entity_name if prospect else 'Add Prospect',
- 'second_title': prospect.full_name() if prospect else None
- }
- return render(request, 'crm/prospect_form.html', context)
-
-# @permission_required('crm.view_crm', raise_exception=True)
-# def add_prospect(request):
-# if request.method == 'POST':
-# entity_name = request.POST.get('entity_name')
-# first_name = request.POST.get('first_name')
-# last_name = request.POST.get('last_name')
-# email = request.POST.get('email')
-# phone = request.POST.get('phone')
-# address = request.POST.get('address')
-# zip_code = request.POST.get('zip_code')
-# city = request.POST.get('city')
-# # region = request.POST.get('region')
-
-# try:
-# prospect = Prospect.objects.create(
-# entity_name=entity_name,
-# first_name=first_name,
-# last_name=last_name,
-# email=email,
-# phone=phone,
-# address=address,
-# zip_code=zip_code,
-# city=city,
-# # region=region,
-# created_by=request.user,
-# modified_by=request.user
-# )
-# messages.success(request, f'Prospect {name} has been added successfully!')
-# return redirect('crm:events') # or wherever you want to redirect after success
-# except Exception as e:
-# messages.error(request, f'Error adding prospect: {str(e)}')
-
-# return render(request, 'crm/add_prospect.html')
-
-class EventCreateView(CRMAccessMixin, CreateView):
- model = Event
- form_class = EventForm
- template_name = 'crm/event_form.html'
- success_url = reverse_lazy('crm:planned_events')
-
- def get_initial(self):
- initial = super().get_initial()
- prospect_id = self.kwargs.get('prospect_id')
- if prospect_id:
- initial['prospects'] = [prospect_id]
- return initial
-
- def form_valid(self, form):
- form.instance.created_by = self.request.user
- form.instance.modified_by = self.request.user
- return super().form_valid(form)
-
-class EditEventView(CRMAccessMixin, UpdateView):
- model = Event
- form_class = EventForm
- template_name = 'crm/event_form.html'
- success_url = reverse_lazy('crm:planned_events')
-
- def form_valid(self, form):
- form.instance.modified_by = self.request.user
- response = super().form_valid(form)
- messages.success(self.request, 'Event updated successfully!')
- return response
-
-class StartEventView(CRMAccessMixin, BaseUpdateView):
- model = Event
- http_method_names = ['post', 'get']
-
- def get(self, request, *args, **kwargs):
- return self.post(request, *args, **kwargs)
-
- def post(self, request, *args, **kwargs):
- event = get_object_or_404(Event, pk=kwargs['pk'], status='PLANNED')
- event.status = 'ACTIVE'
- event.save()
-
- if event.type == 'MAIL':
- return HttpResponseRedirect(
- reverse_lazy('crm:setup_email_campaign', kwargs={'event_id': event.id})
- )
- elif event.type == 'SMS':
- return HttpResponseRedirect(
- reverse_lazy('crm:setup_sms_campaign', kwargs={'event_id': event.id})
- )
- elif event.type == 'PRESS':
- return HttpResponseRedirect(
- reverse_lazy('crm:setup_press_release', kwargs={'event_id': event.id})
- )
-
- messages.success(request, 'Event started successfully!')
- return HttpResponseRedirect(reverse_lazy('crm:planned_events'))
-
-class EventListView(CRMAccessMixin, ListView):
- model = Event
- template_name = 'crm/events.html'
- context_object_name = 'events' # We won't use this since we're providing custom context
-
- def get_context_data(self, **kwargs):
- context = super().get_context_data(**kwargs)
- context['planned_events'] = Event.objects.filter(
- status='PLANNED'
- ).order_by('date')
- context['completed_events'] = Event.objects.filter(
- status='COMPLETED'
- ).order_by('-date')
- return context
-
-class ProspectListView(CRMAccessMixin, ListView):
- model = Prospect
- template_name = 'crm/prospect_list.html'
- context_object_name = 'prospects'
- filterset_class = ProspectFilter
-
- def get_queryset(self):
- return super().get_queryset().prefetch_related('prospectstatus_set__status')
-
- def get_context_data(self, **kwargs):
- context = super().get_context_data(**kwargs)
- context['filter'] = self.filterset_class(
- self.request.GET,
- queryset=self.get_queryset()
- )
- return context
-
-class CSVImportView(CRMAccessMixin, FormView):
- template_name = 'crm/csv_import.html'
- form_class = CSVImportForm
- success_url = reverse_lazy('prospect-list')
-
- def form_valid(self, form):
- csv_file = TextIOWrapper(
- form.cleaned_data['csv_file'].file,
- encoding='utf-8-sig' # Handle potential BOM in CSV
- )
- reader = csv.reader(csv_file, delimiter=';') # Using semicolon delimiter
-
- # Skip header if exists
- next(reader, None)
-
- created_count = 0
- updated_count = 0
- error_count = 0
-
- for row in reader:
- try:
- if len(row) < 10: # Ensure we have enough columns
- continue
-
- # Extract data from correct columns
- entity_name = row[0].strip()
- last_name = row[1].strip()
- first_name = row[2].strip()
- email = row[3].strip()
- phone = row[4].strip()
- zip_code = row[8].strip()
- city = row[9].strip()
-
- # Try to update existing prospect or create new one
- prospect, created = Prospect.objects.update_or_create(
- email=email, # Use email as unique identifier
- defaults={
- 'entity_name': entity_name,
- 'first_name': first_name,
- 'last_name': last_name,
- 'phone': phone,
- 'zip_code': zip_code,
- 'city': city,
- 'modified_by': self.request.user,
- }
- )
-
- if created:
- prospect.created_by = self.request.user
- prospect.save()
- created_count += 1
- else:
- updated_count += 1
-
- except Exception as e:
- error_count += 1
- messages.error(
- self.request,
- f"Error processing row with email {email}: {str(e)}"
- )
-
- # Add success message
- messages.success(
- self.request,
- f"Import completed: {created_count} created, {updated_count} updated, {error_count} errors"
- )
-
- return super().form_valid(form)
-
-class SendBulkEmailView(CRMAccessMixin, FormView):
- template_name = 'crm/send_bulk_email.html'
- form_class = BulkEmailForm
- success_url = reverse_lazy('crm:prospect-list')
-
- def form_valid(self, form):
- prospects = form.cleaned_data['prospects']
- subject = form.cleaned_data['subject']
- content = form.cleaned_data['content']
-
- # Create Event for this email campaign
- event = Event.objects.create(
- date=datetime.now(),
- type=EventType.MAILING,
- description=f"Bulk email: {subject}",
- status='COMPLETED',
- created_by=self.request.user,
- modified_by=self.request.user
- )
- event.prospects.set(prospects)
-
- # Send emails
- success_count, error_count = send_bulk_email(
- subject=subject,
- content=content,
- prospects=prospects
- )
-
- # Show result message
- messages.success(
- self.request,
- f"Sent {success_count} emails successfully. {error_count} failed."
- )
-
- return super().form_valid(form)
diff --git a/padelclub_backend/settings.py b/padelclub_backend/settings.py
index b2b2e5b..9209ee4 100644
--- a/padelclub_backend/settings.py
+++ b/padelclub_backend/settings.py
@@ -36,7 +36,7 @@ INSTALLED_APPS = [
'sync',
'tournaments',
'shop',
- # 'crm',
+ 'bizdev',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
diff --git a/padelclub_backend/urls.py b/padelclub_backend/urls.py
index d56034b..e4f5c5c 100644
--- a/padelclub_backend/urls.py
+++ b/padelclub_backend/urls.py
@@ -17,6 +17,7 @@ from django.contrib import admin
from django.urls import include, path
from django.conf import settings
from django.conf.urls.static import static
+
from tournaments.admin_utils import download_french_padel_rankings, debug_tools_page, test_player_details_apis, explore_fft_api_endpoints, get_player_license_info, bulk_license_lookup, search_player_by_name, enrich_rankings_with_licenses
urlpatterns = [
@@ -33,12 +34,18 @@ urlpatterns = [
path('kingdom/debug/player-license-lookup/', get_player_license_info, name='player_license_lookup'),
path('kingdom/debug/bulk-license-lookup/', bulk_license_lookup, name='bulk_license_lookup'),
path('kingdom/debug/explore-api-endpoints/', explore_fft_api_endpoints, name='explore_api_endpoints'),
+ path('kingdom/bizdev/', include('bizdev.admin_urls')),
path('kingdom/', admin.site.urls),
path('api-auth/', include('rest_framework.urls')),
path('dj-auth/', include('django.contrib.auth.urls')),
]
+def email_users_view(request):
+ return render(request, 'admin/crm/email_users.html', {
+ 'title': 'Email Users',
+ })
+
# Serve media files in development
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
diff --git a/sample_prospects.csv b/sample_prospects.csv
new file mode 100644
index 0000000..4fbf545
--- /dev/null
+++ b/sample_prospects.csv
@@ -0,0 +1,11 @@
+first_name,last_name,email,phone
+John,Doe,john.doe@example.com,+33123456789
+Jane,Smith,jane.smith@example.com,+33987654321
+Pierre,Martin,pierre.martin@example.com,+33456789123
+Marie,Dubois,marie.dubois@example.com,+33789123456
+Carlos,Rodriguez,carlos.rodriguez@example.com,+34612345678
+Sophie,Leroy,sophie.leroy@example.com,+33234567890
+Michel,Bernard,michel.bernard@example.com,+33345678901
+Laura,Garcia,laura.garcia@example.com,+34723456789
+Thomas,Petit,thomas.petit@example.com,+33456789012
+Emma,Moreau,emma.moreau@example.com,+33567890123
diff --git a/tournaments/migrations/0131_alter_playerregistration_contact_name.py b/tournaments/migrations/0131_alter_playerregistration_contact_name.py
new file mode 100644
index 0000000..8ea41b9
--- /dev/null
+++ b/tournaments/migrations/0131_alter_playerregistration_contact_name.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.1 on 2025-07-03 10:01
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('tournaments', '0130_playerregistration_contact_email_and_more'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='playerregistration',
+ name='contact_name',
+ field=models.CharField(blank=True, max_length=200, null=True),
+ ),
+ ]
diff --git a/tournaments/migrations/0132_alter_purchase_user.py b/tournaments/migrations/0132_alter_purchase_user.py
new file mode 100644
index 0000000..ae546bd
--- /dev/null
+++ b/tournaments/migrations/0132_alter_purchase_user.py
@@ -0,0 +1,20 @@
+# Generated by Django 5.1 on 2025-07-09 12:55
+
+import django.db.models.deletion
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('tournaments', '0131_alter_playerregistration_contact_name'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='purchase',
+ name='user',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='purchases', to=settings.AUTH_USER_MODEL),
+ ),
+ ]
diff --git a/tournaments/migrations/0133_alter_club_timezone.py b/tournaments/migrations/0133_alter_club_timezone.py
new file mode 100644
index 0000000..ff7033c
--- /dev/null
+++ b/tournaments/migrations/0133_alter_club_timezone.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.1 on 2025-07-09 14:51
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('tournaments', '0132_alter_purchase_user'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='club',
+ name='timezone',
+ field=models.CharField(blank=True, choices=[('Africa/Abidjan', 'Africa/Abidjan'), ('Africa/Accra', 'Africa/Accra'), ('Africa/Addis_Ababa', 'Africa/Addis_Ababa'), ('Africa/Algiers', 'Africa/Algiers'), ('Africa/Asmara', 'Africa/Asmara'), ('Africa/Asmera', 'Africa/Asmera'), ('Africa/Bamako', 'Africa/Bamako'), ('Africa/Bangui', 'Africa/Bangui'), ('Africa/Banjul', 'Africa/Banjul'), ('Africa/Bissau', 'Africa/Bissau'), ('Africa/Blantyre', 'Africa/Blantyre'), ('Africa/Brazzaville', 'Africa/Brazzaville'), ('Africa/Bujumbura', 'Africa/Bujumbura'), ('Africa/Cairo', 'Africa/Cairo'), ('Africa/Casablanca', 'Africa/Casablanca'), ('Africa/Ceuta', 'Africa/Ceuta'), ('Africa/Conakry', 'Africa/Conakry'), ('Africa/Dakar', 'Africa/Dakar'), ('Africa/Dar_es_Salaam', 'Africa/Dar_es_Salaam'), ('Africa/Djibouti', 'Africa/Djibouti'), ('Africa/Douala', 'Africa/Douala'), ('Africa/El_Aaiun', 'Africa/El_Aaiun'), ('Africa/Freetown', 'Africa/Freetown'), ('Africa/Gaborone', 'Africa/Gaborone'), ('Africa/Harare', 'Africa/Harare'), ('Africa/Johannesburg', 'Africa/Johannesburg'), ('Africa/Juba', 'Africa/Juba'), ('Africa/Kampala', 'Africa/Kampala'), ('Africa/Khartoum', 'Africa/Khartoum'), ('Africa/Kigali', 'Africa/Kigali'), ('Africa/Kinshasa', 'Africa/Kinshasa'), ('Africa/Lagos', 'Africa/Lagos'), ('Africa/Libreville', 'Africa/Libreville'), ('Africa/Lome', 'Africa/Lome'), ('Africa/Luanda', 'Africa/Luanda'), ('Africa/Lubumbashi', 'Africa/Lubumbashi'), ('Africa/Lusaka', 'Africa/Lusaka'), ('Africa/Malabo', 'Africa/Malabo'), ('Africa/Maputo', 'Africa/Maputo'), ('Africa/Maseru', 'Africa/Maseru'), ('Africa/Mbabane', 'Africa/Mbabane'), ('Africa/Mogadishu', 'Africa/Mogadishu'), ('Africa/Monrovia', 'Africa/Monrovia'), ('Africa/Nairobi', 'Africa/Nairobi'), ('Africa/Ndjamena', 'Africa/Ndjamena'), ('Africa/Niamey', 'Africa/Niamey'), ('Africa/Nouakchott', 'Africa/Nouakchott'), ('Africa/Ouagadougou', 'Africa/Ouagadougou'), ('Africa/Porto-Novo', 'Africa/Porto-Novo'), ('Africa/Sao_Tome', 'Africa/Sao_Tome'), ('Africa/Timbuktu', 'Africa/Timbuktu'), ('Africa/Tripoli', 'Africa/Tripoli'), ('Africa/Tunis', 'Africa/Tunis'), ('Africa/Windhoek', 'Africa/Windhoek'), ('America/Adak', 'America/Adak'), ('America/Anchorage', 'America/Anchorage'), ('America/Anguilla', 'America/Anguilla'), ('America/Antigua', 'America/Antigua'), ('America/Araguaina', 'America/Araguaina'), ('America/Argentina/Buenos_Aires', 'America/Argentina/Buenos_Aires'), ('America/Argentina/Catamarca', 'America/Argentina/Catamarca'), ('America/Argentina/ComodRivadavia', 'America/Argentina/ComodRivadavia'), ('America/Argentina/Cordoba', 'America/Argentina/Cordoba'), ('America/Argentina/Jujuy', 'America/Argentina/Jujuy'), ('America/Argentina/La_Rioja', 'America/Argentina/La_Rioja'), ('America/Argentina/Mendoza', 'America/Argentina/Mendoza'), ('America/Argentina/Rio_Gallegos', 'America/Argentina/Rio_Gallegos'), ('America/Argentina/Salta', 'America/Argentina/Salta'), ('America/Argentina/San_Juan', 'America/Argentina/San_Juan'), ('America/Argentina/San_Luis', 'America/Argentina/San_Luis'), ('America/Argentina/Tucuman', 'America/Argentina/Tucuman'), ('America/Argentina/Ushuaia', 'America/Argentina/Ushuaia'), ('America/Aruba', 'America/Aruba'), ('America/Asuncion', 'America/Asuncion'), ('America/Atikokan', 'America/Atikokan'), ('America/Atka', 'America/Atka'), ('America/Bahia', 'America/Bahia'), ('America/Bahia_Banderas', 'America/Bahia_Banderas'), ('America/Barbados', 'America/Barbados'), ('America/Belem', 'America/Belem'), ('America/Belize', 'America/Belize'), ('America/Blanc-Sablon', 'America/Blanc-Sablon'), ('America/Boa_Vista', 'America/Boa_Vista'), ('America/Bogota', 'America/Bogota'), ('America/Boise', 'America/Boise'), ('America/Buenos_Aires', 'America/Buenos_Aires'), ('America/Cambridge_Bay', 'America/Cambridge_Bay'), ('America/Campo_Grande', 'America/Campo_Grande'), ('America/Cancun', 'America/Cancun'), ('America/Caracas', 'America/Caracas'), ('America/Catamarca', 'America/Catamarca'), ('America/Cayenne', 'America/Cayenne'), ('America/Cayman', 'America/Cayman'), ('America/Chicago', 'America/Chicago'), ('America/Chihuahua', 'America/Chihuahua'), ('America/Ciudad_Juarez', 'America/Ciudad_Juarez'), ('America/Coral_Harbour', 'America/Coral_Harbour'), ('America/Cordoba', 'America/Cordoba'), ('America/Costa_Rica', 'America/Costa_Rica'), ('America/Coyhaique', 'America/Coyhaique'), ('America/Creston', 'America/Creston'), ('America/Cuiaba', 'America/Cuiaba'), ('America/Curacao', 'America/Curacao'), ('America/Danmarkshavn', 'America/Danmarkshavn'), ('America/Dawson', 'America/Dawson'), ('America/Dawson_Creek', 'America/Dawson_Creek'), ('America/Denver', 'America/Denver'), ('America/Detroit', 'America/Detroit'), ('America/Dominica', 'America/Dominica'), ('America/Edmonton', 'America/Edmonton'), ('America/Eirunepe', 'America/Eirunepe'), ('America/El_Salvador', 'America/El_Salvador'), ('America/Ensenada', 'America/Ensenada'), ('America/Fort_Nelson', 'America/Fort_Nelson'), ('America/Fort_Wayne', 'America/Fort_Wayne'), ('America/Fortaleza', 'America/Fortaleza'), ('America/Glace_Bay', 'America/Glace_Bay'), ('America/Godthab', 'America/Godthab'), ('America/Goose_Bay', 'America/Goose_Bay'), ('America/Grand_Turk', 'America/Grand_Turk'), ('America/Grenada', 'America/Grenada'), ('America/Guadeloupe', 'America/Guadeloupe'), ('America/Guatemala', 'America/Guatemala'), ('America/Guayaquil', 'America/Guayaquil'), ('America/Guyana', 'America/Guyana'), ('America/Halifax', 'America/Halifax'), ('America/Havana', 'America/Havana'), ('America/Hermosillo', 'America/Hermosillo'), ('America/Indiana/Indianapolis', 'America/Indiana/Indianapolis'), ('America/Indiana/Knox', 'America/Indiana/Knox'), ('America/Indiana/Marengo', 'America/Indiana/Marengo'), ('America/Indiana/Petersburg', 'America/Indiana/Petersburg'), ('America/Indiana/Tell_City', 'America/Indiana/Tell_City'), ('America/Indiana/Vevay', 'America/Indiana/Vevay'), ('America/Indiana/Vincennes', 'America/Indiana/Vincennes'), ('America/Indiana/Winamac', 'America/Indiana/Winamac'), ('America/Indianapolis', 'America/Indianapolis'), ('America/Inuvik', 'America/Inuvik'), ('America/Iqaluit', 'America/Iqaluit'), ('America/Jamaica', 'America/Jamaica'), ('America/Jujuy', 'America/Jujuy'), ('America/Juneau', 'America/Juneau'), ('America/Kentucky/Louisville', 'America/Kentucky/Louisville'), ('America/Kentucky/Monticello', 'America/Kentucky/Monticello'), ('America/Knox_IN', 'America/Knox_IN'), ('America/Kralendijk', 'America/Kralendijk'), ('America/La_Paz', 'America/La_Paz'), ('America/Lima', 'America/Lima'), ('America/Los_Angeles', 'America/Los_Angeles'), ('America/Louisville', 'America/Louisville'), ('America/Lower_Princes', 'America/Lower_Princes'), ('America/Maceio', 'America/Maceio'), ('America/Managua', 'America/Managua'), ('America/Manaus', 'America/Manaus'), ('America/Marigot', 'America/Marigot'), ('America/Martinique', 'America/Martinique'), ('America/Matamoros', 'America/Matamoros'), ('America/Mazatlan', 'America/Mazatlan'), ('America/Mendoza', 'America/Mendoza'), ('America/Menominee', 'America/Menominee'), ('America/Merida', 'America/Merida'), ('America/Metlakatla', 'America/Metlakatla'), ('America/Mexico_City', 'America/Mexico_City'), ('America/Miquelon', 'America/Miquelon'), ('America/Moncton', 'America/Moncton'), ('America/Monterrey', 'America/Monterrey'), ('America/Montevideo', 'America/Montevideo'), ('America/Montreal', 'America/Montreal'), ('America/Montserrat', 'America/Montserrat'), ('America/Nassau', 'America/Nassau'), ('America/New_York', 'America/New_York'), ('America/Nipigon', 'America/Nipigon'), ('America/Nome', 'America/Nome'), ('America/Noronha', 'America/Noronha'), ('America/North_Dakota/Beulah', 'America/North_Dakota/Beulah'), ('America/North_Dakota/Center', 'America/North_Dakota/Center'), ('America/North_Dakota/New_Salem', 'America/North_Dakota/New_Salem'), ('America/Nuuk', 'America/Nuuk'), ('America/Ojinaga', 'America/Ojinaga'), ('America/Panama', 'America/Panama'), ('America/Pangnirtung', 'America/Pangnirtung'), ('America/Paramaribo', 'America/Paramaribo'), ('America/Phoenix', 'America/Phoenix'), ('America/Port-au-Prince', 'America/Port-au-Prince'), ('America/Port_of_Spain', 'America/Port_of_Spain'), ('America/Porto_Acre', 'America/Porto_Acre'), ('America/Porto_Velho', 'America/Porto_Velho'), ('America/Puerto_Rico', 'America/Puerto_Rico'), ('America/Punta_Arenas', 'America/Punta_Arenas'), ('America/Rainy_River', 'America/Rainy_River'), ('America/Rankin_Inlet', 'America/Rankin_Inlet'), ('America/Recife', 'America/Recife'), ('America/Regina', 'America/Regina'), ('America/Resolute', 'America/Resolute'), ('America/Rio_Branco', 'America/Rio_Branco'), ('America/Rosario', 'America/Rosario'), ('America/Santa_Isabel', 'America/Santa_Isabel'), ('America/Santarem', 'America/Santarem'), ('America/Santiago', 'America/Santiago'), ('America/Santo_Domingo', 'America/Santo_Domingo'), ('America/Sao_Paulo', 'America/Sao_Paulo'), ('America/Scoresbysund', 'America/Scoresbysund'), ('America/Shiprock', 'America/Shiprock'), ('America/Sitka', 'America/Sitka'), ('America/St_Barthelemy', 'America/St_Barthelemy'), ('America/St_Johns', 'America/St_Johns'), ('America/St_Kitts', 'America/St_Kitts'), ('America/St_Lucia', 'America/St_Lucia'), ('America/St_Thomas', 'America/St_Thomas'), ('America/St_Vincent', 'America/St_Vincent'), ('America/Swift_Current', 'America/Swift_Current'), ('America/Tegucigalpa', 'America/Tegucigalpa'), ('America/Thule', 'America/Thule'), ('America/Thunder_Bay', 'America/Thunder_Bay'), ('America/Tijuana', 'America/Tijuana'), ('America/Toronto', 'America/Toronto'), ('America/Tortola', 'America/Tortola'), ('America/Vancouver', 'America/Vancouver'), ('America/Virgin', 'America/Virgin'), ('America/Whitehorse', 'America/Whitehorse'), ('America/Winnipeg', 'America/Winnipeg'), ('America/Yakutat', 'America/Yakutat'), ('America/Yellowknife', 'America/Yellowknife'), ('Antarctica/Casey', 'Antarctica/Casey'), ('Antarctica/Davis', 'Antarctica/Davis'), ('Antarctica/DumontDUrville', 'Antarctica/DumontDUrville'), ('Antarctica/Macquarie', 'Antarctica/Macquarie'), ('Antarctica/Mawson', 'Antarctica/Mawson'), ('Antarctica/McMurdo', 'Antarctica/McMurdo'), ('Antarctica/Palmer', 'Antarctica/Palmer'), ('Antarctica/Rothera', 'Antarctica/Rothera'), ('Antarctica/South_Pole', 'Antarctica/South_Pole'), ('Antarctica/Syowa', 'Antarctica/Syowa'), ('Antarctica/Troll', 'Antarctica/Troll'), ('Antarctica/Vostok', 'Antarctica/Vostok'), ('Arctic/Longyearbyen', 'Arctic/Longyearbyen'), ('Asia/Aden', 'Asia/Aden'), ('Asia/Almaty', 'Asia/Almaty'), ('Asia/Amman', 'Asia/Amman'), ('Asia/Anadyr', 'Asia/Anadyr'), ('Asia/Aqtau', 'Asia/Aqtau'), ('Asia/Aqtobe', 'Asia/Aqtobe'), ('Asia/Ashgabat', 'Asia/Ashgabat'), ('Asia/Ashkhabad', 'Asia/Ashkhabad'), ('Asia/Atyrau', 'Asia/Atyrau'), ('Asia/Baghdad', 'Asia/Baghdad'), ('Asia/Bahrain', 'Asia/Bahrain'), ('Asia/Baku', 'Asia/Baku'), ('Asia/Bangkok', 'Asia/Bangkok'), ('Asia/Barnaul', 'Asia/Barnaul'), ('Asia/Beirut', 'Asia/Beirut'), ('Asia/Bishkek', 'Asia/Bishkek'), ('Asia/Brunei', 'Asia/Brunei'), ('Asia/Calcutta', 'Asia/Calcutta'), ('Asia/Chita', 'Asia/Chita'), ('Asia/Choibalsan', 'Asia/Choibalsan'), ('Asia/Chongqing', 'Asia/Chongqing'), ('Asia/Chungking', 'Asia/Chungking'), ('Asia/Colombo', 'Asia/Colombo'), ('Asia/Dacca', 'Asia/Dacca'), ('Asia/Damascus', 'Asia/Damascus'), ('Asia/Dhaka', 'Asia/Dhaka'), ('Asia/Dili', 'Asia/Dili'), ('Asia/Dubai', 'Asia/Dubai'), ('Asia/Dushanbe', 'Asia/Dushanbe'), ('Asia/Famagusta', 'Asia/Famagusta'), ('Asia/Gaza', 'Asia/Gaza'), ('Asia/Harbin', 'Asia/Harbin'), ('Asia/Hebron', 'Asia/Hebron'), ('Asia/Ho_Chi_Minh', 'Asia/Ho_Chi_Minh'), ('Asia/Hong_Kong', 'Asia/Hong_Kong'), ('Asia/Hovd', 'Asia/Hovd'), ('Asia/Irkutsk', 'Asia/Irkutsk'), ('Asia/Istanbul', 'Asia/Istanbul'), ('Asia/Jakarta', 'Asia/Jakarta'), ('Asia/Jayapura', 'Asia/Jayapura'), ('Asia/Jerusalem', 'Asia/Jerusalem'), ('Asia/Kabul', 'Asia/Kabul'), ('Asia/Kamchatka', 'Asia/Kamchatka'), ('Asia/Karachi', 'Asia/Karachi'), ('Asia/Kashgar', 'Asia/Kashgar'), ('Asia/Kathmandu', 'Asia/Kathmandu'), ('Asia/Katmandu', 'Asia/Katmandu'), ('Asia/Khandyga', 'Asia/Khandyga'), ('Asia/Kolkata', 'Asia/Kolkata'), ('Asia/Krasnoyarsk', 'Asia/Krasnoyarsk'), ('Asia/Kuala_Lumpur', 'Asia/Kuala_Lumpur'), ('Asia/Kuching', 'Asia/Kuching'), ('Asia/Kuwait', 'Asia/Kuwait'), ('Asia/Macao', 'Asia/Macao'), ('Asia/Macau', 'Asia/Macau'), ('Asia/Magadan', 'Asia/Magadan'), ('Asia/Makassar', 'Asia/Makassar'), ('Asia/Manila', 'Asia/Manila'), ('Asia/Muscat', 'Asia/Muscat'), ('Asia/Nicosia', 'Asia/Nicosia'), ('Asia/Novokuznetsk', 'Asia/Novokuznetsk'), ('Asia/Novosibirsk', 'Asia/Novosibirsk'), ('Asia/Omsk', 'Asia/Omsk'), ('Asia/Oral', 'Asia/Oral'), ('Asia/Phnom_Penh', 'Asia/Phnom_Penh'), ('Asia/Pontianak', 'Asia/Pontianak'), ('Asia/Pyongyang', 'Asia/Pyongyang'), ('Asia/Qatar', 'Asia/Qatar'), ('Asia/Qostanay', 'Asia/Qostanay'), ('Asia/Qyzylorda', 'Asia/Qyzylorda'), ('Asia/Rangoon', 'Asia/Rangoon'), ('Asia/Riyadh', 'Asia/Riyadh'), ('Asia/Saigon', 'Asia/Saigon'), ('Asia/Sakhalin', 'Asia/Sakhalin'), ('Asia/Samarkand', 'Asia/Samarkand'), ('Asia/Seoul', 'Asia/Seoul'), ('Asia/Shanghai', 'Asia/Shanghai'), ('Asia/Singapore', 'Asia/Singapore'), ('Asia/Srednekolymsk', 'Asia/Srednekolymsk'), ('Asia/Taipei', 'Asia/Taipei'), ('Asia/Tashkent', 'Asia/Tashkent'), ('Asia/Tbilisi', 'Asia/Tbilisi'), ('Asia/Tehran', 'Asia/Tehran'), ('Asia/Tel_Aviv', 'Asia/Tel_Aviv'), ('Asia/Thimbu', 'Asia/Thimbu'), ('Asia/Thimphu', 'Asia/Thimphu'), ('Asia/Tokyo', 'Asia/Tokyo'), ('Asia/Tomsk', 'Asia/Tomsk'), ('Asia/Ujung_Pandang', 'Asia/Ujung_Pandang'), ('Asia/Ulaanbaatar', 'Asia/Ulaanbaatar'), ('Asia/Ulan_Bator', 'Asia/Ulan_Bator'), ('Asia/Urumqi', 'Asia/Urumqi'), ('Asia/Ust-Nera', 'Asia/Ust-Nera'), ('Asia/Vientiane', 'Asia/Vientiane'), ('Asia/Vladivostok', 'Asia/Vladivostok'), ('Asia/Yakutsk', 'Asia/Yakutsk'), ('Asia/Yangon', 'Asia/Yangon'), ('Asia/Yekaterinburg', 'Asia/Yekaterinburg'), ('Asia/Yerevan', 'Asia/Yerevan'), ('Atlantic/Azores', 'Atlantic/Azores'), ('Atlantic/Bermuda', 'Atlantic/Bermuda'), ('Atlantic/Canary', 'Atlantic/Canary'), ('Atlantic/Cape_Verde', 'Atlantic/Cape_Verde'), ('Atlantic/Faeroe', 'Atlantic/Faeroe'), ('Atlantic/Faroe', 'Atlantic/Faroe'), ('Atlantic/Jan_Mayen', 'Atlantic/Jan_Mayen'), ('Atlantic/Madeira', 'Atlantic/Madeira'), ('Atlantic/Reykjavik', 'Atlantic/Reykjavik'), ('Atlantic/South_Georgia', 'Atlantic/South_Georgia'), ('Atlantic/St_Helena', 'Atlantic/St_Helena'), ('Atlantic/Stanley', 'Atlantic/Stanley'), ('Australia/ACT', 'Australia/ACT'), ('Australia/Adelaide', 'Australia/Adelaide'), ('Australia/Brisbane', 'Australia/Brisbane'), ('Australia/Broken_Hill', 'Australia/Broken_Hill'), ('Australia/Canberra', 'Australia/Canberra'), ('Australia/Currie', 'Australia/Currie'), ('Australia/Darwin', 'Australia/Darwin'), ('Australia/Eucla', 'Australia/Eucla'), ('Australia/Hobart', 'Australia/Hobart'), ('Australia/LHI', 'Australia/LHI'), ('Australia/Lindeman', 'Australia/Lindeman'), ('Australia/Lord_Howe', 'Australia/Lord_Howe'), ('Australia/Melbourne', 'Australia/Melbourne'), ('Australia/NSW', 'Australia/NSW'), ('Australia/North', 'Australia/North'), ('Australia/Perth', 'Australia/Perth'), ('Australia/Queensland', 'Australia/Queensland'), ('Australia/South', 'Australia/South'), ('Australia/Sydney', 'Australia/Sydney'), ('Australia/Tasmania', 'Australia/Tasmania'), ('Australia/Victoria', 'Australia/Victoria'), ('Australia/West', 'Australia/West'), ('Australia/Yancowinna', 'Australia/Yancowinna'), ('Brazil/Acre', 'Brazil/Acre'), ('Brazil/DeNoronha', 'Brazil/DeNoronha'), ('Brazil/East', 'Brazil/East'), ('Brazil/West', 'Brazil/West'), ('CET', 'CET'), ('CST6CDT', 'CST6CDT'), ('Canada/Atlantic', 'Canada/Atlantic'), ('Canada/Central', 'Canada/Central'), ('Canada/Eastern', 'Canada/Eastern'), ('Canada/Mountain', 'Canada/Mountain'), ('Canada/Newfoundland', 'Canada/Newfoundland'), ('Canada/Pacific', 'Canada/Pacific'), ('Canada/Saskatchewan', 'Canada/Saskatchewan'), ('Canada/Yukon', 'Canada/Yukon'), ('Chile/Continental', 'Chile/Continental'), ('Chile/EasterIsland', 'Chile/EasterIsland'), ('Cuba', 'Cuba'), ('EET', 'EET'), ('EST', 'EST'), ('EST5EDT', 'EST5EDT'), ('Egypt', 'Egypt'), ('Eire', 'Eire'), ('Etc/GMT', 'Etc/GMT'), ('Etc/GMT+0', 'Etc/GMT+0'), ('Etc/GMT+1', 'Etc/GMT+1'), ('Etc/GMT+10', 'Etc/GMT+10'), ('Etc/GMT+11', 'Etc/GMT+11'), ('Etc/GMT+12', 'Etc/GMT+12'), ('Etc/GMT+2', 'Etc/GMT+2'), ('Etc/GMT+3', 'Etc/GMT+3'), ('Etc/GMT+4', 'Etc/GMT+4'), ('Etc/GMT+5', 'Etc/GMT+5'), ('Etc/GMT+6', 'Etc/GMT+6'), ('Etc/GMT+7', 'Etc/GMT+7'), ('Etc/GMT+8', 'Etc/GMT+8'), ('Etc/GMT+9', 'Etc/GMT+9'), ('Etc/GMT-0', 'Etc/GMT-0'), ('Etc/GMT-1', 'Etc/GMT-1'), ('Etc/GMT-10', 'Etc/GMT-10'), ('Etc/GMT-11', 'Etc/GMT-11'), ('Etc/GMT-12', 'Etc/GMT-12'), ('Etc/GMT-13', 'Etc/GMT-13'), ('Etc/GMT-14', 'Etc/GMT-14'), ('Etc/GMT-2', 'Etc/GMT-2'), ('Etc/GMT-3', 'Etc/GMT-3'), ('Etc/GMT-4', 'Etc/GMT-4'), ('Etc/GMT-5', 'Etc/GMT-5'), ('Etc/GMT-6', 'Etc/GMT-6'), ('Etc/GMT-7', 'Etc/GMT-7'), ('Etc/GMT-8', 'Etc/GMT-8'), ('Etc/GMT-9', 'Etc/GMT-9'), ('Etc/GMT0', 'Etc/GMT0'), ('Etc/Greenwich', 'Etc/Greenwich'), ('Etc/UCT', 'Etc/UCT'), ('Etc/UTC', 'Etc/UTC'), ('Etc/Universal', 'Etc/Universal'), ('Etc/Zulu', 'Etc/Zulu'), ('Europe/Amsterdam', 'Europe/Amsterdam'), ('Europe/Andorra', 'Europe/Andorra'), ('Europe/Astrakhan', 'Europe/Astrakhan'), ('Europe/Athens', 'Europe/Athens'), ('Europe/Belfast', 'Europe/Belfast'), ('Europe/Belgrade', 'Europe/Belgrade'), ('Europe/Berlin', 'Europe/Berlin'), ('Europe/Bratislava', 'Europe/Bratislava'), ('Europe/Brussels', 'Europe/Brussels'), ('Europe/Bucharest', 'Europe/Bucharest'), ('Europe/Budapest', 'Europe/Budapest'), ('Europe/Busingen', 'Europe/Busingen'), ('Europe/Chisinau', 'Europe/Chisinau'), ('Europe/Copenhagen', 'Europe/Copenhagen'), ('Europe/Dublin', 'Europe/Dublin'), ('Europe/Gibraltar', 'Europe/Gibraltar'), ('Europe/Guernsey', 'Europe/Guernsey'), ('Europe/Helsinki', 'Europe/Helsinki'), ('Europe/Isle_of_Man', 'Europe/Isle_of_Man'), ('Europe/Istanbul', 'Europe/Istanbul'), ('Europe/Jersey', 'Europe/Jersey'), ('Europe/Kaliningrad', 'Europe/Kaliningrad'), ('Europe/Kiev', 'Europe/Kiev'), ('Europe/Kirov', 'Europe/Kirov'), ('Europe/Kyiv', 'Europe/Kyiv'), ('Europe/Lisbon', 'Europe/Lisbon'), ('Europe/Ljubljana', 'Europe/Ljubljana'), ('Europe/London', 'Europe/London'), ('Europe/Luxembourg', 'Europe/Luxembourg'), ('Europe/Madrid', 'Europe/Madrid'), ('Europe/Malta', 'Europe/Malta'), ('Europe/Mariehamn', 'Europe/Mariehamn'), ('Europe/Minsk', 'Europe/Minsk'), ('Europe/Monaco', 'Europe/Monaco'), ('Europe/Moscow', 'Europe/Moscow'), ('Europe/Nicosia', 'Europe/Nicosia'), ('Europe/Oslo', 'Europe/Oslo'), ('Europe/Paris', 'Europe/Paris'), ('Europe/Podgorica', 'Europe/Podgorica'), ('Europe/Prague', 'Europe/Prague'), ('Europe/Riga', 'Europe/Riga'), ('Europe/Rome', 'Europe/Rome'), ('Europe/Samara', 'Europe/Samara'), ('Europe/San_Marino', 'Europe/San_Marino'), ('Europe/Sarajevo', 'Europe/Sarajevo'), ('Europe/Saratov', 'Europe/Saratov'), ('Europe/Simferopol', 'Europe/Simferopol'), ('Europe/Skopje', 'Europe/Skopje'), ('Europe/Sofia', 'Europe/Sofia'), ('Europe/Stockholm', 'Europe/Stockholm'), ('Europe/Tallinn', 'Europe/Tallinn'), ('Europe/Tirane', 'Europe/Tirane'), ('Europe/Tiraspol', 'Europe/Tiraspol'), ('Europe/Ulyanovsk', 'Europe/Ulyanovsk'), ('Europe/Uzhgorod', 'Europe/Uzhgorod'), ('Europe/Vaduz', 'Europe/Vaduz'), ('Europe/Vatican', 'Europe/Vatican'), ('Europe/Vienna', 'Europe/Vienna'), ('Europe/Vilnius', 'Europe/Vilnius'), ('Europe/Volgograd', 'Europe/Volgograd'), ('Europe/Warsaw', 'Europe/Warsaw'), ('Europe/Zagreb', 'Europe/Zagreb'), ('Europe/Zaporozhye', 'Europe/Zaporozhye'), ('Europe/Zurich', 'Europe/Zurich'), ('Factory', 'Factory'), ('GB', 'GB'), ('GB-Eire', 'GB-Eire'), ('GMT', 'GMT'), ('GMT+0', 'GMT+0'), ('GMT-0', 'GMT-0'), ('GMT0', 'GMT0'), ('Greenwich', 'Greenwich'), ('HST', 'HST'), ('Hongkong', 'Hongkong'), ('Iceland', 'Iceland'), ('Indian/Antananarivo', 'Indian/Antananarivo'), ('Indian/Chagos', 'Indian/Chagos'), ('Indian/Christmas', 'Indian/Christmas'), ('Indian/Cocos', 'Indian/Cocos'), ('Indian/Comoro', 'Indian/Comoro'), ('Indian/Kerguelen', 'Indian/Kerguelen'), ('Indian/Mahe', 'Indian/Mahe'), ('Indian/Maldives', 'Indian/Maldives'), ('Indian/Mauritius', 'Indian/Mauritius'), ('Indian/Mayotte', 'Indian/Mayotte'), ('Indian/Reunion', 'Indian/Reunion'), ('Iran', 'Iran'), ('Israel', 'Israel'), ('Jamaica', 'Jamaica'), ('Japan', 'Japan'), ('Kwajalein', 'Kwajalein'), ('Libya', 'Libya'), ('MET', 'MET'), ('MST', 'MST'), ('MST7MDT', 'MST7MDT'), ('Mexico/BajaNorte', 'Mexico/BajaNorte'), ('Mexico/BajaSur', 'Mexico/BajaSur'), ('Mexico/General', 'Mexico/General'), ('NZ', 'NZ'), ('NZ-CHAT', 'NZ-CHAT'), ('Navajo', 'Navajo'), ('PRC', 'PRC'), ('PST8PDT', 'PST8PDT'), ('Pacific/Apia', 'Pacific/Apia'), ('Pacific/Auckland', 'Pacific/Auckland'), ('Pacific/Bougainville', 'Pacific/Bougainville'), ('Pacific/Chatham', 'Pacific/Chatham'), ('Pacific/Chuuk', 'Pacific/Chuuk'), ('Pacific/Easter', 'Pacific/Easter'), ('Pacific/Efate', 'Pacific/Efate'), ('Pacific/Enderbury', 'Pacific/Enderbury'), ('Pacific/Fakaofo', 'Pacific/Fakaofo'), ('Pacific/Fiji', 'Pacific/Fiji'), ('Pacific/Funafuti', 'Pacific/Funafuti'), ('Pacific/Galapagos', 'Pacific/Galapagos'), ('Pacific/Gambier', 'Pacific/Gambier'), ('Pacific/Guadalcanal', 'Pacific/Guadalcanal'), ('Pacific/Guam', 'Pacific/Guam'), ('Pacific/Honolulu', 'Pacific/Honolulu'), ('Pacific/Johnston', 'Pacific/Johnston'), ('Pacific/Kanton', 'Pacific/Kanton'), ('Pacific/Kiritimati', 'Pacific/Kiritimati'), ('Pacific/Kosrae', 'Pacific/Kosrae'), ('Pacific/Kwajalein', 'Pacific/Kwajalein'), ('Pacific/Majuro', 'Pacific/Majuro'), ('Pacific/Marquesas', 'Pacific/Marquesas'), ('Pacific/Midway', 'Pacific/Midway'), ('Pacific/Nauru', 'Pacific/Nauru'), ('Pacific/Niue', 'Pacific/Niue'), ('Pacific/Norfolk', 'Pacific/Norfolk'), ('Pacific/Noumea', 'Pacific/Noumea'), ('Pacific/Pago_Pago', 'Pacific/Pago_Pago'), ('Pacific/Palau', 'Pacific/Palau'), ('Pacific/Pitcairn', 'Pacific/Pitcairn'), ('Pacific/Pohnpei', 'Pacific/Pohnpei'), ('Pacific/Ponape', 'Pacific/Ponape'), ('Pacific/Port_Moresby', 'Pacific/Port_Moresby'), ('Pacific/Rarotonga', 'Pacific/Rarotonga'), ('Pacific/Saipan', 'Pacific/Saipan'), ('Pacific/Samoa', 'Pacific/Samoa'), ('Pacific/Tahiti', 'Pacific/Tahiti'), ('Pacific/Tarawa', 'Pacific/Tarawa'), ('Pacific/Tongatapu', 'Pacific/Tongatapu'), ('Pacific/Truk', 'Pacific/Truk'), ('Pacific/Wake', 'Pacific/Wake'), ('Pacific/Wallis', 'Pacific/Wallis'), ('Pacific/Yap', 'Pacific/Yap'), ('Poland', 'Poland'), ('Portugal', 'Portugal'), ('ROC', 'ROC'), ('ROK', 'ROK'), ('Singapore', 'Singapore'), ('Turkey', 'Turkey'), ('UCT', 'UCT'), ('US/Alaska', 'US/Alaska'), ('US/Aleutian', 'US/Aleutian'), ('US/Arizona', 'US/Arizona'), ('US/Central', 'US/Central'), ('US/East-Indiana', 'US/East-Indiana'), ('US/Eastern', 'US/Eastern'), ('US/Hawaii', 'US/Hawaii'), ('US/Indiana-Starke', 'US/Indiana-Starke'), ('US/Michigan', 'US/Michigan'), ('US/Mountain', 'US/Mountain'), ('US/Pacific', 'US/Pacific'), ('US/Samoa', 'US/Samoa'), ('UTC', 'UTC'), ('Universal', 'Universal'), ('W-SU', 'W-SU'), ('WET', 'WET'), ('Zulu', 'Zulu'), ('localtime', 'localtime')], default='CET', max_length=50, null=True),
+ ),
+ ]
diff --git a/tournaments/migrations/0134_alter_club_timezone.py b/tournaments/migrations/0134_alter_club_timezone.py
new file mode 100644
index 0000000..04cc7f6
--- /dev/null
+++ b/tournaments/migrations/0134_alter_club_timezone.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.1 on 2025-07-09 15:18
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('tournaments', '0133_alter_club_timezone'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='club',
+ name='timezone',
+ field=models.CharField(blank=True, choices=[('Africa/Abidjan', 'Africa/Abidjan'), ('Africa/Accra', 'Africa/Accra'), ('Africa/Addis_Ababa', 'Africa/Addis_Ababa'), ('Africa/Algiers', 'Africa/Algiers'), ('Africa/Asmara', 'Africa/Asmara'), ('Africa/Asmera', 'Africa/Asmera'), ('Africa/Bamako', 'Africa/Bamako'), ('Africa/Bangui', 'Africa/Bangui'), ('Africa/Banjul', 'Africa/Banjul'), ('Africa/Bissau', 'Africa/Bissau'), ('Africa/Blantyre', 'Africa/Blantyre'), ('Africa/Brazzaville', 'Africa/Brazzaville'), ('Africa/Bujumbura', 'Africa/Bujumbura'), ('Africa/Cairo', 'Africa/Cairo'), ('Africa/Casablanca', 'Africa/Casablanca'), ('Africa/Ceuta', 'Africa/Ceuta'), ('Africa/Conakry', 'Africa/Conakry'), ('Africa/Dakar', 'Africa/Dakar'), ('Africa/Dar_es_Salaam', 'Africa/Dar_es_Salaam'), ('Africa/Djibouti', 'Africa/Djibouti'), ('Africa/Douala', 'Africa/Douala'), ('Africa/El_Aaiun', 'Africa/El_Aaiun'), ('Africa/Freetown', 'Africa/Freetown'), ('Africa/Gaborone', 'Africa/Gaborone'), ('Africa/Harare', 'Africa/Harare'), ('Africa/Johannesburg', 'Africa/Johannesburg'), ('Africa/Juba', 'Africa/Juba'), ('Africa/Kampala', 'Africa/Kampala'), ('Africa/Khartoum', 'Africa/Khartoum'), ('Africa/Kigali', 'Africa/Kigali'), ('Africa/Kinshasa', 'Africa/Kinshasa'), ('Africa/Lagos', 'Africa/Lagos'), ('Africa/Libreville', 'Africa/Libreville'), ('Africa/Lome', 'Africa/Lome'), ('Africa/Luanda', 'Africa/Luanda'), ('Africa/Lubumbashi', 'Africa/Lubumbashi'), ('Africa/Lusaka', 'Africa/Lusaka'), ('Africa/Malabo', 'Africa/Malabo'), ('Africa/Maputo', 'Africa/Maputo'), ('Africa/Maseru', 'Africa/Maseru'), ('Africa/Mbabane', 'Africa/Mbabane'), ('Africa/Mogadishu', 'Africa/Mogadishu'), ('Africa/Monrovia', 'Africa/Monrovia'), ('Africa/Nairobi', 'Africa/Nairobi'), ('Africa/Ndjamena', 'Africa/Ndjamena'), ('Africa/Niamey', 'Africa/Niamey'), ('Africa/Nouakchott', 'Africa/Nouakchott'), ('Africa/Ouagadougou', 'Africa/Ouagadougou'), ('Africa/Porto-Novo', 'Africa/Porto-Novo'), ('Africa/Sao_Tome', 'Africa/Sao_Tome'), ('Africa/Timbuktu', 'Africa/Timbuktu'), ('Africa/Tripoli', 'Africa/Tripoli'), ('Africa/Tunis', 'Africa/Tunis'), ('Africa/Windhoek', 'Africa/Windhoek'), ('America/Adak', 'America/Adak'), ('America/Anchorage', 'America/Anchorage'), ('America/Anguilla', 'America/Anguilla'), ('America/Antigua', 'America/Antigua'), ('America/Araguaina', 'America/Araguaina'), ('America/Argentina/Buenos_Aires', 'America/Argentina/Buenos_Aires'), ('America/Argentina/Catamarca', 'America/Argentina/Catamarca'), ('America/Argentina/ComodRivadavia', 'America/Argentina/ComodRivadavia'), ('America/Argentina/Cordoba', 'America/Argentina/Cordoba'), ('America/Argentina/Jujuy', 'America/Argentina/Jujuy'), ('America/Argentina/La_Rioja', 'America/Argentina/La_Rioja'), ('America/Argentina/Mendoza', 'America/Argentina/Mendoza'), ('America/Argentina/Rio_Gallegos', 'America/Argentina/Rio_Gallegos'), ('America/Argentina/Salta', 'America/Argentina/Salta'), ('America/Argentina/San_Juan', 'America/Argentina/San_Juan'), ('America/Argentina/San_Luis', 'America/Argentina/San_Luis'), ('America/Argentina/Tucuman', 'America/Argentina/Tucuman'), ('America/Argentina/Ushuaia', 'America/Argentina/Ushuaia'), ('America/Aruba', 'America/Aruba'), ('America/Asuncion', 'America/Asuncion'), ('America/Atikokan', 'America/Atikokan'), ('America/Atka', 'America/Atka'), ('America/Bahia', 'America/Bahia'), ('America/Bahia_Banderas', 'America/Bahia_Banderas'), ('America/Barbados', 'America/Barbados'), ('America/Belem', 'America/Belem'), ('America/Belize', 'America/Belize'), ('America/Blanc-Sablon', 'America/Blanc-Sablon'), ('America/Boa_Vista', 'America/Boa_Vista'), ('America/Bogota', 'America/Bogota'), ('America/Boise', 'America/Boise'), ('America/Buenos_Aires', 'America/Buenos_Aires'), ('America/Cambridge_Bay', 'America/Cambridge_Bay'), ('America/Campo_Grande', 'America/Campo_Grande'), ('America/Cancun', 'America/Cancun'), ('America/Caracas', 'America/Caracas'), ('America/Catamarca', 'America/Catamarca'), ('America/Cayenne', 'America/Cayenne'), ('America/Cayman', 'America/Cayman'), ('America/Chicago', 'America/Chicago'), ('America/Chihuahua', 'America/Chihuahua'), ('America/Ciudad_Juarez', 'America/Ciudad_Juarez'), ('America/Coral_Harbour', 'America/Coral_Harbour'), ('America/Cordoba', 'America/Cordoba'), ('America/Costa_Rica', 'America/Costa_Rica'), ('America/Coyhaique', 'America/Coyhaique'), ('America/Creston', 'America/Creston'), ('America/Cuiaba', 'America/Cuiaba'), ('America/Curacao', 'America/Curacao'), ('America/Danmarkshavn', 'America/Danmarkshavn'), ('America/Dawson', 'America/Dawson'), ('America/Dawson_Creek', 'America/Dawson_Creek'), ('America/Denver', 'America/Denver'), ('America/Detroit', 'America/Detroit'), ('America/Dominica', 'America/Dominica'), ('America/Edmonton', 'America/Edmonton'), ('America/Eirunepe', 'America/Eirunepe'), ('America/El_Salvador', 'America/El_Salvador'), ('America/Ensenada', 'America/Ensenada'), ('America/Fort_Nelson', 'America/Fort_Nelson'), ('America/Fort_Wayne', 'America/Fort_Wayne'), ('America/Fortaleza', 'America/Fortaleza'), ('America/Glace_Bay', 'America/Glace_Bay'), ('America/Godthab', 'America/Godthab'), ('America/Goose_Bay', 'America/Goose_Bay'), ('America/Grand_Turk', 'America/Grand_Turk'), ('America/Grenada', 'America/Grenada'), ('America/Guadeloupe', 'America/Guadeloupe'), ('America/Guatemala', 'America/Guatemala'), ('America/Guayaquil', 'America/Guayaquil'), ('America/Guyana', 'America/Guyana'), ('America/Halifax', 'America/Halifax'), ('America/Havana', 'America/Havana'), ('America/Hermosillo', 'America/Hermosillo'), ('America/Indiana/Indianapolis', 'America/Indiana/Indianapolis'), ('America/Indiana/Knox', 'America/Indiana/Knox'), ('America/Indiana/Marengo', 'America/Indiana/Marengo'), ('America/Indiana/Petersburg', 'America/Indiana/Petersburg'), ('America/Indiana/Tell_City', 'America/Indiana/Tell_City'), ('America/Indiana/Vevay', 'America/Indiana/Vevay'), ('America/Indiana/Vincennes', 'America/Indiana/Vincennes'), ('America/Indiana/Winamac', 'America/Indiana/Winamac'), ('America/Indianapolis', 'America/Indianapolis'), ('America/Inuvik', 'America/Inuvik'), ('America/Iqaluit', 'America/Iqaluit'), ('America/Jamaica', 'America/Jamaica'), ('America/Jujuy', 'America/Jujuy'), ('America/Juneau', 'America/Juneau'), ('America/Kentucky/Louisville', 'America/Kentucky/Louisville'), ('America/Kentucky/Monticello', 'America/Kentucky/Monticello'), ('America/Knox_IN', 'America/Knox_IN'), ('America/Kralendijk', 'America/Kralendijk'), ('America/La_Paz', 'America/La_Paz'), ('America/Lima', 'America/Lima'), ('America/Los_Angeles', 'America/Los_Angeles'), ('America/Louisville', 'America/Louisville'), ('America/Lower_Princes', 'America/Lower_Princes'), ('America/Maceio', 'America/Maceio'), ('America/Managua', 'America/Managua'), ('America/Manaus', 'America/Manaus'), ('America/Marigot', 'America/Marigot'), ('America/Martinique', 'America/Martinique'), ('America/Matamoros', 'America/Matamoros'), ('America/Mazatlan', 'America/Mazatlan'), ('America/Mendoza', 'America/Mendoza'), ('America/Menominee', 'America/Menominee'), ('America/Merida', 'America/Merida'), ('America/Metlakatla', 'America/Metlakatla'), ('America/Mexico_City', 'America/Mexico_City'), ('America/Miquelon', 'America/Miquelon'), ('America/Moncton', 'America/Moncton'), ('America/Monterrey', 'America/Monterrey'), ('America/Montevideo', 'America/Montevideo'), ('America/Montreal', 'America/Montreal'), ('America/Montserrat', 'America/Montserrat'), ('America/Nassau', 'America/Nassau'), ('America/New_York', 'America/New_York'), ('America/Nipigon', 'America/Nipigon'), ('America/Nome', 'America/Nome'), ('America/Noronha', 'America/Noronha'), ('America/North_Dakota/Beulah', 'America/North_Dakota/Beulah'), ('America/North_Dakota/Center', 'America/North_Dakota/Center'), ('America/North_Dakota/New_Salem', 'America/North_Dakota/New_Salem'), ('America/Nuuk', 'America/Nuuk'), ('America/Ojinaga', 'America/Ojinaga'), ('America/Panama', 'America/Panama'), ('America/Pangnirtung', 'America/Pangnirtung'), ('America/Paramaribo', 'America/Paramaribo'), ('America/Phoenix', 'America/Phoenix'), ('America/Port-au-Prince', 'America/Port-au-Prince'), ('America/Port_of_Spain', 'America/Port_of_Spain'), ('America/Porto_Acre', 'America/Porto_Acre'), ('America/Porto_Velho', 'America/Porto_Velho'), ('America/Puerto_Rico', 'America/Puerto_Rico'), ('America/Punta_Arenas', 'America/Punta_Arenas'), ('America/Rainy_River', 'America/Rainy_River'), ('America/Rankin_Inlet', 'America/Rankin_Inlet'), ('America/Recife', 'America/Recife'), ('America/Regina', 'America/Regina'), ('America/Resolute', 'America/Resolute'), ('America/Rio_Branco', 'America/Rio_Branco'), ('America/Rosario', 'America/Rosario'), ('America/Santa_Isabel', 'America/Santa_Isabel'), ('America/Santarem', 'America/Santarem'), ('America/Santiago', 'America/Santiago'), ('America/Santo_Domingo', 'America/Santo_Domingo'), ('America/Sao_Paulo', 'America/Sao_Paulo'), ('America/Scoresbysund', 'America/Scoresbysund'), ('America/Shiprock', 'America/Shiprock'), ('America/Sitka', 'America/Sitka'), ('America/St_Barthelemy', 'America/St_Barthelemy'), ('America/St_Johns', 'America/St_Johns'), ('America/St_Kitts', 'America/St_Kitts'), ('America/St_Lucia', 'America/St_Lucia'), ('America/St_Thomas', 'America/St_Thomas'), ('America/St_Vincent', 'America/St_Vincent'), ('America/Swift_Current', 'America/Swift_Current'), ('America/Tegucigalpa', 'America/Tegucigalpa'), ('America/Thule', 'America/Thule'), ('America/Thunder_Bay', 'America/Thunder_Bay'), ('America/Tijuana', 'America/Tijuana'), ('America/Toronto', 'America/Toronto'), ('America/Tortola', 'America/Tortola'), ('America/Vancouver', 'America/Vancouver'), ('America/Virgin', 'America/Virgin'), ('America/Whitehorse', 'America/Whitehorse'), ('America/Winnipeg', 'America/Winnipeg'), ('America/Yakutat', 'America/Yakutat'), ('America/Yellowknife', 'America/Yellowknife'), ('Antarctica/Casey', 'Antarctica/Casey'), ('Antarctica/Davis', 'Antarctica/Davis'), ('Antarctica/DumontDUrville', 'Antarctica/DumontDUrville'), ('Antarctica/Macquarie', 'Antarctica/Macquarie'), ('Antarctica/Mawson', 'Antarctica/Mawson'), ('Antarctica/McMurdo', 'Antarctica/McMurdo'), ('Antarctica/Palmer', 'Antarctica/Palmer'), ('Antarctica/Rothera', 'Antarctica/Rothera'), ('Antarctica/South_Pole', 'Antarctica/South_Pole'), ('Antarctica/Syowa', 'Antarctica/Syowa'), ('Antarctica/Troll', 'Antarctica/Troll'), ('Antarctica/Vostok', 'Antarctica/Vostok'), ('Arctic/Longyearbyen', 'Arctic/Longyearbyen'), ('Asia/Aden', 'Asia/Aden'), ('Asia/Almaty', 'Asia/Almaty'), ('Asia/Amman', 'Asia/Amman'), ('Asia/Anadyr', 'Asia/Anadyr'), ('Asia/Aqtau', 'Asia/Aqtau'), ('Asia/Aqtobe', 'Asia/Aqtobe'), ('Asia/Ashgabat', 'Asia/Ashgabat'), ('Asia/Ashkhabad', 'Asia/Ashkhabad'), ('Asia/Atyrau', 'Asia/Atyrau'), ('Asia/Baghdad', 'Asia/Baghdad'), ('Asia/Bahrain', 'Asia/Bahrain'), ('Asia/Baku', 'Asia/Baku'), ('Asia/Bangkok', 'Asia/Bangkok'), ('Asia/Barnaul', 'Asia/Barnaul'), ('Asia/Beirut', 'Asia/Beirut'), ('Asia/Bishkek', 'Asia/Bishkek'), ('Asia/Brunei', 'Asia/Brunei'), ('Asia/Calcutta', 'Asia/Calcutta'), ('Asia/Chita', 'Asia/Chita'), ('Asia/Choibalsan', 'Asia/Choibalsan'), ('Asia/Chongqing', 'Asia/Chongqing'), ('Asia/Chungking', 'Asia/Chungking'), ('Asia/Colombo', 'Asia/Colombo'), ('Asia/Dacca', 'Asia/Dacca'), ('Asia/Damascus', 'Asia/Damascus'), ('Asia/Dhaka', 'Asia/Dhaka'), ('Asia/Dili', 'Asia/Dili'), ('Asia/Dubai', 'Asia/Dubai'), ('Asia/Dushanbe', 'Asia/Dushanbe'), ('Asia/Famagusta', 'Asia/Famagusta'), ('Asia/Gaza', 'Asia/Gaza'), ('Asia/Harbin', 'Asia/Harbin'), ('Asia/Hebron', 'Asia/Hebron'), ('Asia/Ho_Chi_Minh', 'Asia/Ho_Chi_Minh'), ('Asia/Hong_Kong', 'Asia/Hong_Kong'), ('Asia/Hovd', 'Asia/Hovd'), ('Asia/Irkutsk', 'Asia/Irkutsk'), ('Asia/Istanbul', 'Asia/Istanbul'), ('Asia/Jakarta', 'Asia/Jakarta'), ('Asia/Jayapura', 'Asia/Jayapura'), ('Asia/Jerusalem', 'Asia/Jerusalem'), ('Asia/Kabul', 'Asia/Kabul'), ('Asia/Kamchatka', 'Asia/Kamchatka'), ('Asia/Karachi', 'Asia/Karachi'), ('Asia/Kashgar', 'Asia/Kashgar'), ('Asia/Kathmandu', 'Asia/Kathmandu'), ('Asia/Katmandu', 'Asia/Katmandu'), ('Asia/Khandyga', 'Asia/Khandyga'), ('Asia/Kolkata', 'Asia/Kolkata'), ('Asia/Krasnoyarsk', 'Asia/Krasnoyarsk'), ('Asia/Kuala_Lumpur', 'Asia/Kuala_Lumpur'), ('Asia/Kuching', 'Asia/Kuching'), ('Asia/Kuwait', 'Asia/Kuwait'), ('Asia/Macao', 'Asia/Macao'), ('Asia/Macau', 'Asia/Macau'), ('Asia/Magadan', 'Asia/Magadan'), ('Asia/Makassar', 'Asia/Makassar'), ('Asia/Manila', 'Asia/Manila'), ('Asia/Muscat', 'Asia/Muscat'), ('Asia/Nicosia', 'Asia/Nicosia'), ('Asia/Novokuznetsk', 'Asia/Novokuznetsk'), ('Asia/Novosibirsk', 'Asia/Novosibirsk'), ('Asia/Omsk', 'Asia/Omsk'), ('Asia/Oral', 'Asia/Oral'), ('Asia/Phnom_Penh', 'Asia/Phnom_Penh'), ('Asia/Pontianak', 'Asia/Pontianak'), ('Asia/Pyongyang', 'Asia/Pyongyang'), ('Asia/Qatar', 'Asia/Qatar'), ('Asia/Qostanay', 'Asia/Qostanay'), ('Asia/Qyzylorda', 'Asia/Qyzylorda'), ('Asia/Rangoon', 'Asia/Rangoon'), ('Asia/Riyadh', 'Asia/Riyadh'), ('Asia/Saigon', 'Asia/Saigon'), ('Asia/Sakhalin', 'Asia/Sakhalin'), ('Asia/Samarkand', 'Asia/Samarkand'), ('Asia/Seoul', 'Asia/Seoul'), ('Asia/Shanghai', 'Asia/Shanghai'), ('Asia/Singapore', 'Asia/Singapore'), ('Asia/Srednekolymsk', 'Asia/Srednekolymsk'), ('Asia/Taipei', 'Asia/Taipei'), ('Asia/Tashkent', 'Asia/Tashkent'), ('Asia/Tbilisi', 'Asia/Tbilisi'), ('Asia/Tehran', 'Asia/Tehran'), ('Asia/Tel_Aviv', 'Asia/Tel_Aviv'), ('Asia/Thimbu', 'Asia/Thimbu'), ('Asia/Thimphu', 'Asia/Thimphu'), ('Asia/Tokyo', 'Asia/Tokyo'), ('Asia/Tomsk', 'Asia/Tomsk'), ('Asia/Ujung_Pandang', 'Asia/Ujung_Pandang'), ('Asia/Ulaanbaatar', 'Asia/Ulaanbaatar'), ('Asia/Ulan_Bator', 'Asia/Ulan_Bator'), ('Asia/Urumqi', 'Asia/Urumqi'), ('Asia/Ust-Nera', 'Asia/Ust-Nera'), ('Asia/Vientiane', 'Asia/Vientiane'), ('Asia/Vladivostok', 'Asia/Vladivostok'), ('Asia/Yakutsk', 'Asia/Yakutsk'), ('Asia/Yangon', 'Asia/Yangon'), ('Asia/Yekaterinburg', 'Asia/Yekaterinburg'), ('Asia/Yerevan', 'Asia/Yerevan'), ('Atlantic/Azores', 'Atlantic/Azores'), ('Atlantic/Bermuda', 'Atlantic/Bermuda'), ('Atlantic/Canary', 'Atlantic/Canary'), ('Atlantic/Cape_Verde', 'Atlantic/Cape_Verde'), ('Atlantic/Faeroe', 'Atlantic/Faeroe'), ('Atlantic/Faroe', 'Atlantic/Faroe'), ('Atlantic/Jan_Mayen', 'Atlantic/Jan_Mayen'), ('Atlantic/Madeira', 'Atlantic/Madeira'), ('Atlantic/Reykjavik', 'Atlantic/Reykjavik'), ('Atlantic/South_Georgia', 'Atlantic/South_Georgia'), ('Atlantic/St_Helena', 'Atlantic/St_Helena'), ('Atlantic/Stanley', 'Atlantic/Stanley'), ('Australia/ACT', 'Australia/ACT'), ('Australia/Adelaide', 'Australia/Adelaide'), ('Australia/Brisbane', 'Australia/Brisbane'), ('Australia/Broken_Hill', 'Australia/Broken_Hill'), ('Australia/Canberra', 'Australia/Canberra'), ('Australia/Currie', 'Australia/Currie'), ('Australia/Darwin', 'Australia/Darwin'), ('Australia/Eucla', 'Australia/Eucla'), ('Australia/Hobart', 'Australia/Hobart'), ('Australia/LHI', 'Australia/LHI'), ('Australia/Lindeman', 'Australia/Lindeman'), ('Australia/Lord_Howe', 'Australia/Lord_Howe'), ('Australia/Melbourne', 'Australia/Melbourne'), ('Australia/NSW', 'Australia/NSW'), ('Australia/North', 'Australia/North'), ('Australia/Perth', 'Australia/Perth'), ('Australia/Queensland', 'Australia/Queensland'), ('Australia/South', 'Australia/South'), ('Australia/Sydney', 'Australia/Sydney'), ('Australia/Tasmania', 'Australia/Tasmania'), ('Australia/Victoria', 'Australia/Victoria'), ('Australia/West', 'Australia/West'), ('Australia/Yancowinna', 'Australia/Yancowinna'), ('Brazil/Acre', 'Brazil/Acre'), ('Brazil/DeNoronha', 'Brazil/DeNoronha'), ('Brazil/East', 'Brazil/East'), ('Brazil/West', 'Brazil/West'), ('CET', 'CET'), ('CST6CDT', 'CST6CDT'), ('Canada/Atlantic', 'Canada/Atlantic'), ('Canada/Central', 'Canada/Central'), ('Canada/Eastern', 'Canada/Eastern'), ('Canada/Mountain', 'Canada/Mountain'), ('Canada/Newfoundland', 'Canada/Newfoundland'), ('Canada/Pacific', 'Canada/Pacific'), ('Canada/Saskatchewan', 'Canada/Saskatchewan'), ('Canada/Yukon', 'Canada/Yukon'), ('Chile/Continental', 'Chile/Continental'), ('Chile/EasterIsland', 'Chile/EasterIsland'), ('Cuba', 'Cuba'), ('EET', 'EET'), ('EST', 'EST'), ('EST5EDT', 'EST5EDT'), ('Egypt', 'Egypt'), ('Eire', 'Eire'), ('Etc/GMT', 'Etc/GMT'), ('Etc/GMT+0', 'Etc/GMT+0'), ('Etc/GMT+1', 'Etc/GMT+1'), ('Etc/GMT+10', 'Etc/GMT+10'), ('Etc/GMT+11', 'Etc/GMT+11'), ('Etc/GMT+12', 'Etc/GMT+12'), ('Etc/GMT+2', 'Etc/GMT+2'), ('Etc/GMT+3', 'Etc/GMT+3'), ('Etc/GMT+4', 'Etc/GMT+4'), ('Etc/GMT+5', 'Etc/GMT+5'), ('Etc/GMT+6', 'Etc/GMT+6'), ('Etc/GMT+7', 'Etc/GMT+7'), ('Etc/GMT+8', 'Etc/GMT+8'), ('Etc/GMT+9', 'Etc/GMT+9'), ('Etc/GMT-0', 'Etc/GMT-0'), ('Etc/GMT-1', 'Etc/GMT-1'), ('Etc/GMT-10', 'Etc/GMT-10'), ('Etc/GMT-11', 'Etc/GMT-11'), ('Etc/GMT-12', 'Etc/GMT-12'), ('Etc/GMT-13', 'Etc/GMT-13'), ('Etc/GMT-14', 'Etc/GMT-14'), ('Etc/GMT-2', 'Etc/GMT-2'), ('Etc/GMT-3', 'Etc/GMT-3'), ('Etc/GMT-4', 'Etc/GMT-4'), ('Etc/GMT-5', 'Etc/GMT-5'), ('Etc/GMT-6', 'Etc/GMT-6'), ('Etc/GMT-7', 'Etc/GMT-7'), ('Etc/GMT-8', 'Etc/GMT-8'), ('Etc/GMT-9', 'Etc/GMT-9'), ('Etc/GMT0', 'Etc/GMT0'), ('Etc/Greenwich', 'Etc/Greenwich'), ('Etc/UCT', 'Etc/UCT'), ('Etc/UTC', 'Etc/UTC'), ('Etc/Universal', 'Etc/Universal'), ('Etc/Zulu', 'Etc/Zulu'), ('Europe/Amsterdam', 'Europe/Amsterdam'), ('Europe/Andorra', 'Europe/Andorra'), ('Europe/Astrakhan', 'Europe/Astrakhan'), ('Europe/Athens', 'Europe/Athens'), ('Europe/Belfast', 'Europe/Belfast'), ('Europe/Belgrade', 'Europe/Belgrade'), ('Europe/Berlin', 'Europe/Berlin'), ('Europe/Bratislava', 'Europe/Bratislava'), ('Europe/Brussels', 'Europe/Brussels'), ('Europe/Bucharest', 'Europe/Bucharest'), ('Europe/Budapest', 'Europe/Budapest'), ('Europe/Busingen', 'Europe/Busingen'), ('Europe/Chisinau', 'Europe/Chisinau'), ('Europe/Copenhagen', 'Europe/Copenhagen'), ('Europe/Dublin', 'Europe/Dublin'), ('Europe/Gibraltar', 'Europe/Gibraltar'), ('Europe/Guernsey', 'Europe/Guernsey'), ('Europe/Helsinki', 'Europe/Helsinki'), ('Europe/Isle_of_Man', 'Europe/Isle_of_Man'), ('Europe/Istanbul', 'Europe/Istanbul'), ('Europe/Jersey', 'Europe/Jersey'), ('Europe/Kaliningrad', 'Europe/Kaliningrad'), ('Europe/Kiev', 'Europe/Kiev'), ('Europe/Kirov', 'Europe/Kirov'), ('Europe/Kyiv', 'Europe/Kyiv'), ('Europe/Lisbon', 'Europe/Lisbon'), ('Europe/Ljubljana', 'Europe/Ljubljana'), ('Europe/London', 'Europe/London'), ('Europe/Luxembourg', 'Europe/Luxembourg'), ('Europe/Madrid', 'Europe/Madrid'), ('Europe/Malta', 'Europe/Malta'), ('Europe/Mariehamn', 'Europe/Mariehamn'), ('Europe/Minsk', 'Europe/Minsk'), ('Europe/Monaco', 'Europe/Monaco'), ('Europe/Moscow', 'Europe/Moscow'), ('Europe/Nicosia', 'Europe/Nicosia'), ('Europe/Oslo', 'Europe/Oslo'), ('Europe/Paris', 'Europe/Paris'), ('Europe/Podgorica', 'Europe/Podgorica'), ('Europe/Prague', 'Europe/Prague'), ('Europe/Riga', 'Europe/Riga'), ('Europe/Rome', 'Europe/Rome'), ('Europe/Samara', 'Europe/Samara'), ('Europe/San_Marino', 'Europe/San_Marino'), ('Europe/Sarajevo', 'Europe/Sarajevo'), ('Europe/Saratov', 'Europe/Saratov'), ('Europe/Simferopol', 'Europe/Simferopol'), ('Europe/Skopje', 'Europe/Skopje'), ('Europe/Sofia', 'Europe/Sofia'), ('Europe/Stockholm', 'Europe/Stockholm'), ('Europe/Tallinn', 'Europe/Tallinn'), ('Europe/Tirane', 'Europe/Tirane'), ('Europe/Tiraspol', 'Europe/Tiraspol'), ('Europe/Ulyanovsk', 'Europe/Ulyanovsk'), ('Europe/Uzhgorod', 'Europe/Uzhgorod'), ('Europe/Vaduz', 'Europe/Vaduz'), ('Europe/Vatican', 'Europe/Vatican'), ('Europe/Vienna', 'Europe/Vienna'), ('Europe/Vilnius', 'Europe/Vilnius'), ('Europe/Volgograd', 'Europe/Volgograd'), ('Europe/Warsaw', 'Europe/Warsaw'), ('Europe/Zagreb', 'Europe/Zagreb'), ('Europe/Zaporozhye', 'Europe/Zaporozhye'), ('Europe/Zurich', 'Europe/Zurich'), ('Factory', 'Factory'), ('GB', 'GB'), ('GB-Eire', 'GB-Eire'), ('GMT', 'GMT'), ('GMT+0', 'GMT+0'), ('GMT-0', 'GMT-0'), ('GMT0', 'GMT0'), ('Greenwich', 'Greenwich'), ('HST', 'HST'), ('Hongkong', 'Hongkong'), ('Iceland', 'Iceland'), ('Indian/Antananarivo', 'Indian/Antananarivo'), ('Indian/Chagos', 'Indian/Chagos'), ('Indian/Christmas', 'Indian/Christmas'), ('Indian/Cocos', 'Indian/Cocos'), ('Indian/Comoro', 'Indian/Comoro'), ('Indian/Kerguelen', 'Indian/Kerguelen'), ('Indian/Mahe', 'Indian/Mahe'), ('Indian/Maldives', 'Indian/Maldives'), ('Indian/Mauritius', 'Indian/Mauritius'), ('Indian/Mayotte', 'Indian/Mayotte'), ('Indian/Reunion', 'Indian/Reunion'), ('Iran', 'Iran'), ('Israel', 'Israel'), ('Jamaica', 'Jamaica'), ('Japan', 'Japan'), ('Kwajalein', 'Kwajalein'), ('Libya', 'Libya'), ('MET', 'MET'), ('MST', 'MST'), ('MST7MDT', 'MST7MDT'), ('Mexico/BajaNorte', 'Mexico/BajaNorte'), ('Mexico/BajaSur', 'Mexico/BajaSur'), ('Mexico/General', 'Mexico/General'), ('NZ', 'NZ'), ('NZ-CHAT', 'NZ-CHAT'), ('Navajo', 'Navajo'), ('PRC', 'PRC'), ('PST8PDT', 'PST8PDT'), ('Pacific/Apia', 'Pacific/Apia'), ('Pacific/Auckland', 'Pacific/Auckland'), ('Pacific/Bougainville', 'Pacific/Bougainville'), ('Pacific/Chatham', 'Pacific/Chatham'), ('Pacific/Chuuk', 'Pacific/Chuuk'), ('Pacific/Easter', 'Pacific/Easter'), ('Pacific/Efate', 'Pacific/Efate'), ('Pacific/Enderbury', 'Pacific/Enderbury'), ('Pacific/Fakaofo', 'Pacific/Fakaofo'), ('Pacific/Fiji', 'Pacific/Fiji'), ('Pacific/Funafuti', 'Pacific/Funafuti'), ('Pacific/Galapagos', 'Pacific/Galapagos'), ('Pacific/Gambier', 'Pacific/Gambier'), ('Pacific/Guadalcanal', 'Pacific/Guadalcanal'), ('Pacific/Guam', 'Pacific/Guam'), ('Pacific/Honolulu', 'Pacific/Honolulu'), ('Pacific/Johnston', 'Pacific/Johnston'), ('Pacific/Kanton', 'Pacific/Kanton'), ('Pacific/Kiritimati', 'Pacific/Kiritimati'), ('Pacific/Kosrae', 'Pacific/Kosrae'), ('Pacific/Kwajalein', 'Pacific/Kwajalein'), ('Pacific/Majuro', 'Pacific/Majuro'), ('Pacific/Marquesas', 'Pacific/Marquesas'), ('Pacific/Midway', 'Pacific/Midway'), ('Pacific/Nauru', 'Pacific/Nauru'), ('Pacific/Niue', 'Pacific/Niue'), ('Pacific/Norfolk', 'Pacific/Norfolk'), ('Pacific/Noumea', 'Pacific/Noumea'), ('Pacific/Pago_Pago', 'Pacific/Pago_Pago'), ('Pacific/Palau', 'Pacific/Palau'), ('Pacific/Pitcairn', 'Pacific/Pitcairn'), ('Pacific/Pohnpei', 'Pacific/Pohnpei'), ('Pacific/Ponape', 'Pacific/Ponape'), ('Pacific/Port_Moresby', 'Pacific/Port_Moresby'), ('Pacific/Rarotonga', 'Pacific/Rarotonga'), ('Pacific/Saipan', 'Pacific/Saipan'), ('Pacific/Samoa', 'Pacific/Samoa'), ('Pacific/Tahiti', 'Pacific/Tahiti'), ('Pacific/Tarawa', 'Pacific/Tarawa'), ('Pacific/Tongatapu', 'Pacific/Tongatapu'), ('Pacific/Truk', 'Pacific/Truk'), ('Pacific/Wake', 'Pacific/Wake'), ('Pacific/Wallis', 'Pacific/Wallis'), ('Pacific/Yap', 'Pacific/Yap'), ('Poland', 'Poland'), ('Portugal', 'Portugal'), ('ROC', 'ROC'), ('ROK', 'ROK'), ('Singapore', 'Singapore'), ('Turkey', 'Turkey'), ('UCT', 'UCT'), ('US/Alaska', 'US/Alaska'), ('US/Aleutian', 'US/Aleutian'), ('US/Arizona', 'US/Arizona'), ('US/Central', 'US/Central'), ('US/East-Indiana', 'US/East-Indiana'), ('US/Eastern', 'US/Eastern'), ('US/Hawaii', 'US/Hawaii'), ('US/Indiana-Starke', 'US/Indiana-Starke'), ('US/Michigan', 'US/Michigan'), ('US/Mountain', 'US/Mountain'), ('US/Pacific', 'US/Pacific'), ('US/Samoa', 'US/Samoa'), ('UTC', 'UTC'), ('Universal', 'Universal'), ('W-SU', 'W-SU'), ('WET', 'WET'), ('Zulu', 'Zulu')], default='CET', max_length=50, null=True),
+ ),
+ ]
diff --git a/tournaments/models/purchase.py b/tournaments/models/purchase.py
index 5d8e4bf..b978bb1 100644
--- a/tournaments/models/purchase.py
+++ b/tournaments/models/purchase.py
@@ -5,7 +5,7 @@ from . import BaseModel, CustomUser
class Purchase(BaseModel):
id = models.BigIntegerField(primary_key=True, unique=True, editable=True)
- user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
+ user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='purchases')
purchase_date = models.DateTimeField()
product_id = models.CharField(max_length=100)
quantity = models.IntegerField(null=True, blank=True)