Update to Django 2.2
Upgrade site and modules to Django 2.2. Remove and replace obsolete functionality with current equivalents. Update requirements to latest versions where possible. Remove unused dependencies.
This commit is contained in:
parent
ac57053ecf
commit
252697b842
78 changed files with 646 additions and 364 deletions
|
@ -1,2 +1,2 @@
|
||||||
django<1.12,>=1.11
|
django<3.0,>=2.2
|
||||||
pysaml2==4.8.0
|
pysaml2>=5.3.0
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM python:3.6-stretch as symposion_base
|
FROM python:3.8-buster as symposion_base
|
||||||
|
|
||||||
RUN set -ex \
|
RUN set -ex \
|
||||||
&& apt-get update
|
&& apt-get update
|
||||||
|
@ -25,6 +25,7 @@ RUN set -ex \
|
||||||
COPY constraints.txt requirements.txt /reqs/
|
COPY constraints.txt requirements.txt /reqs/
|
||||||
|
|
||||||
RUN set -ex \
|
RUN set -ex \
|
||||||
|
&& pip install -U pip \
|
||||||
&& pip install --no-cache-dir -r /reqs/requirements.txt -c /reqs/constraints.txt \
|
&& pip install --no-cache-dir -r /reqs/requirements.txt -c /reqs/constraints.txt \
|
||||||
&& apt-get purge -y --auto-remove $buildDeps \
|
&& apt-get purge -y --auto-remove $buildDeps \
|
||||||
&& rm -rf /usr/src/python ~/.cache
|
&& rm -rf /usr/src/python ~/.cache
|
||||||
|
|
|
@ -8,3 +8,5 @@ LOGIN_URL='/accounts/login'
|
||||||
ROOT_URLCONF = "pinaxcon.devmode_urls"
|
ROOT_URLCONF = "pinaxcon.devmode_urls"
|
||||||
|
|
||||||
DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage'
|
DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage'
|
||||||
|
|
||||||
|
INTERNAL_IPS = ['*']
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
from django.conf.urls import include, url
|
from django.contrib.auth.views import LoginView, LogoutView
|
||||||
from django.contrib.auth.views import login, logout
|
from django.urls import include, path
|
||||||
|
|
||||||
from pinaxcon import urls
|
from pinaxcon import urls
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^accounts/logout', logout, {'template_name': 'admin/logout.html'}),
|
path('accounts/logout', LogoutView.as_view(template_name='admin/logout.html')),
|
||||||
url(r'^accounts/login', login, {'template_name': 'admin/login.html'}),
|
path('accounts/login', LoginView.as_view(template_name='admin/login.html')),
|
||||||
]
|
]
|
||||||
|
|
||||||
urlpatterns += urls.urlpatterns
|
urlpatterns += urls.urlpatterns
|
||||||
|
|
|
@ -4,8 +4,13 @@ from functools import wraps
|
||||||
class MonkeyPatchMiddleware(object):
|
class MonkeyPatchMiddleware(object):
|
||||||
''' Ensures that our monkey patching only gets called after it is safe to do so.'''
|
''' Ensures that our monkey patching only gets called after it is safe to do so.'''
|
||||||
|
|
||||||
def process_request(self, request):
|
def __init__(self, get_response):
|
||||||
|
self.get_response = get_response
|
||||||
|
|
||||||
|
def __call__(self, request):
|
||||||
do_monkey_patch()
|
do_monkey_patch()
|
||||||
|
response = self.get_response(request)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
def do_monkey_patch():
|
def do_monkey_patch():
|
||||||
|
@ -53,7 +58,7 @@ def patch_stripe_payment_form(): # noqa: C901
|
||||||
if not isinstance(value, HttpRequest):
|
if not isinstance(value, HttpRequest):
|
||||||
continue
|
continue
|
||||||
user = value.user
|
user = value.user
|
||||||
if not user.is_authenticated():
|
if not user.is_authenticated:
|
||||||
break
|
break
|
||||||
try:
|
try:
|
||||||
attendee_profile = models.AttendeeProfile.objects.get(
|
attendee_profile = models.AttendeeProfile.objects.get(
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from django.conf import settings
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from pinaxcon.raffle.mixins import PrizeMixin, RaffleMixin
|
from pinaxcon.raffle.mixins import PrizeMixin, RaffleMixin
|
||||||
|
@ -26,11 +27,18 @@ class Prize(PrizeMixin, models.Model):
|
||||||
unlocked.
|
unlocked.
|
||||||
"""
|
"""
|
||||||
description = models.CharField(max_length=255)
|
description = models.CharField(max_length=255)
|
||||||
raffle = models.ForeignKey('pinaxcon_raffle.Raffle', related_name='prizes')
|
raffle = models.ForeignKey(
|
||||||
|
'pinaxcon_raffle.Raffle',
|
||||||
|
related_name='prizes',
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
order = models.PositiveIntegerField()
|
order = models.PositiveIntegerField()
|
||||||
winning_ticket = models.OneToOneField(
|
winning_ticket = models.OneToOneField(
|
||||||
'pinaxcon_raffle.DrawnTicket', null=True,
|
'pinaxcon_raffle.DrawnTicket',
|
||||||
blank=True, related_name='+', on_delete=models.PROTECT
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
related_name='+',
|
||||||
|
on_delete=models.PROTECT,
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -45,9 +53,16 @@ class PrizeAudit(models.Model):
|
||||||
Stores an audit event for changes to a particular :model:`pinaxcon_raffle.Prize`.
|
Stores an audit event for changes to a particular :model:`pinaxcon_raffle.Prize`.
|
||||||
"""
|
"""
|
||||||
reason = models.CharField(max_length=255)
|
reason = models.CharField(max_length=255)
|
||||||
prize = models.ForeignKey('pinaxcon_raffle.Prize', related_name='audit_events')
|
prize = models.ForeignKey(
|
||||||
|
'pinaxcon_raffle.Prize',
|
||||||
|
related_name='audit_events',
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
|
||||||
user = models.ForeignKey('auth.User')
|
user = models.ForeignKey(
|
||||||
|
settings.AUTH_USER_MODEL,
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
timestamp = models.DateTimeField(auto_now_add=True)
|
timestamp = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -62,8 +77,15 @@ class Draw(models.Model):
|
||||||
Stores a draw for a given :model:`pinaxcon_raffle.Raffle`, along with audit fields
|
Stores a draw for a given :model:`pinaxcon_raffle.Raffle`, along with audit fields
|
||||||
for the creating :model:`auth.User` and the creation timestamp.
|
for the creating :model:`auth.User` and the creation timestamp.
|
||||||
"""
|
"""
|
||||||
raffle = models.ForeignKey('pinaxcon_raffle.Raffle', related_name='draws')
|
raffle = models.ForeignKey(
|
||||||
drawn_by = models.ForeignKey('auth.User')
|
'pinaxcon_raffle.Raffle',
|
||||||
|
related_name='draws',
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
drawn_by = models.ForeignKey(
|
||||||
|
settings.AUTH_USER_MODEL,
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
drawn_time = models.DateTimeField(auto_now_add=True)
|
drawn_time = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -78,9 +100,18 @@ class DrawnTicket(models.Model):
|
||||||
"""
|
"""
|
||||||
ticket = models.CharField(max_length=255)
|
ticket = models.CharField(max_length=255)
|
||||||
|
|
||||||
draw = models.ForeignKey('pinaxcon_raffle.Draw')
|
draw = models.ForeignKey(
|
||||||
prize = models.ForeignKey('pinaxcon_raffle.Prize')
|
'pinaxcon_raffle.Draw',
|
||||||
lineitem = models.ForeignKey('registrasion.LineItem')
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
prize = models.ForeignKey(
|
||||||
|
'pinaxcon_raffle.Prize',
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
lineitem = models.ForeignKey(
|
||||||
|
'registrasion.LineItem',
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.ticket}: {self.draw.raffle}"
|
return f"{self.ticket}: {self.draw.raffle}"
|
|
@ -1,4 +1,4 @@
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth import get_user_model
|
||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
from symposion.conference.models import Section, current_conference
|
from symposion.conference.models import Section, current_conference
|
||||||
|
@ -8,6 +8,8 @@ from symposion.schedule.models import Presentation
|
||||||
from symposion.proposals.models import ProposalKind
|
from symposion.proposals.models import ProposalKind
|
||||||
from pinaxcon.proposals.models import TalkProposal
|
from pinaxcon.proposals.models import TalkProposal
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import saml2
|
||||||
import saml2.saml
|
import saml2.saml
|
||||||
|
|
||||||
from datetime import date, datetime, timedelta
|
from datetime import date, datetime, timedelta
|
||||||
|
import pytz
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
@ -124,7 +125,7 @@ else:
|
||||||
|
|
||||||
ALLOWED_HOSTS = ['127.0.0.1', 'localhost', '*']
|
ALLOWED_HOSTS = ['127.0.0.1', 'localhost', '*']
|
||||||
|
|
||||||
TIME_ZONE = "Australia/Brisbane"
|
TIME_ZONE = "Australia/Melbourne"
|
||||||
DATE_FORMAT = "j F Y"
|
DATE_FORMAT = "j F Y"
|
||||||
LANGUAGE_CODE = "en-au"
|
LANGUAGE_CODE = "en-au"
|
||||||
|
|
||||||
|
@ -176,12 +177,12 @@ TEMPLATES = [
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE_CLASSES = [
|
MIDDLEWARE = [
|
||||||
|
"whitenoise.middleware.WhiteNoiseMiddleware",
|
||||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||||
"django.middleware.common.CommonMiddleware",
|
"django.middleware.common.CommonMiddleware",
|
||||||
"django.middleware.csrf.CsrfViewMiddleware",
|
"django.middleware.csrf.CsrfViewMiddleware",
|
||||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||||
"django.contrib.auth.middleware.SessionAuthenticationMiddleware",
|
|
||||||
"django.contrib.messages.middleware.MessageMiddleware",
|
"django.contrib.messages.middleware.MessageMiddleware",
|
||||||
"debug_toolbar.middleware.DebugToolbarMiddleware",
|
"debug_toolbar.middleware.DebugToolbarMiddleware",
|
||||||
"reversion.middleware.RevisionMiddleware",
|
"reversion.middleware.RevisionMiddleware",
|
||||||
|
@ -200,6 +201,7 @@ else:
|
||||||
WSGI_APPLICATION = "pinaxcon.wsgi.application"
|
WSGI_APPLICATION = "pinaxcon.wsgi.application"
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
|
"whitenoise.runserver_nostatic",
|
||||||
"django.contrib.admin",
|
"django.contrib.admin",
|
||||||
"django.contrib.auth",
|
"django.contrib.auth",
|
||||||
"django.contrib.contenttypes",
|
"django.contrib.contenttypes",
|
||||||
|
@ -224,6 +226,7 @@ INSTALLED_APPS = [
|
||||||
"taggit",
|
"taggit",
|
||||||
"reversion",
|
"reversion",
|
||||||
"sitetree",
|
"sitetree",
|
||||||
|
"django_jsonfield_backport",
|
||||||
"pinax.eventlog",
|
"pinax.eventlog",
|
||||||
|
|
||||||
# symposion
|
# symposion
|
||||||
|
@ -283,9 +286,12 @@ DEBUG_TOOLBAR_PANELS = [
|
||||||
|
|
||||||
DEBUG_TOOLBAR_CONFIG = {
|
DEBUG_TOOLBAR_CONFIG = {
|
||||||
'INTERCEPT_REDIRECTS': False,
|
'INTERCEPT_REDIRECTS': False,
|
||||||
'SHOW_TOOLBAR_CALLBACK': lambda x: DEBUG,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INTERNAL_IPS = [
|
||||||
|
'127.0.0.1',
|
||||||
|
]
|
||||||
|
|
||||||
from debug_toolbar.panels.logging import collector
|
from debug_toolbar.panels.logging import collector
|
||||||
LOGGING = {
|
LOGGING = {
|
||||||
'version': 1,
|
'version': 1,
|
||||||
|
@ -502,9 +508,10 @@ class PenguinDinnerCat(Category):
|
||||||
return t
|
return t
|
||||||
|
|
||||||
|
|
||||||
LCA_START = datetime(2021, 1, 23)
|
_TZINFO = pytz.timezone(TIME_ZONE)
|
||||||
LCA_END = datetime(2021, 1, 25)
|
LCA_START = datetime(2021, 1, 23, tzinfo=_TZINFO)
|
||||||
EARLY_BIRD_DEADLINE = datetime(2020, 12, 1)
|
LCA_END = datetime(2021, 1, 25, tzinfo=_TZINFO)
|
||||||
|
EARLY_BIRD_DEADLINE = datetime(2020, 12, 1, tzinfo=_TZINFO)
|
||||||
PENGUIN_DINNER_TICKET_DATE = date(2021, 1, 23)
|
PENGUIN_DINNER_TICKET_DATE = date(2021, 1, 23)
|
||||||
SPEAKER_DINNER_TICKET_DATE = date(2021, 1, 25)
|
SPEAKER_DINNER_TICKET_DATE = date(2021, 1, 25)
|
||||||
PDNS_TICKET_DATE = date(2021, 1, 24)
|
PDNS_TICKET_DATE = date(2021, 1, 24)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{% extends "site_base.html" %}
|
{% extends "site_base.html" %}
|
||||||
{% load staticfiles %}
|
{% load static %}
|
||||||
|
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{% extends "site_base.html" %}
|
{% extends "site_base.html" %}
|
||||||
{% load staticfiles %}
|
{% load static %}
|
||||||
|
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
{% extends "site_base.html" %}
|
{% extends "site_base.html" %}
|
||||||
{% load staticfiles %}
|
{% load static %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% load review_tags %}
|
{% load review_tags %}
|
||||||
{% load teams_tags %}
|
{% load teams_tags %}
|
||||||
{% load registrasion_tags %}
|
{% load registrasion_tags %}
|
||||||
{% load lca2018_tags %}
|
{% load lca2018_tags %}
|
||||||
{% load staticfiles %}
|
|
||||||
|
|
||||||
|
|
||||||
{% block head_title %}Dashboard{% endblock %}
|
{% block head_title %}Dashboard{% endblock %}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{% extends "site_base.html" %}
|
{% extends "site_base.html" %}
|
||||||
{% load registrasion_tags %}
|
{% load registrasion_tags %}
|
||||||
{% load lca2018_tags %}
|
{% load lca2018_tags %}
|
||||||
{% load staticfiles %}
|
{% load static %}
|
||||||
|
|
||||||
{% block head_title %}Raffle Tickets{% endblock %}
|
{% block head_title %}Raffle Tickets{% endblock %}
|
||||||
{% block page_title %}Raffle Tickets{% endblock %}
|
{% block page_title %}Raffle Tickets{% endblock %}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{% extends "site_base.html" %}
|
{% extends "site_base.html" %}
|
||||||
{% load registrasion_tags %}
|
{% load registrasion_tags %}
|
||||||
{% load lca2018_tags %}
|
{% load lca2018_tags %}
|
||||||
{% load staticfiles %}
|
{% load static %}
|
||||||
|
|
||||||
{% block head_title %}Raffle Winners{% endblock %}
|
{% block head_title %}Raffle Winners{% endblock %}
|
||||||
{% block page_title %}Raffle Winners{% endblock %}
|
{% block page_title %}Raffle Winners{% endblock %}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{% extends "site_base.html" %}
|
{% extends "site_base.html" %}
|
||||||
{% load staticfiles %}
|
{% load static %}
|
||||||
{% load lca2018_tags %}
|
{% load lca2018_tags %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{% extends "registrasion/base.html" %}
|
{% extends "registrasion/base.html" %}
|
||||||
{% load registrasion_tags %}
|
{% load registrasion_tags %}
|
||||||
{% load lca2018_tags %}
|
{% load lca2018_tags %}
|
||||||
{% load staticfiles %}
|
{% load static %}
|
||||||
|
|
||||||
{% block head_title %}Tax Invoice/Statement #{{ invoice.id }}{% endblock %}
|
{% block head_title %}Tax Invoice/Statement #{{ invoice.id }}{% endblock %}
|
||||||
{% block page_title %}{% conference_name %}{% endblock %}
|
{% block page_title %}{% conference_name %}{% endblock %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% load staticfiles %}
|
{% load static %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load sitetree %}
|
{% load sitetree %}
|
||||||
{% load sass_tags %}
|
{% load sass_tags %}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
{% load registrasion_tags %}
|
{% load registrasion_tags %}
|
||||||
{% load lca2018_tags %}
|
{% load lca2018_tags %}
|
||||||
{% load lca2019_tags %}
|
{% load lca2019_tags %}
|
||||||
{% load staticfiles %}
|
{% load static %}
|
||||||
{% load waffle_tags %}
|
{% load waffle_tags %}
|
||||||
|
|
||||||
{% if user.is_staff %}
|
{% if user.is_staff %}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{% extends "site_base.html" %}
|
{% extends "site_base.html" %}
|
||||||
{% load staticfiles %}
|
{% load static %}
|
||||||
|
|
||||||
|
|
||||||
{% block body_outer %}
|
{% block body_outer %}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{% extends "site_base.html" %}
|
{% extends "site_base.html" %}
|
||||||
{% load staticfiles %}
|
{% load static %}
|
||||||
|
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
|
|
|
@ -13,9 +13,11 @@
|
||||||
{% if reviewed == 'all_reviews' %}
|
{% if reviewed == 'all_reviews' %}
|
||||||
<h4>All proposals</h4>
|
<h4>All proposals</h4>
|
||||||
{% elif reviewed == 'user_reviewed' %}
|
{% elif reviewed == 'user_reviewed' %}
|
||||||
<h4>Proposals you have reviewed</h4>
|
<h4>Proposals you have reviewed</h4>
|
||||||
|
{% elif reviewed == 'user_not_reviewed' %}
|
||||||
|
<h4>Proposals you have not reviewed</h4>
|
||||||
{% else %}
|
{% else %}
|
||||||
<h4>Proposals you have not yet reviewed</h4>
|
<h4>Proposals reviewed by selected reviewer</h4>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% include "symposion/reviews/_review_table.html" %}
|
{% include "symposion/reviews/_review_table.html" %}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{% extends "site_base.html" %}
|
{% extends "site_base.html" %}
|
||||||
{% load staticfiles %}
|
{% load static %}
|
||||||
|
|
||||||
{% load bootstrap %}
|
{% load bootstrap %}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
{% load lca2018_tags %}
|
{% load lca2018_tags %}
|
||||||
{% load lca2019_tags %}
|
{% load lca2019_tags %}
|
||||||
{% load sitetree %}
|
{% load sitetree %}
|
||||||
{% load staticfiles %}
|
{% load static %}
|
||||||
{% load thumbnail %}
|
{% load thumbnail %}
|
||||||
|
|
||||||
{% block head_title %}Presentation: {{ presentation.title }}{% endblock %}
|
{% block head_title %}Presentation: {{ presentation.title }}{% endblock %}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
{% load lca2018_tags %}
|
{% load lca2018_tags %}
|
||||||
{% load sitetree %}
|
{% load sitetree %}
|
||||||
{% load staticfiles %}
|
{% load static %}
|
||||||
{% load thumbnail %}
|
{% load thumbnail %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
{% load lca2018_tags %}
|
{% load lca2018_tags %}
|
||||||
{% load sitetree %}
|
{% load sitetree %}
|
||||||
{% load staticfiles %}
|
{% load static %}
|
||||||
{% load thumbnail %}
|
{% load thumbnail %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ GST_RATE = settings.GST_RATE
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
@register.assignment_tag()
|
@register.simple_tag()
|
||||||
def classname(ob):
|
def classname(ob):
|
||||||
return ob.__class__.__name__
|
return ob.__class__.__name__
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
import debug_toolbar
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.conf.urls import include, url
|
|
||||||
from django.conf.urls.static import static
|
from django.conf.urls.static import static
|
||||||
from django.views.generic import RedirectView
|
from django.views.generic import RedirectView
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
|
from django.urls import include, path
|
||||||
from django.contrib.flatpages.views import flatpage
|
from django.contrib.flatpages.views import flatpage
|
||||||
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
@ -11,31 +12,30 @@ import symposion.views
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^saml2/', include('djangosaml2.urls')),
|
path('saml2/', include('djangosaml2.urls')),
|
||||||
url(r"^admin/", include(admin.site.urls)),
|
path('admin/', admin.site.urls),
|
||||||
|
|
||||||
url(r"^speaker/", include("symposion.speakers.urls")),
|
path("speaker/", include("symposion.speakers.urls")),
|
||||||
url(r"^proposals/", include("symposion.proposals.urls")),
|
path("proposals/", include("symposion.proposals.urls")),
|
||||||
url(r"^reviews/", include("symposion.reviews.urls")),
|
path("reviews/", include("symposion.reviews.urls")),
|
||||||
url(r"^schedule/", include("symposion.schedule.urls")),
|
path("schedule/", include("symposion.schedule.urls")),
|
||||||
url(r"^conference/", include("symposion.conference.urls")),
|
path("conference/", include("symposion.conference.urls")),
|
||||||
|
|
||||||
url(r"^teams/", include("symposion.teams.urls")),
|
path("teams/", include("symposion.teams.urls")),
|
||||||
url(r'^raffle/', include("pinaxcon.raffle.urls")),
|
path('raffle/', include("pinaxcon.raffle.urls")),
|
||||||
|
|
||||||
# Required by registrasion
|
# Required by registrasion
|
||||||
url(r'^tickets/payments/', include('registripe.urls')),
|
path('tickets/payments/', include('registripe.urls')),
|
||||||
url(r'^tickets/', include('registrasion.urls')),
|
path('tickets/', include('registrasion.urls')),
|
||||||
url(r'^nested_admin/', include('nested_admin.urls')),
|
path('nested_admin/', include('nested_admin.urls')),
|
||||||
url(r'^checkin/', include('regidesk.urls')),
|
path('checkin/', include('regidesk.urls')),
|
||||||
url(r'^pages/', include('django.contrib.flatpages.urls')),
|
path('pages/', include('django.contrib.flatpages.urls')),
|
||||||
|
|
||||||
url(r'^dashboard/', symposion.views.dashboard, name="dashboard"),
|
path('dashboard/', symposion.views.dashboard, name="dashboard"),
|
||||||
url(r'^boardingpass', RedirectView.as_view(pattern_name="regidesk:boardingpass")),
|
path('boardingpass', RedirectView.as_view(pattern_name="regidesk:boardingpass")),
|
||||||
|
|
||||||
|
# Debug Toolbar. Always include to ensure tests work.
|
||||||
|
path('__debug__/', include(debug_toolbar.urls)),
|
||||||
]
|
]
|
||||||
|
|
||||||
if settings.DEBUG:
|
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||||
import debug_toolbar
|
|
||||||
urlpatterns.insert(0, url(r'^__debug__/', include(debug_toolbar.urls)))
|
|
||||||
|
|
||||||
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)#
|
|
||||||
|
|
|
@ -5,6 +5,4 @@ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pinaxcon.settings")
|
||||||
|
|
||||||
from django.core.wsgi import get_wsgi_application # noqa
|
from django.core.wsgi import get_wsgi_application # noqa
|
||||||
|
|
||||||
from dj_static import Cling, MediaCling # noqa
|
application = get_wsgi_application()
|
||||||
|
|
||||||
application = Cling(MediaCling(get_wsgi_application()))
|
|
||||||
|
|
135
requirements.txt
135
requirements.txt
|
@ -1,86 +1,51 @@
|
||||||
asn1crypto==0.24.0
|
Django>=2.2
|
||||||
bleach==2.1.3
|
pinax-theme-bootstrap==8.0.1
|
||||||
cachetools==2.1.0
|
pinax-eventlog[django-lts]==5.1.0
|
||||||
cairocffi==0.8.1
|
|
||||||
CairoSVG==2.1.2
|
|
||||||
certifi==2018.4.16
|
|
||||||
cffi==1.11.5
|
|
||||||
chardet==3.0.4
|
|
||||||
coverage==4.0.3
|
|
||||||
cryptography==2.3
|
|
||||||
cssselect2==0.2.1
|
|
||||||
dataclasses==0.6
|
|
||||||
decorator==4.3.0
|
|
||||||
defusedxml==0.5.0
|
|
||||||
dj-database-url==0.4.2
|
|
||||||
dj-static==0.0.6
|
|
||||||
Django==1.11.25
|
|
||||||
django-appconf==1.0.1
|
|
||||||
django-bootstrap-form==3.4
|
|
||||||
django-capture-tag==1.0
|
|
||||||
django-compressor==2.3
|
|
||||||
django-countries==5.3.1
|
|
||||||
django-crispy-forms==1.7.2
|
|
||||||
django-debug-toolbar==1.9.1
|
|
||||||
django-formset-js==0.5.0
|
django-formset-js==0.5.0
|
||||||
django-gapc-storage==0.5.1
|
whitenoise==5.2.0
|
||||||
django-ical==1.4
|
dj-database-url==0.5.0
|
||||||
django-jquery-js==3.1.1
|
pylibmc==1.6.1
|
||||||
django-model-utils==3.1.2
|
django-debug-toolbar==3.1.1
|
||||||
django-nested-admin==2.2.6
|
django-bootstrap-form==3.4
|
||||||
django-nose==1.4.5
|
django-settings-export~=1.2.1
|
||||||
django-reversion==1.10.1
|
django-capture-tag==1.0
|
||||||
django-sass-processor==0.7.3
|
djangosaml2==0.50.0
|
||||||
django-settings-export==1.2.1
|
django-gapc-storage==0.5.2
|
||||||
django-sitetree==1.10.0
|
django-waffle==2.0.0
|
||||||
django-taggit==0.18.0
|
|
||||||
django-timezone-field==2.1
|
# database
|
||||||
django-waffle==0.14.0
|
mysqlclient==2.0.1
|
||||||
djangosaml2==0.17.2
|
|
||||||
easy-thumbnails==2.5
|
# For testing
|
||||||
future==0.16.0
|
django-nose==1.4.7
|
||||||
google-api-python-client==1.7.0
|
coverage==5.3
|
||||||
google-auth==1.5.1
|
factory_boy==3.1.0
|
||||||
google-auth-httplib2==0.0.3
|
|
||||||
html5lib==1.0.1
|
# Symposion reqs
|
||||||
httplib2==0.11.3
|
django-appconf==1.0.4
|
||||||
icalendar==4.0.2
|
django-model-utils==4.0.0
|
||||||
idna==2.7
|
django-reversion==3.0.8
|
||||||
jsonfield==2.0.2
|
django-sitetree==1.16.0
|
||||||
libsass==0.19.3
|
django-taggit==1.3.0
|
||||||
lxml==4.0.0
|
django-timezone-field==4.0
|
||||||
mysqlclient==1.3.13
|
easy-thumbnails==2.7.0
|
||||||
nose==1.3.7
|
bleach==3.2.1
|
||||||
oauth2client==4.1.2
|
pytz>=2020.1
|
||||||
Paste==2.0.3
|
django-ical==1.7.1
|
||||||
Pillow==5.2.0
|
|
||||||
pinax-eventlog==1.1.1
|
# Registrasion reqs
|
||||||
pinax-stripe==3.2.1
|
django-nested-admin==3.3.2
|
||||||
pinax-theme-bootstrap==7.10.2
|
CairoSVG==2.4.2
|
||||||
pyasn1==0.4.4
|
|
||||||
pyasn1-modules==0.2.2
|
# Registripe
|
||||||
pycparser==2.18
|
django-countries>=6.1.3
|
||||||
pycryptodomex==3.6.4
|
pinax-stripe==4.4.0
|
||||||
pylibmc==1.5.1
|
requests==2.24.0
|
||||||
pyOpenSSL==18.0.0
|
stripe==2.55.0
|
||||||
pypng==0.0.18
|
|
||||||
PyQRCode==1.2.1
|
# SASS Compiler and template tags
|
||||||
pysaml2==4.8.0
|
libsass==0.20.1
|
||||||
python-dateutil==2.7.3
|
django-sass-processor==0.8.2
|
||||||
pytz==2018.4
|
django-compressor==2.4
|
||||||
rcssmin==1.0.6
|
|
||||||
repoze.who==2.3
|
django-crispy-forms==1.9.2
|
||||||
requests==2.19.1
|
|
||||||
rjsmin==1.1.0
|
|
||||||
rsa==3.4.2
|
|
||||||
six==1.11.0
|
|
||||||
sqlparse==0.2.4
|
|
||||||
static3==0.7.0
|
|
||||||
stripe==1.38.0
|
|
||||||
tinycss2==0.6.1
|
|
||||||
uritemplate==3.0.0
|
|
||||||
urllib3==1.23
|
|
||||||
uWSGI==2.0.17.1
|
|
||||||
webencodings==0.5.1
|
|
||||||
WebOb==1.8.2
|
|
||||||
zope.interface==4.5.0
|
|
||||||
|
|
4
vendor/regidesk/regidesk/forms.py
vendored
4
vendor/regidesk/regidesk/forms.py
vendored
|
@ -1,15 +1,13 @@
|
||||||
import copy
|
import copy
|
||||||
from regidesk import models
|
from regidesk import models
|
||||||
|
|
||||||
from django import forms
|
|
||||||
from django.core.urlresolvers import reverse
|
|
||||||
import functools
|
import functools
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.core.urlresolvers import reverse
|
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db.models import F, Q
|
from django.db.models import F, Q
|
||||||
from django.forms import widgets
|
from django.forms import widgets
|
||||||
|
from django.urls import reverse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from django_countries import countries
|
from django_countries import countries
|
||||||
|
|
|
@ -2,10 +2,13 @@
|
||||||
|
|
||||||
from django.core.management.base import BaseCommand, CommandError
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
|
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth import get_user_model
|
||||||
from registrasion.views import _convert_img as convert_img
|
from registrasion.views import _convert_img as convert_img
|
||||||
from registrasion.views import render_badge_svg
|
from registrasion.views import render_badge_svg
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
|
|
6
vendor/regidesk/regidesk/models.py
vendored
6
vendor/regidesk/regidesk/models.py
vendored
|
@ -12,7 +12,7 @@ from django.db.models import Q, F
|
||||||
from django.db.models import Case, When, Value
|
from django.db.models import Case, When, Value
|
||||||
from django.db.models import Count
|
from django.db.models import Count
|
||||||
from django.db.models.signals import post_save
|
from django.db.models.signals import post_save
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth import get_user_model
|
||||||
import pyqrcode
|
import pyqrcode
|
||||||
|
|
||||||
from symposion import constants
|
from symposion import constants
|
||||||
|
@ -20,6 +20,8 @@ from symposion.text_parser import parse
|
||||||
from registrasion.models import commerce
|
from registrasion.models import commerce
|
||||||
from registrasion.util import generate_access_code as generate_code
|
from registrasion.util import generate_access_code as generate_code
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
class BoardingPassTemplate(models.Model):
|
class BoardingPassTemplate(models.Model):
|
||||||
|
|
||||||
|
@ -60,7 +62,7 @@ class BoardingPass(models.Model):
|
||||||
|
|
||||||
class CheckIn(models.Model):
|
class CheckIn(models.Model):
|
||||||
|
|
||||||
user = models.OneToOneField(User)
|
user = models.OneToOneField(User, on_delete=models.CASCADE)
|
||||||
boardingpass = models.OneToOneField(BoardingPass, null=True,
|
boardingpass = models.OneToOneField(BoardingPass, null=True,
|
||||||
blank=True, on_delete=models.SET_NULL)
|
blank=True, on_delete=models.SET_NULL)
|
||||||
seen = models.DateTimeField(null=True,blank=True)
|
seen = models.DateTimeField(null=True,blank=True)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{% extends "site_base.html" %}
|
{% extends "site_base.html" %}
|
||||||
{% load staticfiles %}
|
{% load static %}
|
||||||
|
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
|
|
7
vendor/regidesk/regidesk/views.py
vendored
7
vendor/regidesk/regidesk/views.py
vendored
|
@ -9,7 +9,8 @@ from django.conf import settings
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.decorators import permission_required, user_passes_test, login_required
|
from django.contrib.auth.decorators import permission_required, user_passes_test, login_required
|
||||||
from django.contrib.auth.mixins import PermissionRequiredMixin
|
from django.contrib.auth.mixins import PermissionRequiredMixin
|
||||||
from django.contrib.auth.models import User, Group
|
from django.contrib.auth.models import Group
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.db.models import F, Q
|
from django.db.models import F, Q
|
||||||
|
@ -32,10 +33,10 @@ from symposion.conference.models import Conference
|
||||||
from regidesk import forms
|
from regidesk import forms
|
||||||
from regidesk.models import BoardingPass, BoardingPassTemplate, CheckIn
|
from regidesk.models import BoardingPass, BoardingPassTemplate, CheckIn
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
AttendeeProfile = util.get_object_from_name(settings.ATTENDEE_PROFILE_MODEL)
|
AttendeeProfile = util.get_object_from_name(settings.ATTENDEE_PROFILE_MODEL)
|
||||||
|
|
||||||
|
|
||||||
def _staff_only(user):
|
def _staff_only(user):
|
||||||
''' Returns true if the user is staff. '''
|
''' Returns true if the user is staff. '''
|
||||||
return user.is_staff
|
return user.is_staff
|
||||||
|
|
4
vendor/regidesk/requirements.txt
vendored
4
vendor/regidesk/requirements.txt
vendored
|
@ -1,4 +1,4 @@
|
||||||
django-countries>=4.0
|
django-countries>=6.1.3
|
||||||
requests>=2.11.1
|
requests>=2.24.0
|
||||||
pypng
|
pypng
|
||||||
pyqrcode
|
pyqrcode
|
||||||
|
|
10
vendor/registrasion/registrasion/admin.py
vendored
10
vendor/registrasion/registrasion/admin.py
vendored
|
@ -44,12 +44,14 @@ class DiscountForProductInline(admin.TabularInline):
|
||||||
model = conditions.DiscountForProduct
|
model = conditions.DiscountForProduct
|
||||||
verbose_name = _("Product included in discount")
|
verbose_name = _("Product included in discount")
|
||||||
verbose_name_plural = _("Products included in discount")
|
verbose_name_plural = _("Products included in discount")
|
||||||
|
sortable_options = []
|
||||||
|
|
||||||
|
|
||||||
class DiscountForCategoryInline(admin.TabularInline):
|
class DiscountForCategoryInline(admin.TabularInline):
|
||||||
model = conditions.DiscountForCategory
|
model = conditions.DiscountForCategory
|
||||||
verbose_name = _("Category included in discount")
|
verbose_name = _("Category included in discount")
|
||||||
verbose_name_plural = _("Categories included in discount")
|
verbose_name_plural = _("Categories included in discount")
|
||||||
|
sortable_options = []
|
||||||
|
|
||||||
|
|
||||||
@admin.register(conditions.TimeOrStockLimitDiscount)
|
@admin.register(conditions.TimeOrStockLimitDiscount)
|
||||||
|
@ -137,7 +139,7 @@ class VoucherFlagInline(nested_admin.NestedStackedInline):
|
||||||
|
|
||||||
|
|
||||||
@admin.register(inventory.Voucher)
|
@admin.register(inventory.Voucher)
|
||||||
class VoucherAdmin(nested_admin.NestedAdmin):
|
class VoucherAdmin(nested_admin.NestedModelAdmin):
|
||||||
|
|
||||||
def effects(self, obj):
|
def effects(self, obj):
|
||||||
''' List the effects of the voucher in the admin. '''
|
''' List the effects of the voucher in the admin. '''
|
||||||
|
@ -178,7 +180,7 @@ class VoucherAdmin(nested_admin.NestedAdmin):
|
||||||
# Enabling conditions
|
# Enabling conditions
|
||||||
@admin.register(conditions.ProductFlag)
|
@admin.register(conditions.ProductFlag)
|
||||||
class ProductFlagAdmin(
|
class ProductFlagAdmin(
|
||||||
nested_admin.NestedAdmin,
|
nested_admin.NestedModelAdmin,
|
||||||
EffectsDisplayMixin):
|
EffectsDisplayMixin):
|
||||||
|
|
||||||
def enablers(self, obj):
|
def enablers(self, obj):
|
||||||
|
@ -194,7 +196,7 @@ class ProductFlagAdmin(
|
||||||
# Enabling conditions
|
# Enabling conditions
|
||||||
@admin.register(conditions.CategoryFlag)
|
@admin.register(conditions.CategoryFlag)
|
||||||
class CategoryFlagAdmin(
|
class CategoryFlagAdmin(
|
||||||
nested_admin.NestedAdmin,
|
nested_admin.NestedModelAdmin,
|
||||||
EffectsDisplayMixin):
|
EffectsDisplayMixin):
|
||||||
|
|
||||||
model = conditions.CategoryFlag
|
model = conditions.CategoryFlag
|
||||||
|
@ -206,7 +208,7 @@ class CategoryFlagAdmin(
|
||||||
|
|
||||||
|
|
||||||
@admin.register(conditions.SpeakerFlag)
|
@admin.register(conditions.SpeakerFlag)
|
||||||
class SpeakerFlagAdmin(nested_admin.NestedAdmin, EffectsDisplayMixin):
|
class SpeakerFlagAdmin(nested_admin.NestedModelAdmin, EffectsDisplayMixin):
|
||||||
|
|
||||||
model = conditions.SpeakerFlag
|
model = conditions.SpeakerFlag
|
||||||
fields = ("description", "is_presenter", "is_copresenter", "proposal_kind",
|
fields = ("description", "is_presenter", "is_copresenter", "proposal_kind",
|
||||||
|
|
|
@ -24,7 +24,8 @@ import pdb
|
||||||
|
|
||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
from django.contrib.auth.models import User, Group
|
from django.contrib.auth.models import Group
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
from django.db.utils import OperationalError, ProgrammingError
|
from django.db.utils import OperationalError, ProgrammingError
|
||||||
from pinaxcon.registrasion.models import AttendeeProfile
|
from pinaxcon.registrasion.models import AttendeeProfile
|
||||||
from registrasion.controllers.cart import CartController
|
from registrasion.controllers.cart import CartController
|
||||||
|
@ -35,6 +36,8 @@ from registrasion.models import Product
|
||||||
from registrasion.models import Invoice
|
from registrasion.models import Invoice
|
||||||
from symposion.speakers.models import Speaker
|
from symposion.speakers.models import Speaker
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
# A few unicode encodings ...
|
# A few unicode encodings ...
|
||||||
GLYPH_PLUS = '+'
|
GLYPH_PLUS = '+'
|
||||||
GLYPH_GLASS = u'\ue001'
|
GLYPH_GLASS = u'\ue001'
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import contextlib
|
import contextlib
|
||||||
import functools
|
import functools
|
||||||
|
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth import get_user_model
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
class BatchController(object):
|
class BatchController(object):
|
||||||
|
|
|
@ -6,7 +6,7 @@ from functools import reduce
|
||||||
from registrasion.models import commerce
|
from registrasion.models import commerce
|
||||||
from registrasion.models import inventory
|
from registrasion.models import inventory
|
||||||
|
|
||||||
from collections import Iterable
|
from collections.abc import Iterable
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from django.db.models import Case
|
from django.db.models import Case
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from . import conditions
|
from . import conditions
|
||||||
from . import inventory
|
from . import inventory
|
||||||
|
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth import get_user_model
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import F, Q, Sum
|
from django.db.models import F, Q, Sum
|
||||||
|
@ -10,6 +10,8 @@ from django.utils.encoding import python_2_unicode_compatible
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from model_utils.managers import InheritanceManager
|
from model_utils.managers import InheritanceManager
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
# Commerce Models
|
# Commerce Models
|
||||||
|
|
||||||
|
@ -38,7 +40,7 @@ class Cart(models.Model):
|
||||||
(STATUS_RELEASED, _("Released")),
|
(STATUS_RELEASED, _("Released")),
|
||||||
]
|
]
|
||||||
|
|
||||||
user = models.ForeignKey(User)
|
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||||
# ProductItems (foreign key)
|
# ProductItems (foreign key)
|
||||||
vouchers = models.ManyToManyField(inventory.Voucher, blank=True)
|
vouchers = models.ManyToManyField(inventory.Voucher, blank=True)
|
||||||
time_last_updated = models.DateTimeField(
|
time_last_updated = models.DateTimeField(
|
||||||
|
@ -76,8 +78,8 @@ class ProductItem(models.Model):
|
||||||
return "product: %s * %d in Cart: %s" % (
|
return "product: %s * %d in Cart: %s" % (
|
||||||
self.product, self.quantity, self.cart)
|
self.product, self.quantity, self.cart)
|
||||||
|
|
||||||
cart = models.ForeignKey(Cart)
|
cart = models.ForeignKey(Cart, on_delete=models.CASCADE)
|
||||||
product = models.ForeignKey(inventory.Product)
|
product = models.ForeignKey(inventory.Product, on_delete=models.CASCADE)
|
||||||
quantity = models.PositiveIntegerField(db_index=True)
|
quantity = models.PositiveIntegerField(db_index=True)
|
||||||
|
|
||||||
|
|
||||||
|
@ -93,9 +95,10 @@ class DiscountItem(models.Model):
|
||||||
return "%s: %s * %d in Cart: %s" % (
|
return "%s: %s * %d in Cart: %s" % (
|
||||||
self.discount, self.product, self.quantity, self.cart)
|
self.discount, self.product, self.quantity, self.cart)
|
||||||
|
|
||||||
cart = models.ForeignKey(Cart)
|
cart = models.ForeignKey(Cart, on_delete=models.CASCADE)
|
||||||
product = models.ForeignKey(inventory.Product)
|
product = models.ForeignKey(inventory.Product, on_delete=models.CASCADE)
|
||||||
discount = models.ForeignKey(conditions.DiscountBase)
|
discount = models.ForeignKey(conditions.DiscountBase,
|
||||||
|
on_delete=models.CASCADE)
|
||||||
quantity = models.PositiveIntegerField()
|
quantity = models.PositiveIntegerField()
|
||||||
|
|
||||||
|
|
||||||
|
@ -189,8 +192,8 @@ class Invoice(models.Model):
|
||||||
return self.value - self.total_payments()
|
return self.value - self.total_payments()
|
||||||
|
|
||||||
# Invoice Number
|
# Invoice Number
|
||||||
user = models.ForeignKey(User)
|
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||||
cart = models.ForeignKey(Cart, null=True)
|
cart = models.ForeignKey(Cart, null=True, on_delete=models.CASCADE)
|
||||||
cart_revision = models.IntegerField(
|
cart_revision = models.IntegerField(
|
||||||
null=True,
|
null=True,
|
||||||
db_index=True,
|
db_index=True,
|
||||||
|
@ -242,11 +245,12 @@ class LineItem(models.Model):
|
||||||
''' price * quantity '''
|
''' price * quantity '''
|
||||||
return self.price * self.quantity
|
return self.price * self.quantity
|
||||||
|
|
||||||
invoice = models.ForeignKey(Invoice)
|
invoice = models.ForeignKey(Invoice, on_delete=models.CASCADE)
|
||||||
description = models.CharField(max_length=255)
|
description = models.CharField(max_length=255)
|
||||||
quantity = models.PositiveIntegerField()
|
quantity = models.PositiveIntegerField()
|
||||||
price = models.DecimalField(max_digits=8, decimal_places=2)
|
price = models.DecimalField(max_digits=8, decimal_places=2)
|
||||||
product = models.ForeignKey(inventory.Product, null=True, blank=True)
|
product = models.ForeignKey(inventory.Product, null=True, blank=True,
|
||||||
|
on_delete=models.CASCADE)
|
||||||
|
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
@python_2_unicode_compatible
|
||||||
|
@ -275,7 +279,7 @@ class PaymentBase(models.Model):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "Payment: ref=%s amount=%s" % (self.reference, self.amount)
|
return "Payment: ref=%s amount=%s" % (self.reference, self.amount)
|
||||||
|
|
||||||
invoice = models.ForeignKey(Invoice)
|
invoice = models.ForeignKey(Invoice, on_delete=models.CASCADE)
|
||||||
time = models.DateTimeField(default=timezone.now)
|
time = models.DateTimeField(default=timezone.now)
|
||||||
reference = models.CharField(max_length=255)
|
reference = models.CharField(max_length=255)
|
||||||
amount = models.DecimalField(max_digits=8, decimal_places=2)
|
amount = models.DecimalField(max_digits=8, decimal_places=2)
|
||||||
|
@ -287,7 +291,7 @@ class ManualPayment(PaymentBase):
|
||||||
class Meta:
|
class Meta:
|
||||||
app_label = "registrasion"
|
app_label = "registrasion"
|
||||||
|
|
||||||
entered_by = models.ForeignKey(User)
|
entered_by = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||||
|
|
||||||
|
|
||||||
class CreditNote(PaymentBase):
|
class CreditNote(PaymentBase):
|
||||||
|
@ -364,7 +368,7 @@ class CreditNoteApplication(CleanOnSave, PaymentBase):
|
||||||
"Cannot apply a refunded credit note to an invoice"
|
"Cannot apply a refunded credit note to an invoice"
|
||||||
)
|
)
|
||||||
|
|
||||||
parent = models.OneToOneField(CreditNote)
|
parent = models.OneToOneField(CreditNote, on_delete=models.CASCADE)
|
||||||
|
|
||||||
|
|
||||||
class CreditNoteRefund(CleanOnSave, models.Model):
|
class CreditNoteRefund(CleanOnSave, models.Model):
|
||||||
|
@ -391,7 +395,7 @@ class CreditNoteRefund(CleanOnSave, models.Model):
|
||||||
"Cannot refund a credit note that has been paid to an invoice"
|
"Cannot refund a credit note that has been paid to an invoice"
|
||||||
)
|
)
|
||||||
|
|
||||||
parent = models.OneToOneField(CreditNote)
|
parent = models.OneToOneField(CreditNote, on_delete=models.CASCADE)
|
||||||
time = models.DateTimeField(default=timezone.now)
|
time = models.DateTimeField(default=timezone.now)
|
||||||
reference = models.CharField(max_length=255)
|
reference = models.CharField(max_length=255)
|
||||||
|
|
||||||
|
@ -402,4 +406,4 @@ class ManualCreditNoteRefund(CreditNoteRefund):
|
||||||
class Meta:
|
class Meta:
|
||||||
app_label = "registrasion"
|
app_label = "registrasion"
|
||||||
|
|
||||||
entered_by = models.ForeignKey(User)
|
entered_by = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||||
|
|
|
@ -10,8 +10,6 @@ from django.utils.encoding import python_2_unicode_compatible
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from model_utils.managers import InheritanceManager
|
from model_utils.managers import InheritanceManager
|
||||||
|
|
||||||
from symposion import proposals
|
|
||||||
|
|
||||||
|
|
||||||
# Condition Types
|
# Condition Types
|
||||||
|
|
||||||
|
@ -99,7 +97,7 @@ class SpeakerCondition(models.Model):
|
||||||
"presentation."),
|
"presentation."),
|
||||||
)
|
)
|
||||||
proposal_kind = models.ManyToManyField(
|
proposal_kind = models.ManyToManyField(
|
||||||
proposals.models.ProposalKind,
|
"symposion_proposals.ProposalKind",
|
||||||
help_text=_("The types of proposals that these users may be "
|
help_text=_("The types of proposals that these users may be "
|
||||||
"presenters of."),
|
"presenters of."),
|
||||||
)
|
)
|
||||||
|
@ -520,6 +518,7 @@ class CategoryFlag(FlagBase):
|
||||||
inventory.Category,
|
inventory.Category,
|
||||||
help_text=_("If a product from this category is purchased, this "
|
help_text=_("If a product from this category is purchased, this "
|
||||||
"condition is met."),
|
"condition is met."),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -156,7 +156,8 @@ class Product(models.Model):
|
||||||
)
|
)
|
||||||
category = models.ForeignKey(
|
category = models.ForeignKey(
|
||||||
Category,
|
Category,
|
||||||
verbose_name=_("Product category")
|
verbose_name=_("Product category"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
)
|
)
|
||||||
price = models.DecimalField(
|
price = models.DecimalField(
|
||||||
max_digits=8,
|
max_digits=8,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from registrasion import util
|
from registrasion import util
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth import get_user_model
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.encoding import python_2_unicode_compatible
|
from django.utils.encoding import python_2_unicode_compatible
|
||||||
|
@ -9,6 +9,9 @@ from model_utils.managers import InheritanceManager
|
||||||
|
|
||||||
from registrasion.models.commerce import Invoice, ProductItem
|
from registrasion.models.commerce import Invoice, ProductItem
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
# User models
|
# User models
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
@python_2_unicode_compatible
|
||||||
|
|
|
@ -2,8 +2,8 @@ import csv
|
||||||
|
|
||||||
from django.contrib.auth.decorators import user_passes_test
|
from django.contrib.auth.decorators import user_passes_test
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.core.urlresolvers import reverse
|
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
|
from django.urls import reverse
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
from registrasion import views
|
from registrasion import views
|
||||||
|
|
|
@ -6,8 +6,7 @@ import itertools
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.decorators import user_passes_test
|
from django.contrib.auth.decorators import user_passes_test
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth import get_user_model
|
||||||
from django.core.urlresolvers import reverse
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import F, Q, Subquery, OuterRef
|
from django.db.models import F, Q, Subquery, OuterRef
|
||||||
from django.db.models import Count, Max, Sum
|
from django.db.models import Count, Max, Sum
|
||||||
|
@ -15,6 +14,7 @@ from django.db.models import Case, When, Value
|
||||||
from django.db.models.fields.related import RelatedField
|
from django.db.models.fields.related import RelatedField
|
||||||
from django.db.models.fields import CharField
|
from django.db.models.fields import CharField
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
from registrasion.controllers.cart import CartController
|
from registrasion.controllers.cart import CartController
|
||||||
from registrasion.controllers.item import ItemController
|
from registrasion.controllers.item import ItemController
|
||||||
|
@ -39,6 +39,7 @@ def CURRENCY():
|
||||||
return models.DecimalField(decimal_places=2)
|
return models.DecimalField(decimal_places=2)
|
||||||
|
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
AttendeeProfile = util.get_object_from_name(settings.ATTENDEE_PROFILE_MODEL)
|
AttendeeProfile = util.get_object_from_name(settings.ATTENDEE_PROFILE_MODEL)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,10 +5,7 @@ from registrasion.controllers.item import ItemController
|
||||||
from django import template
|
from django import template
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db.models import Sum
|
from django.db.models import Sum
|
||||||
try:
|
from urllib.parse import urlencode
|
||||||
from urllib import urlencode
|
|
||||||
except ImportError:
|
|
||||||
from urllib.parse import urlencode
|
|
||||||
|
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
|
|
||||||
|
@ -24,7 +21,7 @@ def user_for_context(context):
|
||||||
return context.request.user
|
return context.request.user
|
||||||
|
|
||||||
|
|
||||||
@register.assignment_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
def available_categories(context):
|
def available_categories(context):
|
||||||
''' Gets all of the currently available products.
|
''' Gets all of the currently available products.
|
||||||
|
|
||||||
|
@ -36,7 +33,7 @@ def available_categories(context):
|
||||||
return CategoryController.available_categories(user_for_context(context))
|
return CategoryController.available_categories(user_for_context(context))
|
||||||
|
|
||||||
|
|
||||||
@register.assignment_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
def missing_categories(context):
|
def missing_categories(context):
|
||||||
''' Adds the categories that the user does not currently have. '''
|
''' Adds the categories that the user does not currently have. '''
|
||||||
user = user_for_context(context)
|
user = user_for_context(context)
|
||||||
|
@ -52,7 +49,7 @@ def missing_categories(context):
|
||||||
|
|
||||||
return sorted(set(i for i in missing), key=attrgetter("order"))
|
return sorted(set(i for i in missing), key=attrgetter("order"))
|
||||||
|
|
||||||
@register.assignment_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
def available_credit(context):
|
def available_credit(context):
|
||||||
''' Calculates the sum of unclaimed credit from this user's credit notes.
|
''' Calculates the sum of unclaimed credit from this user's credit notes.
|
||||||
|
|
||||||
|
@ -69,7 +66,7 @@ def available_credit(context):
|
||||||
return 0 - ret
|
return 0 - ret
|
||||||
|
|
||||||
|
|
||||||
@register.assignment_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
def invoices(context):
|
def invoices(context):
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
@ -78,7 +75,7 @@ def invoices(context):
|
||||||
return commerce.Invoice.objects.filter(user=user_for_context(context))
|
return commerce.Invoice.objects.filter(user=user_for_context(context))
|
||||||
|
|
||||||
|
|
||||||
@register.assignment_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
def items_pending(context):
|
def items_pending(context):
|
||||||
''' Gets all of the items that the user from this context has reserved.
|
''' Gets all of the items that the user from this context has reserved.
|
||||||
|
|
||||||
|
@ -89,7 +86,7 @@ def items_pending(context):
|
||||||
return ItemController(user_for_context(context)).items_pending()
|
return ItemController(user_for_context(context)).items_pending()
|
||||||
|
|
||||||
|
|
||||||
@register.assignment_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
def items_purchased(context, category=None):
|
def items_purchased(context, category=None):
|
||||||
''' Returns the items purchased for this user.
|
''' Returns the items purchased for this user.
|
||||||
|
|
||||||
|
@ -102,7 +99,7 @@ def items_purchased(context, category=None):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@register.assignment_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
def total_items_purchased(context, category=None):
|
def total_items_purchased(context, category=None):
|
||||||
''' Returns the number of items purchased for this user (sum of quantities).
|
''' Returns the number of items purchased for this user (sum of quantities).
|
||||||
|
|
||||||
|
@ -113,7 +110,7 @@ def total_items_purchased(context, category=None):
|
||||||
return sum(i.quantity for i in items_purchased(context, category))
|
return sum(i.quantity for i in items_purchased(context, category))
|
||||||
|
|
||||||
|
|
||||||
@register.assignment_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
def report_as_csv(context, section):
|
def report_as_csv(context, section):
|
||||||
|
|
||||||
old_query = context.request.META["QUERY_STRING"]
|
old_query = context.request.META["QUERY_STRING"]
|
||||||
|
@ -126,7 +123,7 @@ def report_as_csv(context, section):
|
||||||
return context.request.path + "?" + querystring
|
return context.request.path + "?" + querystring
|
||||||
|
|
||||||
|
|
||||||
@register.assignment_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
def sold_out_and_unregistered(context):
|
def sold_out_and_unregistered(context):
|
||||||
''' If the current user is unregistered, returns True if there are no
|
''' If the current user is unregistered, returns True if there are no
|
||||||
products in the TICKET_PRODUCT_CATEGORY that are available to that user.
|
products in the TICKET_PRODUCT_CATEGORY that are available to that user.
|
||||||
|
@ -186,7 +183,7 @@ def include_if_exists(parser, token):
|
||||||
try:
|
try:
|
||||||
tag_name, template_name = token.split_contents()
|
tag_name, template_name = token.split_contents()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise (template.TemplateSyntaxError,
|
raise template.TemplateSyntaxError(
|
||||||
"%r tag requires a single argument" % token.contents.split()[0])
|
"%r tag requires a single argument" % token.contents.split()[0])
|
||||||
|
|
||||||
return IncludeNode(template_name)
|
return IncludeNode(template_name)
|
||||||
|
|
|
@ -127,11 +127,11 @@ class BatchTestCase(RegistrationCartTestCase):
|
||||||
# end_batch should get called once on exiting the batch
|
# end_batch should get called once on exiting the batch
|
||||||
with BatchController.batch(self.USER_1):
|
with BatchController.batch(self.USER_1):
|
||||||
ender = get_ender(self.USER_1)
|
ender = get_ender(self.USER_1)
|
||||||
self.assertEquals(1, ender.end_count)
|
self.assertEqual(1, ender.end_count)
|
||||||
|
|
||||||
# end_batch should get called once on exiting the batch
|
# end_batch should get called once on exiting the batch
|
||||||
# no matter how deep the object gets cached
|
# no matter how deep the object gets cached
|
||||||
with BatchController.batch(self.USER_1):
|
with BatchController.batch(self.USER_1):
|
||||||
with BatchController.batch(self.USER_1):
|
with BatchController.batch(self.USER_1):
|
||||||
ender = get_ender(self.USER_1)
|
ender = get_ender(self.USER_1)
|
||||||
self.assertEquals(1, ender.end_count)
|
self.assertEqual(1, ender.end_count)
|
||||||
|
|
|
@ -2,7 +2,7 @@ import datetime
|
||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth import get_user_model
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.management import call_command
|
from django.core.management import call_command
|
||||||
|
@ -19,6 +19,7 @@ from registrasion.tests.controller_helpers import TestingCartController
|
||||||
from registrasion.tests.patches import MixInPatches
|
from registrasion.tests.patches import MixInPatches
|
||||||
|
|
||||||
UTC = pytz.timezone('UTC')
|
UTC = pytz.timezone('UTC')
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
class RegistrationCartTestCase(MixInPatches, TestCase):
|
class RegistrationCartTestCase(MixInPatches, TestCase):
|
||||||
|
@ -85,7 +86,7 @@ class RegistrationCartTestCase(MixInPatches, TestCase):
|
||||||
prod = inventory.Product.objects.create(
|
prod = inventory.Product.objects.create(
|
||||||
name="Product " + str(i + 1),
|
name="Product " + str(i + 1),
|
||||||
description="This is a test product.",
|
description="This is a test product.",
|
||||||
category=cls.categories[i / 2], # 2 products per category
|
category=cls.categories[i // 2], # 2 products per category
|
||||||
price=Decimal("10.00"),
|
price=Decimal("10.00"),
|
||||||
reservation_duration=cls.RESERVATION,
|
reservation_duration=cls.RESERVATION,
|
||||||
limit_per_user=10,
|
limit_per_user=10,
|
||||||
|
@ -192,7 +193,7 @@ class BasicCartTests(RegistrationCartTestCase):
|
||||||
product=self.PROD_1)
|
product=self.PROD_1)
|
||||||
self.assertEqual(1, len(items))
|
self.assertEqual(1, len(items))
|
||||||
item = items[0]
|
item = items[0]
|
||||||
self.assertEquals(2, item.quantity)
|
self.assertEqual(2, item.quantity)
|
||||||
|
|
||||||
def test_set_quantity(self):
|
def test_set_quantity(self):
|
||||||
current_cart = TestingCartController.for_user(self.USER_1)
|
current_cart = TestingCartController.for_user(self.USER_1)
|
||||||
|
|
|
@ -114,7 +114,7 @@ class CreditNoteTestCase(TestHelperMixin, RegistrationCartTestCase):
|
||||||
cn = self._credit_note_for_invoice(invoice.invoice)
|
cn = self._credit_note_for_invoice(invoice.invoice)
|
||||||
|
|
||||||
# That credit note should be in the unclaimed pile
|
# That credit note should be in the unclaimed pile
|
||||||
self.assertEquals(1, commerce.CreditNote.unclaimed().count())
|
self.assertEqual(1, commerce.CreditNote.unclaimed().count())
|
||||||
|
|
||||||
# Create a new (identical) cart with invoice
|
# Create a new (identical) cart with invoice
|
||||||
cart = TestingCartController.for_user(self.USER_1)
|
cart = TestingCartController.for_user(self.USER_1)
|
||||||
|
@ -126,7 +126,7 @@ class CreditNoteTestCase(TestHelperMixin, RegistrationCartTestCase):
|
||||||
self.assertTrue(invoice2.invoice.is_paid)
|
self.assertTrue(invoice2.invoice.is_paid)
|
||||||
|
|
||||||
# That invoice should not show up as unclaimed any more
|
# That invoice should not show up as unclaimed any more
|
||||||
self.assertEquals(0, commerce.CreditNote.unclaimed().count())
|
self.assertEqual(0, commerce.CreditNote.unclaimed().count())
|
||||||
|
|
||||||
def test_apply_credit_note_generates_new_credit_note_if_overpaying(self):
|
def test_apply_credit_note_generates_new_credit_note_if_overpaying(self):
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ class CreditNoteTestCase(TestHelperMixin, RegistrationCartTestCase):
|
||||||
# There should be one credit note generated out of the invoice.
|
# There should be one credit note generated out of the invoice.
|
||||||
cn = self._credit_note_for_invoice(invoice.invoice) # noqa
|
cn = self._credit_note_for_invoice(invoice.invoice) # noqa
|
||||||
|
|
||||||
self.assertEquals(1, commerce.CreditNote.unclaimed().count())
|
self.assertEqual(1, commerce.CreditNote.unclaimed().count())
|
||||||
|
|
||||||
# Create a new invoice for a cart of half value of inv 1
|
# Create a new invoice for a cart of half value of inv 1
|
||||||
invoice2 = self._invoice_containing_prod_1(1)
|
invoice2 = self._invoice_containing_prod_1(1)
|
||||||
|
@ -150,7 +150,7 @@ class CreditNoteTestCase(TestHelperMixin, RegistrationCartTestCase):
|
||||||
|
|
||||||
# We generated a new credit note, and spent the old one,
|
# We generated a new credit note, and spent the old one,
|
||||||
# unclaimed should still be 1.
|
# unclaimed should still be 1.
|
||||||
self.assertEquals(1, commerce.CreditNote.unclaimed().count())
|
self.assertEqual(1, commerce.CreditNote.unclaimed().count())
|
||||||
|
|
||||||
credit_note2 = commerce.CreditNote.objects.get(
|
credit_note2 = commerce.CreditNote.objects.get(
|
||||||
invoice=invoice2.invoice,
|
invoice=invoice2.invoice,
|
||||||
|
@ -158,7 +158,7 @@ class CreditNoteTestCase(TestHelperMixin, RegistrationCartTestCase):
|
||||||
|
|
||||||
# The new credit note should be the residual of the cost of cart 1
|
# The new credit note should be the residual of the cost of cart 1
|
||||||
# minus the cost of cart 2.
|
# minus the cost of cart 2.
|
||||||
self.assertEquals(
|
self.assertEqual(
|
||||||
invoice.invoice.value - invoice2.invoice.value,
|
invoice.invoice.value - invoice2.invoice.value,
|
||||||
credit_note2.value,
|
credit_note2.value,
|
||||||
)
|
)
|
||||||
|
@ -210,14 +210,14 @@ class CreditNoteTestCase(TestHelperMixin, RegistrationCartTestCase):
|
||||||
|
|
||||||
invoice.refund()
|
invoice.refund()
|
||||||
|
|
||||||
self.assertEquals(1, commerce.CreditNote.unclaimed().count())
|
self.assertEqual(1, commerce.CreditNote.unclaimed().count())
|
||||||
|
|
||||||
cn = self._credit_note_for_invoice(invoice.invoice)
|
cn = self._credit_note_for_invoice(invoice.invoice)
|
||||||
|
|
||||||
cn.refund()
|
cn.refund()
|
||||||
|
|
||||||
# Refunding a credit note should mark it as claimed
|
# Refunding a credit note should mark it as claimed
|
||||||
self.assertEquals(0, commerce.CreditNote.unclaimed().count())
|
self.assertEqual(0, commerce.CreditNote.unclaimed().count())
|
||||||
|
|
||||||
# Create a new cart with invoice
|
# Create a new cart with invoice
|
||||||
cart = TestingCartController.for_user(self.USER_1)
|
cart = TestingCartController.for_user(self.USER_1)
|
||||||
|
@ -238,7 +238,7 @@ class CreditNoteTestCase(TestHelperMixin, RegistrationCartTestCase):
|
||||||
|
|
||||||
invoice.refund()
|
invoice.refund()
|
||||||
|
|
||||||
self.assertEquals(1, commerce.CreditNote.unclaimed().count())
|
self.assertEqual(1, commerce.CreditNote.unclaimed().count())
|
||||||
|
|
||||||
cn = self._credit_note_for_invoice(invoice.invoice)
|
cn = self._credit_note_for_invoice(invoice.invoice)
|
||||||
|
|
||||||
|
@ -251,7 +251,7 @@ class CreditNoteTestCase(TestHelperMixin, RegistrationCartTestCase):
|
||||||
# Creating `invoice_2` will automatically apply `cn`.
|
# Creating `invoice_2` will automatically apply `cn`.
|
||||||
cn.apply_to_invoice(invoice_2.invoice)
|
cn.apply_to_invoice(invoice_2.invoice)
|
||||||
|
|
||||||
self.assertEquals(0, commerce.CreditNote.unclaimed().count())
|
self.assertEqual(0, commerce.CreditNote.unclaimed().count())
|
||||||
|
|
||||||
# Cannot refund this credit note as it is already applied.
|
# Cannot refund this credit note as it is already applied.
|
||||||
with self.assertRaises(ValidationError):
|
with self.assertRaises(ValidationError):
|
||||||
|
@ -327,13 +327,13 @@ class CreditNoteTestCase(TestHelperMixin, RegistrationCartTestCase):
|
||||||
invoice._refresh()
|
invoice._refresh()
|
||||||
|
|
||||||
# The first invoice should be refunded
|
# The first invoice should be refunded
|
||||||
self.assertEquals(
|
self.assertEqual(
|
||||||
commerce.Invoice.STATUS_VOID,
|
commerce.Invoice.STATUS_VOID,
|
||||||
invoice.invoice.status,
|
invoice.invoice.status,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Both credit notes should be for the same amount
|
# Both credit notes should be for the same amount
|
||||||
self.assertEquals(
|
self.assertEqual(
|
||||||
cn.credit_note.value,
|
cn.credit_note.value,
|
||||||
cn2.credit_note.value,
|
cn2.credit_note.value,
|
||||||
)
|
)
|
||||||
|
|
|
@ -98,7 +98,8 @@ class InvoiceTestCase(TestHelperMixin, RegistrationCartTestCase):
|
||||||
|
|
||||||
def test_total_payments_balance_due(self):
|
def test_total_payments_balance_due(self):
|
||||||
invoice = self._invoice_containing_prod_1(2)
|
invoice = self._invoice_containing_prod_1(2)
|
||||||
for i in xrange(0, invoice.invoice.value):
|
invoice_value = int(invoice.invoice.value)
|
||||||
|
for i in range(0, invoice_value):
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
i + 1, invoice.invoice.total_payments()
|
i + 1, invoice.invoice.total_payments()
|
||||||
)
|
)
|
||||||
|
@ -175,7 +176,7 @@ class InvoiceTestCase(TestHelperMixin, RegistrationCartTestCase):
|
||||||
invoice_1.refund()
|
invoice_1.refund()
|
||||||
|
|
||||||
cart.refresh_from_db()
|
cart.refresh_from_db()
|
||||||
self.assertEquals(commerce.Cart.STATUS_RELEASED, cart.status)
|
self.assertEqual(commerce.Cart.STATUS_RELEASED, cart.status)
|
||||||
|
|
||||||
def test_invoice_voids_self_if_cart_changes(self):
|
def test_invoice_voids_self_if_cart_changes(self):
|
||||||
current_cart = TestingCartController.for_user(self.USER_1)
|
current_cart = TestingCartController.for_user(self.USER_1)
|
||||||
|
@ -322,12 +323,12 @@ class InvoiceTestCase(TestHelperMixin, RegistrationCartTestCase):
|
||||||
)
|
)
|
||||||
inv = TestingInvoiceController(_invoice)
|
inv = TestingInvoiceController(_invoice)
|
||||||
|
|
||||||
self.assertEquals(
|
self.assertEqual(
|
||||||
inv.invoice.value,
|
inv.invoice.value,
|
||||||
sum(i[1] for i in description_price_pairs)
|
sum(i[1] for i in description_price_pairs)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEquals(
|
self.assertEqual(
|
||||||
len(inv.invoice.lineitem_set.all()),
|
len(inv.invoice.lineitem_set.all()),
|
||||||
len(description_price_pairs)
|
len(description_price_pairs)
|
||||||
)
|
)
|
||||||
|
@ -336,37 +337,37 @@ class InvoiceTestCase(TestHelperMixin, RegistrationCartTestCase):
|
||||||
|
|
||||||
def test_sends_email_on_invoice_creation(self):
|
def test_sends_email_on_invoice_creation(self):
|
||||||
invoice = self._invoice_containing_prod_1(1)
|
invoice = self._invoice_containing_prod_1(1)
|
||||||
self.assertEquals(1, len(self.emails))
|
self.assertEqual(1, len(self.emails))
|
||||||
email = self.emails[0]
|
email = self.emails[0]
|
||||||
self.assertEquals([self.USER_1.email], email["to"])
|
self.assertEqual([self.USER_1.email], email["to"])
|
||||||
self.assertEquals("invoice_created", email["kind"])
|
self.assertEqual("invoice_created", email["kind"])
|
||||||
self.assertEquals(invoice.invoice, email["context"]["invoice"])
|
self.assertEqual(invoice.invoice, email["context"]["invoice"])
|
||||||
|
|
||||||
def test_sends_first_change_email_on_invoice_fully_paid(self):
|
def test_sends_first_change_email_on_invoice_fully_paid(self):
|
||||||
invoice = self._invoice_containing_prod_1(1)
|
invoice = self._invoice_containing_prod_1(1)
|
||||||
|
|
||||||
self.assertEquals(1, len(self.emails))
|
self.assertEqual(1, len(self.emails))
|
||||||
invoice.pay("Partial", invoice.invoice.value - 1)
|
invoice.pay("Partial", invoice.invoice.value - 1)
|
||||||
# Should have an "invoice_created" email and nothing else.
|
# Should have an "invoice_created" email and nothing else.
|
||||||
self.assertEquals(1, len(self.emails))
|
self.assertEqual(1, len(self.emails))
|
||||||
invoice.pay("Remainder", 1)
|
invoice.pay("Remainder", 1)
|
||||||
self.assertEquals(2, len(self.emails))
|
self.assertEqual(2, len(self.emails))
|
||||||
|
|
||||||
email = self.emails[1]
|
email = self.emails[1]
|
||||||
self.assertEquals([self.USER_1.email], email["to"])
|
self.assertEqual([self.USER_1.email], email["to"])
|
||||||
self.assertEquals("invoice_updated", email["kind"])
|
self.assertEqual("invoice_updated", email["kind"])
|
||||||
self.assertEquals(invoice.invoice, email["context"]["invoice"])
|
self.assertEqual(invoice.invoice, email["context"]["invoice"])
|
||||||
|
|
||||||
def test_sends_email_when_invoice_refunded(self):
|
def test_sends_email_when_invoice_refunded(self):
|
||||||
invoice = self._invoice_containing_prod_1(1)
|
invoice = self._invoice_containing_prod_1(1)
|
||||||
|
|
||||||
self.assertEquals(1, len(self.emails))
|
self.assertEqual(1, len(self.emails))
|
||||||
invoice.pay("Payment", invoice.invoice.value)
|
invoice.pay("Payment", invoice.invoice.value)
|
||||||
self.assertEquals(2, len(self.emails))
|
self.assertEqual(2, len(self.emails))
|
||||||
invoice.refund()
|
invoice.refund()
|
||||||
self.assertEquals(3, len(self.emails))
|
self.assertEqual(3, len(self.emails))
|
||||||
|
|
||||||
email = self.emails[2]
|
email = self.emails[2]
|
||||||
self.assertEquals([self.USER_1.email], email["to"])
|
self.assertEqual([self.USER_1.email], email["to"])
|
||||||
self.assertEquals("invoice_updated", email["kind"])
|
self.assertEqual("invoice_updated", email["kind"])
|
||||||
self.assertEquals(invoice.invoice, email["context"]["invoice"])
|
self.assertEqual(invoice.invoice, email["context"]["invoice"])
|
||||||
|
|
|
@ -67,7 +67,7 @@ class SpeakerTestCase(RegistrationCartTestCase):
|
||||||
kind=kind_1,
|
kind=kind_1,
|
||||||
title="Proposal 1",
|
title="Proposal 1",
|
||||||
abstract="Abstract",
|
abstract="Abstract",
|
||||||
description="Description",
|
#description="Description",
|
||||||
speaker=speaker_1,
|
speaker=speaker_1,
|
||||||
)
|
)
|
||||||
proposal_models.AdditionalSpeaker.objects.create(
|
proposal_models.AdditionalSpeaker.objects.create(
|
||||||
|
@ -80,7 +80,7 @@ class SpeakerTestCase(RegistrationCartTestCase):
|
||||||
kind=kind_2,
|
kind=kind_2,
|
||||||
title="Proposal 2",
|
title="Proposal 2",
|
||||||
abstract="Abstract",
|
abstract="Abstract",
|
||||||
description="Description",
|
#description="Description",
|
||||||
speaker=speaker_1,
|
speaker=speaker_1,
|
||||||
)
|
)
|
||||||
proposal_models.AdditionalSpeaker.objects.create(
|
proposal_models.AdditionalSpeaker.objects.create(
|
||||||
|
|
4
vendor/registrasion/registrasion/views.py
vendored
4
vendor/registrasion/registrasion/views.py
vendored
|
@ -28,7 +28,7 @@ from django import forms as django_forms
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.contrib.auth.decorators import user_passes_test
|
from django.contrib.auth.decorators import user_passes_test
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
@ -50,6 +50,8 @@ from registrasion.contrib.badger import (
|
||||||
InvalidTicketChoiceError
|
InvalidTicketChoiceError
|
||||||
)
|
)
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
_GuidedRegistrationSection = namedtuple(
|
_GuidedRegistrationSection = namedtuple(
|
||||||
"GuidedRegistrationSection",
|
"GuidedRegistrationSection",
|
||||||
(
|
(
|
||||||
|
|
4
vendor/registrasion/requirements/base.txt
vendored
4
vendor/registrasion/requirements/base.txt
vendored
|
@ -1,3 +1,3 @@
|
||||||
django-nested-admin==2.2.6
|
django-nested-admin==3.3.2
|
||||||
#symposion==1.0b2.dev3
|
#symposion==1.0b2.dev3
|
||||||
lxml==4.0.0
|
lxml==4.6.1
|
||||||
|
|
8
vendor/registripe/registripe/forms.py
vendored
8
vendor/registripe/registripe/forms.py
vendored
|
@ -1,15 +1,13 @@
|
||||||
import copy
|
import copy
|
||||||
from registripe import models
|
from registripe import models
|
||||||
|
|
||||||
from django import forms
|
|
||||||
from django.core.urlresolvers import reverse
|
|
||||||
import functools
|
import functools
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.core.urlresolvers import reverse
|
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db.models import F, Q
|
from django.db.models import F, Q
|
||||||
from django.forms import widgets
|
from django.forms import widgets
|
||||||
|
from django.urls import reverse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from django_countries import countries
|
from django_countries import countries
|
||||||
|
@ -21,7 +19,7 @@ from pinax.stripe import models as pinax_stripe_models
|
||||||
|
|
||||||
class StripeCardElement(forms.widgets.TextInput):
|
class StripeCardElement(forms.widgets.TextInput):
|
||||||
|
|
||||||
def render(self, name, value, attrs=None):
|
def render(self, name, value, attrs=None, renderer=None):
|
||||||
element = '''
|
element = '''
|
||||||
<div class="registrasion-stripe-element" id='%s' style='"-moz-appearance: textfield; -webkit-appearance: textfield; appearance: field;"'>Please wait.</div>''' % (name, )
|
<div class="registrasion-stripe-element" id='%s' style='"-moz-appearance: textfield; -webkit-appearance: textfield; appearance: field;"'>Please wait.</div>''' % (name, )
|
||||||
|
|
||||||
|
@ -36,7 +34,7 @@ class StripeCardElement(forms.widgets.TextInput):
|
||||||
|
|
||||||
class StripeTokenWidget(forms.widgets.HiddenInput):
|
class StripeTokenWidget(forms.widgets.HiddenInput):
|
||||||
|
|
||||||
def render(self, name, value, attrs=None):
|
def render(self, name, value, attrs=None, renderer=None):
|
||||||
|
|
||||||
return '''
|
return '''
|
||||||
<div class='registrasion-stripe-token' style='display:none;'
|
<div class='registrasion-stripe-token' style='display:none;'
|
||||||
|
|
4
vendor/registripe/registripe/models.py
vendored
4
vendor/registripe/registripe/models.py
vendored
|
@ -7,8 +7,8 @@ from pinax.stripe.models import Charge
|
||||||
|
|
||||||
class StripePayment(commerce.PaymentBase):
|
class StripePayment(commerce.PaymentBase):
|
||||||
|
|
||||||
charge = models.ForeignKey(Charge)
|
charge = models.ForeignKey(Charge, on_delete=models.CASCADE)
|
||||||
|
|
||||||
class StripeCreditNoteRefund(commerce.CreditNoteRefund):
|
class StripeCreditNoteRefund(commerce.CreditNoteRefund):
|
||||||
|
|
||||||
charge = models.ForeignKey(Charge)
|
charge = models.ForeignKey(Charge, on_delete=models.CASCADE)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{% comment %}
|
{% comment %}
|
||||||
This is used in the default invoice.html file to display Stripe funcationality if the app is loaded.
|
This is used in the default invoice.html file to display Stripe functionality if the app is loaded.
|
||||||
{% endcomment %}
|
{% endcomment %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
8
vendor/registripe/requirements.txt
vendored
8
vendor/registripe/requirements.txt
vendored
|
@ -1,4 +1,4 @@
|
||||||
django-countries>=4.0
|
django-countries>=6.1.3
|
||||||
pinax-stripe==3.2.1
|
pinax-stripe==4.4.0
|
||||||
requests>=2.11.1
|
requests>=2.24.0
|
||||||
stripe==1.38.0
|
stripe==2.55.0
|
||||||
|
|
6
vendor/symposion/conference/models.py
vendored
6
vendor/symposion/conference/models.py
vendored
|
@ -49,7 +49,11 @@ class Section(models.Model):
|
||||||
scheduling process.
|
scheduling process.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
conference = models.ForeignKey(Conference, verbose_name=_("Conference"))
|
conference = models.ForeignKey(
|
||||||
|
Conference,
|
||||||
|
verbose_name=_("Conference"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
|
||||||
name = models.CharField(_("Name"), max_length=100)
|
name = models.CharField(_("Name"), max_length=100)
|
||||||
slug = models.SlugField(verbose_name=_("Slug"))
|
slug = models.SlugField(verbose_name=_("Slug"))
|
||||||
|
|
4
vendor/symposion/conference/views.py
vendored
4
vendor/symposion/conference/views.py
vendored
|
@ -2,7 +2,9 @@ from django.http import Http404
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth import get_user_model
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
|
57
vendor/symposion/proposals/models.py
vendored
57
vendor/symposion/proposals/models.py
vendored
|
@ -1,13 +1,13 @@
|
||||||
import os
|
import os
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from django.core.urlresolvers import reverse
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
from django.urls import reverse
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
|
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth import get_user_model
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@ from symposion.text_parser import parse
|
||||||
from symposion.conference.models import Section
|
from symposion.conference.models import Section
|
||||||
from symposion.speakers.models import Speaker
|
from symposion.speakers.models import Speaker
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
class ProposalSection(models.Model):
|
class ProposalSection(models.Model):
|
||||||
"""
|
"""
|
||||||
|
@ -30,7 +32,11 @@ class ProposalSection(models.Model):
|
||||||
* closed is NULL or False
|
* closed is NULL or False
|
||||||
"""
|
"""
|
||||||
|
|
||||||
section = models.OneToOneField(Section, verbose_name=_("Section"))
|
section = models.OneToOneField(
|
||||||
|
Section,
|
||||||
|
verbose_name=_("Section"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
|
||||||
start = models.DateTimeField(null=True, blank=True, verbose_name=_("Start"))
|
start = models.DateTimeField(null=True, blank=True, verbose_name=_("Start"))
|
||||||
end = models.DateTimeField(null=True, blank=True, verbose_name=_("End"))
|
end = models.DateTimeField(null=True, blank=True, verbose_name=_("End"))
|
||||||
|
@ -66,7 +72,12 @@ class ProposalKind(models.Model):
|
||||||
to distinguish the section as well as the kind.
|
to distinguish the section as well as the kind.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
section = models.ForeignKey(Section, related_name="proposal_kinds", verbose_name=_("Section"))
|
section = models.ForeignKey(
|
||||||
|
Section,
|
||||||
|
related_name="proposal_kinds",
|
||||||
|
verbose_name=_("Section"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
|
||||||
name = models.CharField(_("Name"), max_length=100)
|
name = models.CharField(_("Name"), max_length=100)
|
||||||
slug = models.SlugField(verbose_name=_("Slug"))
|
slug = models.SlugField(verbose_name=_("Slug"))
|
||||||
|
@ -79,7 +90,11 @@ class ProposalBase(models.Model):
|
||||||
|
|
||||||
objects = InheritanceManager()
|
objects = InheritanceManager()
|
||||||
|
|
||||||
kind = models.ForeignKey(ProposalKind, verbose_name=_("Kind"))
|
kind = models.ForeignKey(
|
||||||
|
ProposalKind,
|
||||||
|
verbose_name=_("Kind"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
|
||||||
title = models.CharField(max_length=100, verbose_name=_("Title"))
|
title = models.CharField(max_length=100, verbose_name=_("Title"))
|
||||||
abstract = models.TextField(
|
abstract = models.TextField(
|
||||||
|
@ -134,7 +149,12 @@ class ProposalBase(models.Model):
|
||||||
editable=False,
|
editable=False,
|
||||||
verbose_name=_("Submitted")
|
verbose_name=_("Submitted")
|
||||||
)
|
)
|
||||||
speaker = models.ForeignKey(Speaker, related_name="proposals", verbose_name=_("Speaker"))
|
speaker = models.ForeignKey(
|
||||||
|
Speaker,
|
||||||
|
related_name="proposals",
|
||||||
|
verbose_name=_("Speaker"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
|
||||||
# @@@ this validation used to exist as a validators keyword on additional_speakers
|
# @@@ this validation used to exist as a validators keyword on additional_speakers
|
||||||
# M2M field but that is no longer supported by Django. Should be moved to
|
# M2M field but that is no longer supported by Django. Should be moved to
|
||||||
|
@ -213,8 +233,16 @@ class AdditionalSpeaker(models.Model):
|
||||||
(SPEAKING_STATUS_DECLINED, _("Declined")),
|
(SPEAKING_STATUS_DECLINED, _("Declined")),
|
||||||
]
|
]
|
||||||
|
|
||||||
speaker = models.ForeignKey(Speaker, verbose_name=_("Speaker"))
|
speaker = models.ForeignKey(
|
||||||
proposalbase = models.ForeignKey(ProposalBase, verbose_name=_("Proposalbase"))
|
Speaker,
|
||||||
|
verbose_name=_("Speaker"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
proposalbase = models.ForeignKey(
|
||||||
|
ProposalBase,
|
||||||
|
verbose_name=_("Proposalbase"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
status = models.IntegerField(choices=SPEAKING_STATUS, default=SPEAKING_STATUS_PENDING, verbose_name=_("Status"))
|
status = models.IntegerField(choices=SPEAKING_STATUS, default=SPEAKING_STATUS_PENDING, verbose_name=_("Status"))
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -239,9 +267,18 @@ def uuid_filename(instance, filename):
|
||||||
|
|
||||||
class SupportingDocument(models.Model):
|
class SupportingDocument(models.Model):
|
||||||
|
|
||||||
proposal = models.ForeignKey(ProposalBase, related_name="supporting_documents", verbose_name=_("Proposal"))
|
proposal = models.ForeignKey(
|
||||||
|
ProposalBase,
|
||||||
|
related_name="supporting_documents",
|
||||||
|
verbose_name=_("Proposal"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
|
||||||
uploaded_by = models.ForeignKey(User, verbose_name=_("Uploaded by"))
|
uploaded_by = models.ForeignKey(
|
||||||
|
User,
|
||||||
|
verbose_name=_("Uploaded by"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
|
||||||
created_at = models.DateTimeField(default=now, verbose_name=_("Created at"))
|
created_at = models.DateTimeField(default=now, verbose_name=_("Created at"))
|
||||||
|
|
||||||
|
|
8
vendor/symposion/proposals/views.py
vendored
8
vendor/symposion/proposals/views.py
vendored
|
@ -5,14 +5,14 @@ import sys
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
|
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
|
||||||
from django.core.urlresolvers import reverse
|
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.http import Http404, HttpResponse, HttpResponseForbidden
|
from django.http import Http404, HttpResponse, HttpResponseForbidden
|
||||||
from django.shortcuts import render, redirect, get_object_or_404
|
from django.shortcuts import render, redirect, get_object_or_404
|
||||||
|
from django.urls import reverse
|
||||||
from django.views import static
|
from django.views import static
|
||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth import get_user_model
|
||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
@ -27,6 +27,8 @@ from symposion.proposals.forms import (
|
||||||
AddSpeakerForm, SupportingDocumentCreateForm
|
AddSpeakerForm, SupportingDocumentCreateForm
|
||||||
)
|
)
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
def get_form(name):
|
def get_form(name):
|
||||||
dot = name.rindex(".")
|
dot = name.rindex(".")
|
||||||
|
@ -36,7 +38,7 @@ def get_form(name):
|
||||||
|
|
||||||
|
|
||||||
def proposal_submit(request):
|
def proposal_submit(request):
|
||||||
if not request.user.is_authenticated():
|
if not request.user.is_authenticated:
|
||||||
messages.info(request, _("To submit a proposal, please "
|
messages.info(request, _("To submit a proposal, please "
|
||||||
"<a href='{0}'>log in</a> and create a speaker profile "
|
"<a href='{0}'>log in</a> and create a speaker profile "
|
||||||
"via the dashboard.".format(settings.LOGIN_URL)))
|
"via the dashboard.".format(settings.LOGIN_URL)))
|
||||||
|
|
91
vendor/symposion/reviews/models.py
vendored
91
vendor/symposion/reviews/models.py
vendored
|
@ -10,7 +10,7 @@ from django.db.models import Case, When, Value
|
||||||
from django.db.models import Count
|
from django.db.models import Count
|
||||||
from django.db.models.signals import post_save
|
from django.db.models.signals import post_save
|
||||||
|
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth import get_user_model
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from symposion import constants
|
from symposion import constants
|
||||||
|
@ -18,6 +18,8 @@ from symposion.text_parser import parse
|
||||||
from symposion.proposals.models import ProposalBase
|
from symposion.proposals.models import ProposalBase
|
||||||
from symposion.schedule.models import Presentation
|
from symposion.schedule.models import Presentation
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
class Votes(object):
|
class Votes(object):
|
||||||
ABSTAIN = "0"
|
ABSTAIN = "0"
|
||||||
|
@ -51,8 +53,16 @@ class ReviewAssignment(models.Model):
|
||||||
(AUTO_ASSIGNED_LATER, _("auto-assigned, later")),
|
(AUTO_ASSIGNED_LATER, _("auto-assigned, later")),
|
||||||
]
|
]
|
||||||
|
|
||||||
proposal = models.ForeignKey(ProposalBase, verbose_name=_("Proposal"))
|
proposal = models.ForeignKey(
|
||||||
user = models.ForeignKey(User, verbose_name=_("User"))
|
ProposalBase,
|
||||||
|
verbose_name=_("Proposal"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
user = models.ForeignKey(
|
||||||
|
User,
|
||||||
|
verbose_name=_("User"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
|
||||||
origin = models.IntegerField(choices=ORIGIN_CHOICES, verbose_name=_("Origin"))
|
origin = models.IntegerField(choices=ORIGIN_CHOICES, verbose_name=_("Origin"))
|
||||||
|
|
||||||
|
@ -91,8 +101,17 @@ class ReviewAssignment(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class ProposalMessage(models.Model):
|
class ProposalMessage(models.Model):
|
||||||
proposal = models.ForeignKey(ProposalBase, related_name="messages", verbose_name=_("Proposal"))
|
proposal = models.ForeignKey(
|
||||||
user = models.ForeignKey(User, verbose_name=_("User"))
|
ProposalBase,
|
||||||
|
related_name="messages",
|
||||||
|
verbose_name=_("Proposal"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
user = models.ForeignKey(
|
||||||
|
User,
|
||||||
|
verbose_name=_("User"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
|
||||||
message = models.TextField(verbose_name=_("Message"))
|
message = models.TextField(verbose_name=_("Message"))
|
||||||
message_html = models.TextField(blank=True)
|
message_html = models.TextField(blank=True)
|
||||||
|
@ -111,8 +130,17 @@ class ProposalMessage(models.Model):
|
||||||
class Review(models.Model):
|
class Review(models.Model):
|
||||||
VOTES = VOTES
|
VOTES = VOTES
|
||||||
|
|
||||||
proposal = models.ForeignKey(ProposalBase, related_name="reviews", verbose_name=_("Proposal"))
|
proposal = models.ForeignKey(
|
||||||
user = models.ForeignKey(User, verbose_name=_("User"))
|
ProposalBase,
|
||||||
|
related_name="reviews",
|
||||||
|
verbose_name=_("Proposal"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
user = models.ForeignKey(
|
||||||
|
User,
|
||||||
|
verbose_name=_("User"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
|
||||||
# No way to encode "-0" vs. "+0" into an IntegerField, and I don't feel
|
# No way to encode "-0" vs. "+0" into an IntegerField, and I don't feel
|
||||||
# like some complicated encoding system.
|
# like some complicated encoding system.
|
||||||
|
@ -208,8 +236,17 @@ class Review(models.Model):
|
||||||
class LatestVote(models.Model):
|
class LatestVote(models.Model):
|
||||||
VOTES = VOTES
|
VOTES = VOTES
|
||||||
|
|
||||||
proposal = models.ForeignKey(ProposalBase, related_name="votes", verbose_name=_("Proposal"))
|
proposal = models.ForeignKey(
|
||||||
user = models.ForeignKey(User, verbose_name=_("User"))
|
ProposalBase,
|
||||||
|
related_name="votes",
|
||||||
|
verbose_name=_("Proposal"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
user = models.ForeignKey(
|
||||||
|
User,
|
||||||
|
verbose_name=_("User"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
|
||||||
# No way to encode "-0" vs. "+0" into an IntegerField, and I don't feel
|
# No way to encode "-0" vs. "+0" into an IntegerField, and I don't feel
|
||||||
# like some complicated encoding system.
|
# like some complicated encoding system.
|
||||||
|
@ -232,7 +269,12 @@ class LatestVote(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class ProposalResult(models.Model):
|
class ProposalResult(models.Model):
|
||||||
proposal = models.OneToOneField(ProposalBase, related_name="result", verbose_name=_("Proposal"))
|
proposal = models.OneToOneField(
|
||||||
|
ProposalBase,
|
||||||
|
related_name="result",
|
||||||
|
verbose_name=_("Proposal"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
score = models.DecimalField(max_digits=5, decimal_places=2, default=Decimal("0.00"), verbose_name=_("Score"))
|
score = models.DecimalField(max_digits=5, decimal_places=2, default=Decimal("0.00"), verbose_name=_("Score"))
|
||||||
comment_count = models.PositiveIntegerField(default=0, verbose_name=_("Comment count"))
|
comment_count = models.PositiveIntegerField(default=0, verbose_name=_("Comment count"))
|
||||||
# vote_count only counts non-abstain votes.
|
# vote_count only counts non-abstain votes.
|
||||||
|
@ -297,8 +339,17 @@ class ProposalResult(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class Comment(models.Model):
|
class Comment(models.Model):
|
||||||
proposal = models.ForeignKey(ProposalBase, related_name="comments", verbose_name=_("Proposal"))
|
proposal = models.ForeignKey(
|
||||||
commenter = models.ForeignKey(User, verbose_name=_("Commenter"))
|
ProposalBase,
|
||||||
|
related_name="comments",
|
||||||
|
verbose_name=_("Proposal"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
commenter = models.ForeignKey(
|
||||||
|
User,
|
||||||
|
verbose_name=_("Commenter"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
text = models.TextField(verbose_name=_("Text"))
|
text = models.TextField(verbose_name=_("Text"))
|
||||||
text_html = models.TextField(blank=True)
|
text_html = models.TextField(blank=True)
|
||||||
|
|
||||||
|
@ -329,9 +380,19 @@ class NotificationTemplate(models.Model):
|
||||||
|
|
||||||
class ResultNotification(models.Model):
|
class ResultNotification(models.Model):
|
||||||
|
|
||||||
proposal = models.ForeignKey(ProposalBase, related_name="notifications", verbose_name=_("Proposal"))
|
proposal = models.ForeignKey(
|
||||||
template = models.ForeignKey(NotificationTemplate, null=True, blank=True,
|
ProposalBase,
|
||||||
on_delete=models.SET_NULL, verbose_name=_("Template"))
|
related_name="notifications",
|
||||||
|
verbose_name=_("Proposal"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
template = models.ForeignKey(
|
||||||
|
NotificationTemplate,
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
|
verbose_name=_("Template")
|
||||||
|
)
|
||||||
timestamp = models.DateTimeField(default=datetime.now, verbose_name=_("Timestamp"))
|
timestamp = models.DateTimeField(default=datetime.now, verbose_name=_("Timestamp"))
|
||||||
to_address = models.EmailField(verbose_name=_("To address"))
|
to_address = models.EmailField(verbose_name=_("To address"))
|
||||||
from_address = models.EmailField(verbose_name=_("From address"))
|
from_address = models.EmailField(verbose_name=_("From address"))
|
||||||
|
|
|
@ -6,7 +6,7 @@ from symposion.reviews.models import ReviewAssignment
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
@register.assignment_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
def review_assignments(context):
|
def review_assignments(context):
|
||||||
request = context["request"]
|
request = context["request"]
|
||||||
assignments = ReviewAssignment.objects.filter(user=request.user)
|
assignments = ReviewAssignment.objects.filter(user=request.user)
|
||||||
|
|
3
vendor/symposion/reviews/views.py
vendored
3
vendor/symposion/reviews/views.py
vendored
|
@ -268,6 +268,8 @@ def review_list(request, section_slug, user_pk):
|
||||||
if not request.user.pk == user_pk:
|
if not request.user.pk == user_pk:
|
||||||
return access_not_permitted(request)
|
return access_not_permitted(request)
|
||||||
|
|
||||||
|
section = get_object_or_404(ProposalSection, section__slug=section_slug)
|
||||||
|
|
||||||
queryset = ProposalBase.objects.select_related("speaker__user", "result")
|
queryset = ProposalBase.objects.select_related("speaker__user", "result")
|
||||||
reviewed = LatestVote.objects.filter(user__pk=user_pk).values_list("proposal", flat=True)
|
reviewed = LatestVote.objects.filter(user__pk=user_pk).values_list("proposal", flat=True)
|
||||||
queryset = queryset.filter(kind__section__slug=section_slug)
|
queryset = queryset.filter(kind__section__slug=section_slug)
|
||||||
|
@ -280,6 +282,7 @@ def review_list(request, section_slug, user_pk):
|
||||||
|
|
||||||
ctx = {
|
ctx = {
|
||||||
"proposals": proposals,
|
"proposals": proposals,
|
||||||
|
"section": section,
|
||||||
}
|
}
|
||||||
return render(request, "symposion/reviews/review_list.html", ctx)
|
return render(request, "symposion/reviews/review_list.html", ctx)
|
||||||
|
|
||||||
|
|
2
vendor/symposion/schedule/forms.py
vendored
2
vendor/symposion/schedule/forms.py
vendored
|
@ -73,6 +73,8 @@ class ScheduleSectionForm(forms.Form):
|
||||||
if 'encoding' in kwargs:
|
if 'encoding' in kwargs:
|
||||||
self.encoding = kwargs['encoding']
|
self.encoding = kwargs['encoding']
|
||||||
kwargs.pop('encoding')
|
kwargs.pop('encoding')
|
||||||
|
else:
|
||||||
|
self.encoding = "utf-8"
|
||||||
super(ScheduleSectionForm, self).__init__(*args, **kwargs)
|
super(ScheduleSectionForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
def clean_filename(self):
|
def clean_filename(self):
|
||||||
|
|
105
vendor/symposion/schedule/models.py
vendored
105
vendor/symposion/schedule/models.py
vendored
|
@ -1,7 +1,7 @@
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth import get_user_model
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
@ -11,11 +11,17 @@ from symposion.proposals.models import ProposalBase
|
||||||
from symposion.conference.models import Section
|
from symposion.conference.models import Section
|
||||||
from symposion.speakers.models import Speaker
|
from symposion.speakers.models import Speaker
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
class Schedule(models.Model):
|
class Schedule(models.Model):
|
||||||
objects = DefaultSelectRelatedManager()
|
objects = DefaultSelectRelatedManager()
|
||||||
|
|
||||||
section = models.OneToOneField(Section, verbose_name=_("Section"))
|
section = models.OneToOneField(
|
||||||
|
Section,
|
||||||
|
verbose_name=_("Section"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
published = models.BooleanField(default=True, verbose_name=_("Published"))
|
published = models.BooleanField(default=True, verbose_name=_("Published"))
|
||||||
hidden = models.BooleanField(_("Hide schedule from overall conference view"), default=False)
|
hidden = models.BooleanField(_("Hide schedule from overall conference view"), default=False)
|
||||||
|
|
||||||
|
@ -35,7 +41,11 @@ class Day(models.Model):
|
||||||
objects = DefaultSelectRelatedManager()
|
objects = DefaultSelectRelatedManager()
|
||||||
|
|
||||||
|
|
||||||
schedule = models.ForeignKey(Schedule, verbose_name=_("Schedule"))
|
schedule = models.ForeignKey(
|
||||||
|
Schedule,
|
||||||
|
verbose_name=_("Schedule"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
date = models.DateField(verbose_name=_("Date"))
|
date = models.DateField(verbose_name=_("Date"))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -53,7 +63,11 @@ class Day(models.Model):
|
||||||
|
|
||||||
class Room(models.Model):
|
class Room(models.Model):
|
||||||
|
|
||||||
schedule = models.ForeignKey(Schedule, verbose_name=_("Schedule"))
|
schedule = models.ForeignKey(
|
||||||
|
Schedule,
|
||||||
|
verbose_name=_("Schedule"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
name = models.CharField(max_length=65, verbose_name=_("Name"))
|
name = models.CharField(max_length=65, verbose_name=_("Name"))
|
||||||
order = models.PositiveIntegerField(verbose_name=_("Order"))
|
order = models.PositiveIntegerField(verbose_name=_("Order"))
|
||||||
|
|
||||||
|
@ -70,8 +84,8 @@ class Room(models.Model):
|
||||||
|
|
||||||
class Track(models.Model):
|
class Track(models.Model):
|
||||||
name = models.CharField(max_length=80, verbose_name=_("Track"))
|
name = models.CharField(max_length=80, verbose_name=_("Track"))
|
||||||
room = models.ForeignKey(Room)
|
room = models.ForeignKey(Room, on_delete=models.CASCADE)
|
||||||
day = models.ForeignKey(Day)
|
day = models.ForeignKey(Day, on_delete=models.CASCADE)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
@ -88,7 +102,11 @@ class SlotKind(models.Model):
|
||||||
break, lunch, or X-minute talk.
|
break, lunch, or X-minute talk.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
schedule = models.ForeignKey(Schedule, verbose_name=_("schedule"))
|
schedule = models.ForeignKey(
|
||||||
|
Schedule,
|
||||||
|
verbose_name=_("schedule"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
label = models.CharField(max_length=50, verbose_name=_("Label"))
|
label = models.CharField(max_length=50, verbose_name=_("Label"))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -103,8 +121,16 @@ class Slot(models.Model):
|
||||||
objects = DefaultSelectRelatedManager()
|
objects = DefaultSelectRelatedManager()
|
||||||
|
|
||||||
name = models.CharField(max_length=512, editable=False)
|
name = models.CharField(max_length=512, editable=False)
|
||||||
day = models.ForeignKey(Day, verbose_name=_("Day"))
|
day = models.ForeignKey(
|
||||||
kind = models.ForeignKey(SlotKind, verbose_name=_("Kind"))
|
Day,
|
||||||
|
verbose_name=_("Day"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
kind = models.ForeignKey(
|
||||||
|
SlotKind,
|
||||||
|
verbose_name=_("Kind"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
start = models.TimeField(verbose_name=_("Start"))
|
start = models.TimeField(verbose_name=_("Start"))
|
||||||
end = models.TimeField(verbose_name=_("End"))
|
end = models.TimeField(verbose_name=_("End"))
|
||||||
exclusive = models.BooleanField(
|
exclusive = models.BooleanField(
|
||||||
|
@ -194,8 +220,16 @@ class SlotRoom(models.Model):
|
||||||
Links a slot with a room.
|
Links a slot with a room.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
slot = models.ForeignKey(Slot, verbose_name=_("Slot"))
|
slot = models.ForeignKey(
|
||||||
room = models.ForeignKey(Room, verbose_name=_("Room"))
|
Slot,
|
||||||
|
verbose_name=_("Slot"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
room = models.ForeignKey(
|
||||||
|
Room,
|
||||||
|
verbose_name=_("Room"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s %s" % (self.room, self.slot)
|
return "%s %s" % (self.room, self.slot)
|
||||||
|
@ -210,11 +244,23 @@ class SlotRoom(models.Model):
|
||||||
class Presentation(models.Model):
|
class Presentation(models.Model):
|
||||||
objects = DefaultSelectRelatedManager()
|
objects = DefaultSelectRelatedManager()
|
||||||
|
|
||||||
slot = models.OneToOneField(Slot, null=True, blank=True, related_name="content_ptr", verbose_name=_("Slot"))
|
slot = models.OneToOneField(
|
||||||
|
Slot,
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
related_name="content_ptr",
|
||||||
|
verbose_name=_("Slot"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
title = models.CharField(max_length=100, verbose_name=_("Title"))
|
title = models.CharField(max_length=100, verbose_name=_("Title"))
|
||||||
abstract = models.TextField(verbose_name=_("Abstract"))
|
abstract = models.TextField(verbose_name=_("Abstract"))
|
||||||
abstract_html = models.TextField(blank=True)
|
abstract_html = models.TextField(blank=True)
|
||||||
speaker = models.ForeignKey(Speaker, related_name="presentations", verbose_name=_("Speaker"))
|
speaker = models.ForeignKey(
|
||||||
|
Speaker,
|
||||||
|
related_name="presentations",
|
||||||
|
verbose_name=_("Speaker"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
additional_speakers = models.ManyToManyField(Speaker, related_name="copresentations",
|
additional_speakers = models.ManyToManyField(Speaker, related_name="copresentations",
|
||||||
blank=True, verbose_name=_("Additional speakers"))
|
blank=True, verbose_name=_("Additional speakers"))
|
||||||
unpublish = models.BooleanField(
|
unpublish = models.BooleanField(
|
||||||
|
@ -222,8 +268,18 @@ class Presentation(models.Model):
|
||||||
verbose_name=_("Do not publish"),
|
verbose_name=_("Do not publish"),
|
||||||
)
|
)
|
||||||
cancelled = models.BooleanField(default=False, verbose_name=_("Cancelled"))
|
cancelled = models.BooleanField(default=False, verbose_name=_("Cancelled"))
|
||||||
proposal_base = models.OneToOneField(ProposalBase, related_name="presentation", verbose_name=_("Proposal base"))
|
proposal_base = models.OneToOneField(
|
||||||
section = models.ForeignKey(Section, related_name="presentations", verbose_name=_("Section"))
|
ProposalBase,
|
||||||
|
related_name="presentation",
|
||||||
|
verbose_name=_("Proposal base"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
section = models.ForeignKey(
|
||||||
|
Section,
|
||||||
|
related_name="presentations",
|
||||||
|
verbose_name=_("Section"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
self.abstract_html = parse(self.abstract)
|
self.abstract_html = parse(self.abstract)
|
||||||
|
@ -256,7 +312,12 @@ class Presentation(models.Model):
|
||||||
|
|
||||||
class Session(models.Model):
|
class Session(models.Model):
|
||||||
|
|
||||||
day = models.ForeignKey(Day, related_name="sessions", verbose_name=_("Day"))
|
day = models.ForeignKey(
|
||||||
|
Day,
|
||||||
|
related_name="sessions",
|
||||||
|
verbose_name=_("Day"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
slots = models.ManyToManyField(Slot, related_name="sessions", verbose_name=_("Slots"))
|
slots = models.ManyToManyField(Slot, related_name="sessions", verbose_name=_("Slots"))
|
||||||
|
|
||||||
def sorted_slots(self):
|
def sorted_slots(self):
|
||||||
|
@ -318,8 +379,16 @@ class SessionRole(models.Model):
|
||||||
(SESSION_ROLE_RUNNER, _("Session Runner")),
|
(SESSION_ROLE_RUNNER, _("Session Runner")),
|
||||||
]
|
]
|
||||||
|
|
||||||
session = models.ForeignKey(Session, verbose_name=_("Session"))
|
session = models.ForeignKey(
|
||||||
user = models.ForeignKey(User, verbose_name=_("User"))
|
Session,
|
||||||
|
verbose_name=_("Session"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
user = models.ForeignKey(
|
||||||
|
User,
|
||||||
|
verbose_name=_("User"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
role = models.IntegerField(choices=SESSION_ROLE_TYPES, verbose_name=_("Role"))
|
role = models.IntegerField(choices=SESSION_ROLE_TYPES, verbose_name=_("Role"))
|
||||||
status = models.NullBooleanField(verbose_name=_("Status"))
|
status = models.NullBooleanField(verbose_name=_("Status"))
|
||||||
|
|
||||||
|
|
12
vendor/symposion/schedule/tests/factories.py
vendored
12
vendor/symposion/schedule/tests/factories.py
vendored
|
@ -9,7 +9,7 @@ from symposion.schedule.models import Schedule, Day, Slot, SlotKind
|
||||||
from symposion.conference.models import Section, Conference
|
from symposion.conference.models import Section, Conference
|
||||||
|
|
||||||
|
|
||||||
class ConferenceFactory(factory.DjangoModelFactory):
|
class ConferenceFactory(factory.django.DjangoModelFactory):
|
||||||
title = fuzzy.FuzzyText()
|
title = fuzzy.FuzzyText()
|
||||||
start_date = fuzzy.FuzzyDate(datetime.date(2014, 1, 1))
|
start_date = fuzzy.FuzzyDate(datetime.date(2014, 1, 1))
|
||||||
end_date = fuzzy.FuzzyDate(
|
end_date = fuzzy.FuzzyDate(
|
||||||
|
@ -21,7 +21,7 @@ class ConferenceFactory(factory.DjangoModelFactory):
|
||||||
model = Conference
|
model = Conference
|
||||||
|
|
||||||
|
|
||||||
class SectionFactory(factory.DjangoModelFactory):
|
class SectionFactory(factory.django.DjangoModelFactory):
|
||||||
conference = factory.SubFactory(ConferenceFactory)
|
conference = factory.SubFactory(ConferenceFactory)
|
||||||
name = fuzzy.FuzzyText()
|
name = fuzzy.FuzzyText()
|
||||||
slug = fuzzy.FuzzyText()
|
slug = fuzzy.FuzzyText()
|
||||||
|
@ -30,7 +30,7 @@ class SectionFactory(factory.DjangoModelFactory):
|
||||||
model = Section
|
model = Section
|
||||||
|
|
||||||
|
|
||||||
class ScheduleFactory(factory.DjangoModelFactory):
|
class ScheduleFactory(factory.django.DjangoModelFactory):
|
||||||
section = factory.SubFactory(SectionFactory)
|
section = factory.SubFactory(SectionFactory)
|
||||||
published = True
|
published = True
|
||||||
hidden = False
|
hidden = False
|
||||||
|
@ -39,7 +39,7 @@ class ScheduleFactory(factory.DjangoModelFactory):
|
||||||
model = Schedule
|
model = Schedule
|
||||||
|
|
||||||
|
|
||||||
class SlotKindFactory(factory.DjangoModelFactory):
|
class SlotKindFactory(factory.django.DjangoModelFactory):
|
||||||
schedule = factory.SubFactory(ScheduleFactory)
|
schedule = factory.SubFactory(ScheduleFactory)
|
||||||
label = fuzzy.FuzzyText()
|
label = fuzzy.FuzzyText()
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ class SlotKindFactory(factory.DjangoModelFactory):
|
||||||
model = SlotKind
|
model = SlotKind
|
||||||
|
|
||||||
|
|
||||||
class DayFactory(factory.DjangoModelFactory):
|
class DayFactory(factory.django.DjangoModelFactory):
|
||||||
schedule = factory.SubFactory(ScheduleFactory)
|
schedule = factory.SubFactory(ScheduleFactory)
|
||||||
date = fuzzy.FuzzyDate(datetime.date(2014, 1, 1))
|
date = fuzzy.FuzzyDate(datetime.date(2014, 1, 1))
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ class DayFactory(factory.DjangoModelFactory):
|
||||||
model = Day
|
model = Day
|
||||||
|
|
||||||
|
|
||||||
class SlotFactory(factory.DjangoModelFactory):
|
class SlotFactory(factory.django.DjangoModelFactory):
|
||||||
day = factory.SubFactory(DayFactory)
|
day = factory.SubFactory(DayFactory)
|
||||||
kind = factory.SubFactory(SlotKindFactory)
|
kind = factory.SubFactory(SlotKindFactory)
|
||||||
start = datetime.time(random.randint(0, 23), random.randint(0, 59))
|
start = datetime.time(random.randint(0, 23), random.randint(0, 59))
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
from datetime import date
|
from datetime import date
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth import get_user_model
|
||||||
from django.core.urlresolvers import reverse
|
from django.urls import reverse
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from symposion.conference.models import Section, current_conference, Conference
|
from symposion.conference.models import Section, current_conference, Conference
|
||||||
from symposion.schedule.models import Day, Schedule, Session
|
from symposion.schedule.models import Day, Schedule, Session
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
class TestScheduleViews(TestCase):
|
class TestScheduleViews(TestCase):
|
||||||
username = "user@example.com"
|
username = "user@example.com"
|
||||||
|
|
12
vendor/symposion/schedule/views.py
vendored
12
vendor/symposion/schedule/views.py
vendored
|
@ -1,13 +1,13 @@
|
||||||
import json
|
import json
|
||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
from django.core.urlresolvers import reverse
|
|
||||||
from django.http import Http404, HttpResponse
|
from django.http import Http404, HttpResponse
|
||||||
from django.shortcuts import render, get_object_or_404, redirect
|
from django.shortcuts import render, get_object_or_404, redirect
|
||||||
|
from django.urls import reverse
|
||||||
from django.template import loader, Context
|
from django.template import loader, Context
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@ from symposion.schedule.timetable import TimeTable
|
||||||
from symposion.conference.models import Conference
|
from symposion.conference.models import Conference
|
||||||
from pinaxcon.templatetags.lca2018_tags import speaker_photo
|
from pinaxcon.templatetags.lca2018_tags import speaker_photo
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
def fetch_schedule(slug):
|
def fetch_schedule(slug):
|
||||||
qs = Schedule.objects.all()
|
qs = Schedule.objects.all()
|
||||||
|
@ -369,7 +371,7 @@ def session_detail(request, session_id):
|
||||||
if chairs:
|
if chairs:
|
||||||
chair = chairs[0].user
|
chair = chairs[0].user
|
||||||
else:
|
else:
|
||||||
if request.user.is_authenticated():
|
if request.user.is_authenticated:
|
||||||
# did the current user previously try to apply and got rejected?
|
# did the current user previously try to apply and got rejected?
|
||||||
if SessionRole.objects.filter(session=session, user=request.user, role=SessionRole.SESSION_ROLE_CHAIR, status=False):
|
if SessionRole.objects.filter(session=session, user=request.user, role=SessionRole.SESSION_ROLE_CHAIR, status=False):
|
||||||
chair_denied = True
|
chair_denied = True
|
||||||
|
@ -380,12 +382,12 @@ def session_detail(request, session_id):
|
||||||
if runners:
|
if runners:
|
||||||
runner = runners[0].user
|
runner = runners[0].user
|
||||||
else:
|
else:
|
||||||
if request.user.is_authenticated():
|
if request.user.is_authenticated:
|
||||||
# did the current user previously try to apply and got rejected?
|
# did the current user previously try to apply and got rejected?
|
||||||
if SessionRole.objects.filter(session=session, user=request.user, role=SessionRole.SESSION_ROLE_RUNNER, status=False):
|
if SessionRole.objects.filter(session=session, user=request.user, role=SessionRole.SESSION_ROLE_RUNNER, status=False):
|
||||||
runner_denied = True
|
runner_denied = True
|
||||||
|
|
||||||
if request.method == "POST" and request.user.is_authenticated():
|
if request.method == "POST" and request.user.is_authenticated:
|
||||||
if not hasattr(request.user, "attendee") or not request.user.attendee.completed_registration:
|
if not hasattr(request.user, "attendee") or not request.user.attendee.completed_registration:
|
||||||
response = redirect("guided_registration")
|
response = redirect("guided_registration")
|
||||||
response["Location"] += "?next=%s" % request.path
|
response["Location"] += "?next=%s" % request.path
|
||||||
|
|
14
vendor/symposion/speakers/models.py
vendored
14
vendor/symposion/speakers/models.py
vendored
|
@ -1,18 +1,26 @@
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from django.core.urlresolvers import reverse
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.urls import reverse
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth import get_user_model
|
||||||
|
|
||||||
from symposion import constants
|
from symposion import constants
|
||||||
from symposion.text_parser import parse
|
from symposion.text_parser import parse
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
class Speaker(models.Model):
|
class Speaker(models.Model):
|
||||||
|
|
||||||
user = models.OneToOneField(User, null=True, related_name="speaker_profile", verbose_name=_("User"))
|
user = models.OneToOneField(
|
||||||
|
User,
|
||||||
|
null=True,
|
||||||
|
related_name="speaker_profile",
|
||||||
|
verbose_name=_("User"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
name = models.CharField(verbose_name=_("Name"), max_length=100,
|
name = models.CharField(verbose_name=_("Name"), max_length=100,
|
||||||
help_text=_("As you would like it to appear in the"
|
help_text=_("As you would like it to appear in the"
|
||||||
" conference programme."))
|
" conference programme."))
|
||||||
|
|
4
vendor/symposion/speakers/views.py
vendored
4
vendor/symposion/speakers/views.py
vendored
|
@ -4,13 +4,15 @@ from django.shortcuts import render, redirect, get_object_or_404
|
||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth import get_user_model
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from symposion.proposals.models import ProposalBase
|
from symposion.proposals.models import ProposalBase
|
||||||
from symposion.speakers.forms import SpeakerForm
|
from symposion.speakers.forms import SpeakerForm
|
||||||
from symposion.speakers.models import Speaker
|
from symposion.speakers.models import Speaker
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def speaker_create(request):
|
def speaker_create(request):
|
||||||
|
|
66
vendor/symposion/sponsorship/models.py
vendored
66
vendor/symposion/sponsorship/models.py
vendored
|
@ -2,16 +2,18 @@ import datetime
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.urlresolvers import reverse
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models.signals import post_init, post_save
|
from django.db.models.signals import post_init, post_save
|
||||||
|
from django.urls import reverse
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth import get_user_model
|
||||||
|
|
||||||
from symposion.conference.models import Conference
|
from symposion.conference.models import Conference
|
||||||
from symposion.sponsorship.managers import SponsorManager
|
from symposion.sponsorship.managers import SponsorManager
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
# The benefits we track as individual fields on sponsors
|
# The benefits we track as individual fields on sponsors
|
||||||
# Names are the names in the database as defined by organizers.
|
# Names are the names in the database as defined by organizers.
|
||||||
|
@ -44,7 +46,11 @@ BENEFITS = [
|
||||||
|
|
||||||
class SponsorLevel(models.Model):
|
class SponsorLevel(models.Model):
|
||||||
|
|
||||||
conference = models.ForeignKey(Conference, verbose_name=_("Conference"))
|
conference = models.ForeignKey(
|
||||||
|
Conference,
|
||||||
|
verbose_name=_("Conference"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
name = models.CharField(_("Name"), max_length=100)
|
name = models.CharField(_("Name"), max_length=100)
|
||||||
order = models.IntegerField(_("Order"), default=0)
|
order = models.IntegerField(_("Order"), default=0)
|
||||||
cost = models.PositiveIntegerField(_("Cost"))
|
cost = models.PositiveIntegerField(_("Cost"))
|
||||||
|
@ -64,8 +70,13 @@ class SponsorLevel(models.Model):
|
||||||
|
|
||||||
class Sponsor(models.Model):
|
class Sponsor(models.Model):
|
||||||
|
|
||||||
applicant = models.ForeignKey(User, related_name="sponsorships", verbose_name=_("Applicant"),
|
applicant = models.ForeignKey(
|
||||||
null=True)
|
User,
|
||||||
|
related_name="sponsorships",
|
||||||
|
verbose_name=_("Applicant"),
|
||||||
|
null=True,
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
|
||||||
name = models.CharField(_("Sponsor Name"), max_length=100)
|
name = models.CharField(_("Sponsor Name"), max_length=100)
|
||||||
display_url = models.URLField(_("display URL"), blank=True)
|
display_url = models.URLField(_("display URL"), blank=True)
|
||||||
|
@ -73,13 +84,24 @@ class Sponsor(models.Model):
|
||||||
annotation = models.TextField(_("Annotation"), blank=True)
|
annotation = models.TextField(_("Annotation"), blank=True)
|
||||||
contact_name = models.CharField(_("Contact Name"), max_length=100)
|
contact_name = models.CharField(_("Contact Name"), max_length=100)
|
||||||
contact_email = models.EmailField(_("Contact Email"))
|
contact_email = models.EmailField(_("Contact Email"))
|
||||||
level = models.ForeignKey(SponsorLevel, verbose_name=_("level"))
|
level = models.ForeignKey(
|
||||||
|
SponsorLevel,
|
||||||
|
verbose_name=_("level"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
added = models.DateTimeField(_("added"), default=datetime.datetime.now)
|
added = models.DateTimeField(_("added"), default=datetime.datetime.now)
|
||||||
active = models.BooleanField(_("active"), default=False)
|
active = models.BooleanField(_("active"), default=False)
|
||||||
|
|
||||||
# Denormalization (this assumes only one logo)
|
# Denormalization (this assumes only one logo)
|
||||||
sponsor_logo = models.ForeignKey("SponsorBenefit", related_name="+", null=True, blank=True,
|
sponsor_logo = models.ForeignKey(
|
||||||
editable=False, verbose_name=_("Sponsor logo"))
|
"SponsorBenefit",
|
||||||
|
related_name="+",
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
verbose_name=_("Sponsor logo"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
|
||||||
# Whether things are complete
|
# Whether things are complete
|
||||||
# True = complete, False = incomplate, Null = n/a for this sponsor level
|
# True = complete, False = incomplate, Null = n/a for this sponsor level
|
||||||
|
@ -242,8 +264,18 @@ class Benefit(models.Model):
|
||||||
|
|
||||||
class BenefitLevel(models.Model):
|
class BenefitLevel(models.Model):
|
||||||
|
|
||||||
benefit = models.ForeignKey(Benefit, related_name="benefit_levels", verbose_name=_("Benefit"))
|
benefit = models.ForeignKey(
|
||||||
level = models.ForeignKey(SponsorLevel, related_name="benefit_levels", verbose_name=_("Level"))
|
Benefit,
|
||||||
|
related_name="benefit_levels",
|
||||||
|
verbose_name=_("Benefit"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
level = models.ForeignKey(
|
||||||
|
SponsorLevel,
|
||||||
|
related_name="benefit_levels",
|
||||||
|
verbose_name=_("Level"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
|
||||||
# default limits for this benefit at given level
|
# default limits for this benefit at given level
|
||||||
max_words = models.PositiveIntegerField(_("Max words"), blank=True, null=True)
|
max_words = models.PositiveIntegerField(_("Max words"), blank=True, null=True)
|
||||||
|
@ -260,8 +292,18 @@ class BenefitLevel(models.Model):
|
||||||
|
|
||||||
class SponsorBenefit(models.Model):
|
class SponsorBenefit(models.Model):
|
||||||
|
|
||||||
sponsor = models.ForeignKey(Sponsor, related_name="sponsor_benefits", verbose_name=_("Sponsor"))
|
sponsor = models.ForeignKey(
|
||||||
benefit = models.ForeignKey(Benefit, related_name="sponsor_benefits", verbose_name=_("Benefit"))
|
Sponsor,
|
||||||
|
related_name="sponsor_benefits",
|
||||||
|
verbose_name=_("Sponsor"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
benefit = models.ForeignKey(
|
||||||
|
Benefit,
|
||||||
|
related_name="sponsor_benefits",
|
||||||
|
verbose_name=_("Benefit"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
active = models.BooleanField(default=True, verbose_name=_("Active"))
|
active = models.BooleanField(default=True, verbose_name=_("Active"))
|
||||||
|
|
||||||
# Limits: will initially be set to defaults from corresponding BenefitLevel
|
# Limits: will initially be set to defaults from corresponding BenefitLevel
|
||||||
|
|
8
vendor/symposion/sponsorship/tests.py
vendored
8
vendor/symposion/sponsorship/tests.py
vendored
|
@ -1,20 +1,22 @@
|
||||||
from cStringIO import StringIO
|
from io import StringIO
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth import get_user_model
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.urlresolvers import reverse
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.test.utils import override_settings
|
from django.test.utils import override_settings
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
from pycon.sponsorship.models import Benefit, Sponsor, SponsorBenefit,\
|
from pycon.sponsorship.models import Benefit, Sponsor, SponsorBenefit,\
|
||||||
SponsorLevel
|
SponsorLevel
|
||||||
from symposion.conference.models import current_conference
|
from symposion.conference.models import current_conference
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
class TestSponsorZipDownload(TestCase):
|
class TestSponsorZipDownload(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
4
vendor/symposion/teams/backends.py
vendored
4
vendor/symposion/teams/backends.py
vendored
|
@ -5,7 +5,7 @@ from .models import Team
|
||||||
|
|
||||||
class TeamPermissionsBackend(object):
|
class TeamPermissionsBackend(object):
|
||||||
|
|
||||||
def authenticate(self, username=None, password=None):
|
def authenticate(self, request, username=None, password=None):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_team_permissions(self, user_obj, obj=None):
|
def get_team_permissions(self, user_obj, obj=None):
|
||||||
|
@ -13,7 +13,7 @@ class TeamPermissionsBackend(object):
|
||||||
Returns a set of permission strings that this user has through his/her
|
Returns a set of permission strings that this user has through his/her
|
||||||
team memberships.
|
team memberships.
|
||||||
"""
|
"""
|
||||||
if user_obj.is_anonymous() or obj is not None:
|
if user_obj.is_anonymous or obj is not None:
|
||||||
return set()
|
return set()
|
||||||
if not hasattr(user_obj, "_team_perm_cache"):
|
if not hasattr(user_obj, "_team_perm_cache"):
|
||||||
# Member permissions
|
# Member permissions
|
||||||
|
|
4
vendor/symposion/teams/forms.py
vendored
4
vendor/symposion/teams/forms.py
vendored
|
@ -4,10 +4,12 @@ from django.utils.html import escape
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth import get_user_model
|
||||||
|
|
||||||
from symposion.teams.models import Membership
|
from symposion.teams.models import Membership
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
class TeamInvitationForm(forms.Form):
|
class TeamInvitationForm(forms.Form):
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
import datetime
|
import datetime
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
@ -44,11 +45,11 @@ class Migration(migrations.Migration):
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='membership',
|
model_name='membership',
|
||||||
name='team',
|
name='team',
|
||||||
field=models.ForeignKey(verbose_name='Team', to='teams.Team', related_name='memberships'),
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, verbose_name='Team', to='teams.Team', related_name='memberships'),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='membership',
|
model_name='membership',
|
||||||
name='user',
|
name='user',
|
||||||
field=models.ForeignKey(verbose_name='User', to=settings.AUTH_USER_MODEL, related_name='memberships'),
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, verbose_name='User', to=settings.AUTH_USER_MODEL, related_name='memberships'),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
25
vendor/symposion/teams/models.py
vendored
25
vendor/symposion/teams/models.py
vendored
|
@ -2,11 +2,15 @@ import datetime
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
from django.contrib.auth.models import Permission, User
|
from django.contrib.auth.models import Permission
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
|
||||||
from reversion import revisions as reversion
|
from reversion import revisions as reversion
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
TEAM_ACCESS_CHOICES = [
|
TEAM_ACCESS_CHOICES = [
|
||||||
("open", _("open")),
|
("open", _("open")),
|
||||||
|
@ -36,9 +40,8 @@ class Team(models.Model):
|
||||||
created = models.DateTimeField(default=datetime.datetime.now,
|
created = models.DateTimeField(default=datetime.datetime.now,
|
||||||
editable=False, verbose_name=_("Created"))
|
editable=False, verbose_name=_("Created"))
|
||||||
|
|
||||||
@models.permalink
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return ("team_detail", [self.slug])
|
return reverse("team_detail", args=[self.slug])
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
@ -78,10 +81,18 @@ MEMBERSHIP_STATE_CHOICES = [
|
||||||
|
|
||||||
class Membership(models.Model):
|
class Membership(models.Model):
|
||||||
|
|
||||||
user = models.ForeignKey(User, related_name="memberships",
|
user = models.ForeignKey(
|
||||||
verbose_name=_("User"))
|
User,
|
||||||
team = models.ForeignKey(Team, related_name="memberships",
|
related_name="memberships",
|
||||||
verbose_name=_("Team"))
|
verbose_name=_("User"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
team = models.ForeignKey(
|
||||||
|
Team,
|
||||||
|
related_name="memberships",
|
||||||
|
verbose_name=_("Team"),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
state = models.CharField(max_length=20, choices=MEMBERSHIP_STATE_CHOICES,
|
state = models.CharField(max_length=20, choices=MEMBERSHIP_STATE_CHOICES,
|
||||||
verbose_name=_("State"))
|
verbose_name=_("State"))
|
||||||
message = models.TextField(blank=True, verbose_name=_("Message"))
|
message = models.TextField(blank=True, verbose_name=_("Message"))
|
||||||
|
|
2
vendor/symposion/utils/mail.py
vendored
2
vendor/symposion/utils/mail.py
vendored
|
@ -9,7 +9,7 @@ from django.contrib.sites.models import Site
|
||||||
|
|
||||||
|
|
||||||
class Sender(object):
|
class Sender(object):
|
||||||
''' Class for sending e-mails under a templete prefix. '''
|
''' Class for sending e-mails under a template prefix. '''
|
||||||
|
|
||||||
def __init__(self, template_prefix):
|
def __init__(self, template_prefix):
|
||||||
self.template_prefix = template_prefix
|
self.template_prefix = template_prefix
|
||||||
|
|
Loading…
Reference in a new issue