Compare commits

...

73 Commits

Author SHA1 Message Date
Matthew Smith
8ca55f2696 Added migration for name change 2020-01-22 03:06:29 +00:00
Matthew Smith
228592a0f3 Creating an invoice now appears in its history. Rudimentary tracking of payments is also implemented 2020-01-22 02:37:39 +00:00
Tom Price
1be1b1abd7 Add invoice versioning to templates. 2018-05-15 17:42:13 +01:00
Johnathan Graydon
42e1931e72 Add revision history to invoices & payments 2018-05-14 15:57:06 +01:00
David Taylor
e81af9e479 Merge pull request #335 from nottinghamtec/requires-io-master
[requires.io] dependency update on master branch
2018-05-08 17:57:11 +01:00
requires.io
efab8c8cef [requires.io] dependency update 2018-05-08 16:41:37 +01:00
requires.io
3f7531e157 [requires.io] dependency update 2018-05-02 03:12:55 +01:00
requires.io
988f3dced4 [requires.io] dependency update 2018-04-30 19:49:11 +01:00
requires.io
bd3240c2bc [requires.io] dependency update 2018-04-28 20:25:35 +01:00
requires.io
7fbbe2871f [requires.io] dependency update 2018-04-22 00:34:34 +01:00
requires.io
109ece508b [requires.io] dependency update 2018-04-19 07:36:06 +01:00
requires.io
971144c2e6 [requires.io] dependency update 2018-04-18 11:16:00 +01:00
David Taylor
a3c6edda0b Merge pull request #334 from nottinghamtec/requires-io-master
[requires.io] dependency update on master branch
2018-04-16 23:59:36 +01:00
requires.io
71bb4696b8 [requires.io] dependency update 2018-04-16 23:19:10 +01:00
requires.io
2a3ed0b763 [requires.io] dependency update 2018-04-12 01:29:58 +01:00
requires.io
632fa56353 [requires.io] dependency update 2018-04-11 06:08:19 +01:00
requires.io
f3020fc783 [requires.io] dependency update 2018-04-10 19:16:12 +01:00
requires.io
9fdf5e674e [requires.io] dependency update 2018-04-10 12:08:43 +01:00
requires.io
cfe03a8628 [requires.io] dependency update 2018-04-10 05:17:39 +01:00
requires.io
eccf224b63 [requires.io] dependency update 2018-04-03 04:33:32 +01:00
requires.io
0b2c86ebb5 [requires.io] dependency update 2018-04-03 00:19:18 +01:00
David Taylor
f616857131 Merge pull request #328 from nottinghamtec/django2
Upgrade to Django 2
2018-04-02 21:36:10 +01:00
David Taylor
60fb90a50c Merge pull request #333 from nottinghamtec/hotfix/fix-jonos-commit
Remove un-necessary use of reversion
2018-03-26 19:46:06 +01:00
David Taylor
66f024e961 Remove un-necessary use of reversion 2018-03-26 19:41:13 +01:00
Johnathan Graydon
06daacf611 Automatically set event to booked when the client authorises it (#332)
* Automatically set rig to booked when event is authorised
Will close #320
2018-03-26 14:51:42 +01:00
Johnathan Graydon
c74bc945b6 Not error if no person
Will close #330
2018-03-26 14:09:51 +01:00
Johnathan Graydon
3c605d2976 Fix pep8 2018-03-25 15:30:05 +01:00
Johnathan Graydon
9720066fd7 Remove checked in by on event duplication
Will close #327
2018-03-25 15:30:05 +01:00
Johnathan Graydon
b157e3b187 Add 127.0.0.1 to Allowed_Hosts for debug 2018-03-25 15:30:05 +01:00
David Taylor
19030fdf2f Use django-widget-tweaks from GitHub until latest version is on PyPI
See https://github.com/jazzband/django-widget-tweaks/issues/62
2018-03-25 00:48:17 +00:00
David Taylor
42450b5a22 User.is_authenticated is no longer callable 2018-03-25 00:28:37 +00:00
David Taylor
ce11df9bbc Rename MIDDLEWARE_CLASSES to MIDDLEWARE 2018-03-25 00:21:30 +00:00
David Taylor
82e664c5e0 SessionAuthenticationMiddleware is no longer required (as of Django 1.10) 2018-03-25 00:21:15 +00:00
David Taylor
8098b33698 Migrate profile to have longer last_name field (Django 2.0 updated AbstractUser model) 2018-03-25 00:20:51 +00:00
David Taylor
9c2603557c Merge pull request #324 from nottinghamtec/hotfix/auth-request
Fix null person on authorisation request
2018-03-25 00:01:05 +00:00
David Taylor
f4209f21dc Remove include( from admin.site.urls 2018-03-24 23:58:54 +00:00
David Taylor
1e3c021a76 Add on_delete=models.CASCADE to old migrations 2018-03-24 23:58:54 +00:00
David Taylor
d8f9256252 Add on_delete=models.CASCADE to OneToOneFields 2018-03-24 23:58:54 +00:00
David Taylor
014bab6c1f Add on_delete=models.CASCADE to all foreign keys. This replicates the previous default behaviour 2018-03-24 23:58:54 +00:00
David Taylor
8872084cab Import URL functions from django.urls 2018-03-24 23:58:39 +00:00
David Taylor
76ceb15000 Bump versions 2018-03-24 23:58:07 +00:00
Johnathan Graydon
7dff951f28 Fix null person on authorisation request
Will close #319
2018-03-24 23:54:03 +00:00
David Taylor
05feb7df1c Merge pull request #325 from nottinghamtec/travis-fix
Bump chrome and chromedriver, update recaptcha keys, add --no-sandbox to chrome
2018-03-24 23:52:43 +00:00
David Taylor
ad3b38d222 Use new RECAPTCHA testing keys 2018-03-24 23:45:43 +00:00
David Taylor
a26e65073c Add no sandbox flag
See https://github.com/travis-ci/docs-travis-ci-com/pull/1671 for more info
2018-03-24 22:19:10 +00:00
David Taylor
7f3d628d01 Bump selenium 2018-03-12 18:06:49 +00:00
David Taylor
abdf785723 Bump chrome and chromedriver 2018-03-12 18:06:13 +00:00
David Taylor
85edba03a2 Merge pull request #315 from nottinghamtec/requires-io-master
[requires.io] dependency update on master branch
2017-11-29 15:03:28 +00:00
David Taylor
d61b21df0a Merge branch 'master' into requires-io-master 2017-11-29 14:56:00 +00:00
Johnathan Graydon
7e68dfb851 Fix hover text on invoice page 2017-11-29 14:40:11 +00:00
requires.io
69cbac31e7 [requires.io] dependency update 2017-11-27 09:21:59 +00:00
requires.io
ce4e0f5630 [requires.io] dependency update 2017-11-24 19:19:49 +00:00
requires.io
c99c5d573f [requires.io] dependency update 2017-11-24 02:55:03 +00:00
requires.io
221ef739b9 [requires.io] dependency update 2017-11-17 02:49:10 +00:00
requires.io
aa98039c35 [requires.io] dependency update 2017-11-15 18:16:25 +00:00
requires.io
7ef923b89f [requires.io] dependency update 2017-11-13 19:53:55 +00:00
requires.io
9ac86a6ad0 [requires.io] dependency update 2017-11-08 13:25:37 +00:00
requires.io
c0c143a166 [requires.io] dependency update 2017-11-08 13:09:23 +00:00
requires.io
0abfa2fd0c [requires.io] dependency update 2017-11-07 09:19:06 +00:00
requires.io
3333b29f24 [requires.io] dependency update 2017-11-05 19:41:14 +00:00
requires.io
880509d611 [requires.io] dependency update 2017-11-04 08:27:51 +00:00
requires.io
387f5b0d8e [requires.io] dependency update 2017-11-03 01:15:17 +00:00
requires.io
27b12d6bf4 [requires.io] dependency update 2017-11-02 02:27:15 +00:00
requires.io
c511f2f528 [requires.io] dependency update 2017-10-30 14:24:44 +00:00
requires.io
a61165f301 [requires.io] dependency update 2017-10-29 19:18:00 +00:00
requires.io
98245939fe [requires.io] dependency update 2017-10-24 21:49:12 +01:00
requires.io
b203832f79 [requires.io] dependency update 2017-10-13 18:30:28 +01:00
requires.io
c6846b85c7 [requires.io] dependency update 2017-10-05 19:35:42 +01:00
requires.io
0c15718d31 [requires.io] dependency update 2017-10-04 16:39:53 +01:00
requires.io
0f1db22452 [requires.io] dependency update 2017-10-02 16:39:04 +01:00
requires.io
e3970929e4 [requires.io] dependency update 2017-09-27 08:30:01 +01:00
requires.io
a64bf8e16f [requires.io] dependency update 2017-09-25 23:43:31 +01:00
David Taylor
cf8edc8a1c Merge pull request #314 from nottinghamtec/hotfix/ical
Fix ical end dates being wrong by 24 hours
2017-09-25 23:16:54 +01:00
30 changed files with 207 additions and 128 deletions

View File

@@ -4,10 +4,10 @@ python:
cache: pip cache: pip
addons: addons:
chrome: beta chrome: stable
install: install:
- wget http://chromedriver.storage.googleapis.com/2.32/chromedriver_linux64.zip - wget https://chromedriver.storage.googleapis.com/2.36/chromedriver_linux64.zip
- unzip chromedriver_linux64.zip - unzip chromedriver_linux64.zip
- export PATH=$PATH:$(pwd) - export PATH=$PATH:$(pwd)
- chmod +x chromedriver - chmod +x chromedriver

View File

@@ -1,7 +1,7 @@
from django.contrib.auth import REDIRECT_FIELD_NAME from django.contrib.auth import REDIRECT_FIELD_NAME
from django.shortcuts import render from django.shortcuts import render
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse from django.urls import reverse
from RIGS import models from RIGS import models
@@ -23,7 +23,7 @@ def user_passes_test_with_403(test_func, login_url=None, oembed_view=None):
def _checklogin(request, *args, **kwargs): def _checklogin(request, *args, **kwargs):
if test_func(request.user): if test_func(request.user):
return view_func(request, *args, **kwargs) return view_func(request, *args, **kwargs)
elif not request.user.is_authenticated(): elif not request.user.is_authenticated:
if oembed_view is not None: if oembed_view is not None:
context = {} context = {}
context['oembed_url'] = "{0}://{1}{2}".format(request.scheme, request.META['HTTP_HOST'], reverse(oembed_view, kwargs=kwargs)) context['oembed_url'] = "{0}://{1}{2}".format(request.scheme, request.META['HTTP_HOST'], reverse(oembed_view, kwargs=kwargs))

View File

@@ -35,6 +35,7 @@ if STAGING:
if DEBUG: if DEBUG:
ALLOWED_HOSTS.append('localhost') ALLOWED_HOSTS.append('localhost')
ALLOWED_HOSTS.append('example.com') ALLOWED_HOSTS.append('example.com')
ALLOWED_HOSTS.append('127.0.0.1')
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
if not DEBUG: if not DEBUG:
@@ -65,7 +66,7 @@ INSTALLED_APPS = (
'raven.contrib.django.raven_compat', 'raven.contrib.django.raven_compat',
) )
MIDDLEWARE_CLASSES = ( MIDDLEWARE = (
'raven.contrib.django.raven_compat.middleware.SentryResponseErrorIdMiddleware', 'raven.contrib.django.raven_compat.middleware.SentryResponseErrorIdMiddleware',
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
'debug_toolbar.middleware.DebugToolbarMiddleware', 'debug_toolbar.middleware.DebugToolbarMiddleware',
@@ -74,7 +75,6 @@ MIDDLEWARE_CLASSES = (
'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',
'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',
) )
@@ -162,8 +162,8 @@ LOGOUT_URL = '/user/logout/'
ACCOUNT_ACTIVATION_DAYS = 7 ACCOUNT_ACTIVATION_DAYS = 7
# reCAPTCHA settings # reCAPTCHA settings
RECAPTCHA_PUBLIC_KEY = os.environ.get('RECAPTCHA_PUBLIC_KEY', None) RECAPTCHA_PUBLIC_KEY = os.environ.get('RECAPTCHA_PUBLIC_KEY', "6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI") # If not set, use development key
RECAPTCHA_PRIVATE_KEY = os.environ.get('RECAPTCHA_PRIVATE_KEY', None) RECAPTCHA_PRIVATE_KEY = os.environ.get('RECAPTCHA_PRIVATE_KEY', "6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe") # If not set, use development key
NOCAPTCHA = True NOCAPTCHA = True
# Email # Email

View File

@@ -17,7 +17,7 @@ urlpatterns = [
url('^user/', include('django.contrib.auth.urls')), url('^user/', include('django.contrib.auth.urls')),
url('^user/', include('registration.backends.default.urls')), url('^user/', include('registration.backends.default.urls')),
url(r'^admin/', include(admin.site.urls)), url(r'^admin/', admin.site.urls),
] ]
if settings.DEBUG: if settings.DEBUG:

View File

@@ -1,25 +1,24 @@
from django.contrib import admin from django.contrib import admin
from RIGS import models, forms
from django.contrib.auth.admin import UserAdmin
from django.utils.translation import ugettext_lazy as _
from reversion.admin import VersionAdmin
from django.contrib.admin import helpers
from django.template.response import TemplateResponse
from django.contrib import messages from django.contrib import messages
from django.db import transaction from django.contrib.admin import helpers
from django.contrib.auth.admin import UserAdmin
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.db import transaction
from django.db.models import Count from django.db.models import Count
from django.forms import ModelForm from django.forms import ModelForm
from django.template.response import TemplateResponse
from django.utils.translation import ugettext_lazy as _
from reversion import revisions as reversion from reversion import revisions as reversion
from reversion.admin import VersionAdmin
from RIGS import models, forms
# Register your models here. # Register your models here.
admin.site.register(models.VatRate, VersionAdmin) admin.site.register(models.VatRate, VersionAdmin)
admin.site.register(models.Event, VersionAdmin) admin.site.register(models.Event, VersionAdmin)
admin.site.register(models.EventItem, VersionAdmin) admin.site.register(models.EventItem, VersionAdmin)
admin.site.register(models.Invoice) admin.site.register(models.Invoice, VersionAdmin)
admin.site.register(models.Payment) admin.site.register(models.Payment, VersionAdmin)
@admin.register(models.Profile) @admin.register(models.Profile)

View File

@@ -2,7 +2,7 @@ import datetime
import re import re
from django.contrib import messages from django.contrib import messages
from django.core.urlresolvers import reverse_lazy from django.urls import reverse_lazy
from django.http import Http404, HttpResponseRedirect from django.http import Http404, HttpResponseRedirect
from django.http import HttpResponse from django.http import HttpResponse
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
@@ -10,8 +10,9 @@ from django.template import RequestContext
from django.template.loader import get_template from django.template.loader import get_template
from django.views import generic from django.views import generic
from django.db.models import Q from django.db.models import Q
from django.db import transaction
from z3c.rml import rml2pdf from z3c.rml import rml2pdf
import reversion
from RIGS import models from RIGS import models
from django import forms from django import forms
@@ -101,14 +102,14 @@ class InvoiceDelete(generic.DeleteView):
def get(self, request, pk): def get(self, request, pk):
obj = self.get_object() obj = self.get_object()
if obj.payment_set.all().count() > 0: if obj.payments.all().count() > 0:
messages.info(self.request, 'To delete an invoice, delete the payments first.') messages.info(self.request, 'To delete an invoice, delete the payments first.')
return HttpResponseRedirect(reverse_lazy('invoice_detail', kwargs={'pk': obj.pk})) return HttpResponseRedirect(reverse_lazy('invoice_detail', kwargs={'pk': obj.pk}))
return super(InvoiceDelete, self).get(pk) return super(InvoiceDelete, self).get(pk)
def post(self, request, pk): def post(self, request, pk):
obj = self.get_object() obj = self.get_object()
if obj.payment_set.all().count() > 0: if obj.payments.all().count() > 0:
messages.info(self.request, 'To delete an invoice, delete the payments first.') messages.info(self.request, 'To delete an invoice, delete the payments first.')
return HttpResponseRedirect(reverse_lazy('invoice_detail', kwargs={'pk': obj.pk})) return HttpResponseRedirect(reverse_lazy('invoice_detail', kwargs={'pk': obj.pk}))
return super(InvoiceDelete, self).post(pk) return super(InvoiceDelete, self).post(pk)
@@ -159,7 +160,10 @@ class InvoiceWaiting(generic.ListView):
class InvoiceEvent(generic.View): class InvoiceEvent(generic.View):
@transaction.atomic()
@reversion.create_revision()
def get(self, *args, **kwargs): def get(self, *args, **kwargs):
reversion.set_user(self.request.user)
epk = kwargs.get('pk') epk = kwargs.get('pk')
event = models.Event.objects.get(pk=epk) event = models.Event.objects.get(pk=epk)
invoice, created = models.Invoice.objects.get_or_create(event=event) invoice, created = models.Invoice.objects.get_or_create(event=event)
@@ -184,6 +188,13 @@ class PaymentCreate(generic.CreateView):
initial.update({'invoice': invoice}) initial.update({'invoice': invoice})
return initial return initial
@transaction.atomic()
@reversion.create_revision()
def form_valid(self, form, *args, **kwargs):
reversion.add_to_revision(form.cleaned_data['invoice'])
reversion.set_comment("Payment removed")
return super().form_valid(form, *args, **kwargs)
def get_success_url(self): def get_success_url(self):
messages.info(self.request, "location.reload()") messages.info(self.request, "location.reload()")
return reverse_lazy('closemodal') return reverse_lazy('closemodal')
@@ -192,5 +203,12 @@ class PaymentCreate(generic.CreateView):
class PaymentDelete(generic.DeleteView): class PaymentDelete(generic.DeleteView):
model = models.Payment model = models.Payment
@transaction.atomic()
@reversion.create_revision()
def delete(self, *args, **kwargs):
reversion.add_to_revision(self.get_object().invoice)
reversion.set_comment("Payment removed")
return super().delete(*args, **kwargs)
def get_success_url(self): def get_success_url(self):
return self.request.POST.get('next') return self.request.POST.get('next')

View File

@@ -1,7 +1,7 @@
from RIGS import models, forms from RIGS import models, forms
from django_ical.views import ICalFeed from django_ical.views import ICalFeed
from django.db.models import Q from django.db.models import Q
from django.core.urlresolvers import reverse_lazy, reverse, NoReverseMatch from django.urls import reverse_lazy, reverse, NoReverseMatch
from django.utils import timezone from django.utils import timezone
from django.conf import settings from django.conf import settings

View File

@@ -18,7 +18,7 @@ class Migration(migrations.Migration):
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('postedAt', models.DateTimeField(auto_now=True)), ('postedAt', models.DateTimeField(auto_now=True)),
('message', models.TextField()), ('message', models.TextField()),
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)), ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
], ],
options={ options={
}, },

View File

@@ -33,11 +33,11 @@ class Migration(migrations.Migration):
('payment_method', models.CharField(blank=True, null=True, max_length=255)), ('payment_method', models.CharField(blank=True, null=True, max_length=255)),
('payment_received', models.CharField(blank=True, null=True, max_length=255)), ('payment_received', models.CharField(blank=True, null=True, max_length=255)),
('purchase_order', models.CharField(blank=True, null=True, max_length=255)), ('purchase_order', models.CharField(blank=True, null=True, max_length=255)),
('based_on', models.ForeignKey(to='RIGS.Event', related_name='future_events')), ('based_on', models.ForeignKey(to='RIGS.Event', related_name='future_events', on_delete=models.CASCADE)),
('checked_in_by', models.ForeignKey(to=settings.AUTH_USER_MODEL, related_name='event_checked_in')), ('checked_in_by', models.ForeignKey(to=settings.AUTH_USER_MODEL, related_name='event_checked_in', on_delete=models.CASCADE)),
('mic', models.ForeignKey(to=settings.AUTH_USER_MODEL, related_name='event_mic')), ('mic', models.ForeignKey(to=settings.AUTH_USER_MODEL, related_name='event_mic', on_delete=models.CASCADE)),
('organisation', models.ForeignKey(to='RIGS.Organisation')), ('organisation', models.ForeignKey(to='RIGS.Organisation', on_delete=models.CASCADE)),
('person', models.ForeignKey(to='RIGS.Person')), ('person', models.ForeignKey(to='RIGS.Person', on_delete=models.CASCADE)),
], ],
options={ options={
}, },
@@ -52,7 +52,7 @@ class Migration(migrations.Migration):
('quantity', models.IntegerField()), ('quantity', models.IntegerField()),
('cost', models.DecimalField(max_digits=10, decimal_places=2)), ('cost', models.DecimalField(max_digits=10, decimal_places=2)),
('order', models.IntegerField()), ('order', models.IntegerField()),
('event', models.ForeignKey(to='RIGS.Event', related_name='item')), ('event', models.ForeignKey(to='RIGS.Event', related_name='item', on_delete=models.CASCADE)),
], ],
options={ options={
}, },
@@ -75,7 +75,7 @@ class Migration(migrations.Migration):
migrations.AddField( migrations.AddField(
model_name='event', model_name='event',
name='venue', name='venue',
field=models.ForeignKey(to='RIGS.Venue'), field=models.ForeignKey(to='RIGS.Venue', on_delete=models.CASCADE),
preserve_default=True, preserve_default=True,
), ),
] ]

View File

@@ -14,26 +14,26 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name='event', model_name='event',
name='based_on', name='based_on',
field=models.ForeignKey(to='RIGS.Event', related_name='future_events', blank=True, null=True), field=models.ForeignKey(to='RIGS.Event', related_name='future_events', blank=True, null=True, on_delete=models.CASCADE),
preserve_default=True, preserve_default=True,
), ),
migrations.AlterField( migrations.AlterField(
model_name='event', model_name='event',
name='checked_in_by', name='checked_in_by',
field=models.ForeignKey(to=settings.AUTH_USER_MODEL, related_name='event_checked_in', blank=True, field=models.ForeignKey(to=settings.AUTH_USER_MODEL, related_name='event_checked_in', blank=True,
null=True), null=True, on_delete=models.CASCADE),
preserve_default=True, preserve_default=True,
), ),
migrations.AlterField( migrations.AlterField(
model_name='event', model_name='event',
name='mic', name='mic',
field=models.ForeignKey(to=settings.AUTH_USER_MODEL, related_name='event_mic', blank=True, null=True), field=models.ForeignKey(to=settings.AUTH_USER_MODEL, related_name='event_mic', blank=True, null=True, on_delete=models.CASCADE),
preserve_default=True, preserve_default=True,
), ),
migrations.AlterField( migrations.AlterField(
model_name='event', model_name='event',
name='organisation', name='organisation',
field=models.ForeignKey(to='RIGS.Organisation', blank=True, null=True), field=models.ForeignKey(to='RIGS.Organisation', blank=True, null=True, on_delete=models.CASCADE),
preserve_default=True, preserve_default=True,
), ),
migrations.AlterField( migrations.AlterField(

View File

@@ -19,8 +19,8 @@ class Migration(migrations.Migration):
('run', models.BooleanField(default=False)), ('run', models.BooleanField(default=False)),
('derig', models.BooleanField(default=False)), ('derig', models.BooleanField(default=False)),
('notes', models.TextField(blank=True, null=True)), ('notes', models.TextField(blank=True, null=True)),
('event', models.ForeignKey(related_name='crew', to='RIGS.Event')), ('event', models.ForeignKey(related_name='crew', to='RIGS.Event', on_delete=models.CASCADE)),
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)), ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
], ],
options={ options={
}, },
@@ -35,7 +35,7 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name='eventitem', model_name='eventitem',
name='event', name='event',
field=models.ForeignKey(related_name='items', to='RIGS.Event'), field=models.ForeignKey(related_name='items', to='RIGS.Event', on_delete=models.CASCADE),
preserve_default=True, preserve_default=True,
), ),
] ]

View File

@@ -14,7 +14,7 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name='event', model_name='event',
name='person', name='person',
field=models.ForeignKey(blank=True, null=True, to='RIGS.Person'), field=models.ForeignKey(blank=True, null=True, to='RIGS.Person', on_delete=models.CASCADE),
preserve_default=True, preserve_default=True,
), ),
] ]

View File

@@ -14,13 +14,13 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name='event', model_name='event',
name='venue', name='venue',
field=models.ForeignKey(blank=True, to='RIGS.Venue', null=True), field=models.ForeignKey(blank=True, to='RIGS.Venue', null=True, on_delete=models.CASCADE),
preserve_default=True, preserve_default=True,
), ),
migrations.AlterField( migrations.AlterField(
model_name='eventitem', model_name='eventitem',
name='event', name='event',
field=models.ForeignKey(related_name='items', blank=True, to='RIGS.Event'), field=models.ForeignKey(related_name='items', blank=True, to='RIGS.Event', on_delete=models.CASCADE),
preserve_default=True, preserve_default=True,
), ),
] ]

View File

@@ -18,7 +18,7 @@ class Migration(migrations.Migration):
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('invoice_date', models.DateField(auto_now_add=True)), ('invoice_date', models.DateField(auto_now_add=True)),
('void', models.BooleanField()), ('void', models.BooleanField()),
('event', models.OneToOneField(to='RIGS.Event')), ('event', models.OneToOneField(to='RIGS.Event', on_delete=models.CASCADE)),
], ],
options={ options={
}, },
@@ -31,7 +31,7 @@ class Migration(migrations.Migration):
('date', models.DateField()), ('date', models.DateField()),
('amount', models.DecimalField(help_text=b'Please use ex. VAT', max_digits=10, decimal_places=2)), ('amount', models.DecimalField(help_text=b'Please use ex. VAT', max_digits=10, decimal_places=2)),
('method', models.CharField(max_length=2, choices=[(b'C', b'Cash'), (b'I', b'Internal'), (b'E', b'External'), (b'SU', b'SU Core'), (b'M', b'Members')])), ('method', models.CharField(max_length=2, choices=[(b'C', b'Cash'), (b'I', b'Internal'), (b'E', b'External'), (b'SU', b'SU Core'), (b'M', b'Members')])),
('invoice', models.ForeignKey(to='RIGS.Invoice')), ('invoice', models.ForeignKey(to='RIGS.Invoice', on_delete=models.CASCADE)),
], ],
options={ options={
}, },
@@ -40,7 +40,7 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name='event', model_name='event',
name='mic', name='mic',
field=models.ForeignKey(related_name='event_mic', verbose_name=b'MIC', blank=True, to=settings.AUTH_USER_MODEL, null=True), field=models.ForeignKey(related_name='event_mic', verbose_name=b'MIC', blank=True, to=settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE),
preserve_default=True, preserve_default=True,
), ),
] ]

View File

@@ -21,7 +21,7 @@ class Migration(migrations.Migration):
('account_code', models.CharField(max_length=50, null=True, blank=True)), ('account_code', models.CharField(max_length=50, null=True, blank=True)),
('amount', models.DecimalField(verbose_name=b'authorisation amount', max_digits=10, decimal_places=2)), ('amount', models.DecimalField(verbose_name=b'authorisation amount', max_digits=10, decimal_places=2)),
('created_at', models.DateTimeField(auto_now_add=True)), ('created_at', models.DateTimeField(auto_now_add=True)),
('event', models.ForeignKey(related_name='authroisations', to='RIGS.Event')), ('event', models.ForeignKey(related_name='authroisations', to='RIGS.Event', on_delete=models.CASCADE)),
], ],
), ),
] ]

View File

@@ -14,6 +14,6 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name='eventauthorisation', model_name='eventauthorisation',
name='event', name='event',
field=models.OneToOneField(related_name='authorisation', to='RIGS.Event'), field=models.OneToOneField(related_name='authorisation', to='RIGS.Event', on_delete=models.CASCADE),
), ),
] ]

View File

@@ -15,7 +15,7 @@ class Migration(migrations.Migration):
migrations.AddField( migrations.AddField(
model_name='eventauthorisation', model_name='eventauthorisation',
name='sent_by', name='sent_by',
field=models.ForeignKey(default=1, to=settings.AUTH_USER_MODEL), field=models.ForeignKey(default=1, to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE),
preserve_default=False, preserve_default=False,
), ),
] ]

View File

@@ -20,7 +20,7 @@ class Migration(migrations.Migration):
migrations.AddField( migrations.AddField(
model_name='event', model_name='event',
name='auth_request_by', name='auth_request_by',
field=models.ForeignKey(blank=True, to=settings.AUTH_USER_MODEL, null=True), field=models.ForeignKey(blank=True, to=settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE),
), ),
migrations.AddField( migrations.AddField(
model_name='event', model_name='event',

View File

@@ -0,0 +1,18 @@
# Generated by Django 2.0.3 on 2018-03-25 00:16
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('RIGS', '0032_auto_20170904_2355'),
]
operations = [
migrations.AlterField(
model_name='profile',
name='last_name',
field=models.CharField(blank=True, max_length=150, verbose_name='last name'),
),
]

View File

@@ -0,0 +1,19 @@
# Generated by Django 2.0.13 on 2020-01-22 03:05
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('RIGS', '0033_auto_20180325_0016'),
]
operations = [
migrations.AlterField(
model_name='payment',
name='invoice',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='payments', to='RIGS.Invoice'),
),
]

View File

@@ -1,24 +1,21 @@
from collections import Counter
import datetime import datetime
import hashlib import hashlib
import datetime
import pytz import pytz
import random
from django.db import models import string
from django.contrib.auth.models import AbstractUser from decimal import Decimal
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import AbstractUser
from django.core.exceptions import ValidationError
from django.db import models
from django.urls import reverse_lazy
from django.utils import timezone from django.utils import timezone
from django.utils.functional import cached_property
from django.utils.encoding import python_2_unicode_compatible from django.utils.encoding import python_2_unicode_compatible
from django.utils.functional import cached_property
from reversion import revisions as reversion from reversion import revisions as reversion
from reversion.models import Version from reversion.models import Version
import string
import random
from collections import Counter
from decimal import Decimal
from django.core.exceptions import ValidationError
from django.core.urlresolvers import reverse_lazy
# Create your models here. # Create your models here.
@@ -302,9 +299,9 @@ class Event(models.Model, RevisionMixin):
) )
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
person = models.ForeignKey('Person', null=True, blank=True) person = models.ForeignKey('Person', null=True, blank=True, on_delete=models.CASCADE)
organisation = models.ForeignKey('Organisation', blank=True, null=True) organisation = models.ForeignKey('Organisation', blank=True, null=True, on_delete=models.CASCADE)
venue = models.ForeignKey('Venue', blank=True, null=True) venue = models.ForeignKey('Venue', blank=True, null=True, on_delete=models.CASCADE)
description = models.TextField(blank=True, null=True) description = models.TextField(blank=True, null=True)
notes = models.TextField(blank=True, null=True) notes = models.TextField(blank=True, null=True)
status = models.IntegerField(choices=EVENT_STATUS_CHOICES, default=PROVISIONAL) status = models.IntegerField(choices=EVENT_STATUS_CHOICES, default=PROVISIONAL)
@@ -323,9 +320,9 @@ class Event(models.Model, RevisionMixin):
meet_info = models.CharField(max_length=255, blank=True, null=True) meet_info = models.CharField(max_length=255, blank=True, null=True)
# Crew management # Crew management
checked_in_by = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='event_checked_in', blank=True, null=True) checked_in_by = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='event_checked_in', blank=True, null=True, on_delete=models.CASCADE)
mic = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='event_mic', blank=True, null=True, mic = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='event_mic', blank=True, null=True,
verbose_name="MIC") verbose_name="MIC", on_delete=models.CASCADE)
# Monies # Monies
payment_method = models.CharField(max_length=255, blank=True, null=True) payment_method = models.CharField(max_length=255, blank=True, null=True)
@@ -334,7 +331,7 @@ class Event(models.Model, RevisionMixin):
collector = models.CharField(max_length=255, blank=True, null=True, verbose_name='collected by') collector = models.CharField(max_length=255, blank=True, null=True, verbose_name='collected by')
# Authorisation request details # Authorisation request details
auth_request_by = models.ForeignKey('Profile', null=True, blank=True) auth_request_by = models.ForeignKey('Profile', null=True, blank=True, on_delete=models.CASCADE)
auth_request_at = models.DateTimeField(null=True, blank=True) auth_request_at = models.DateTimeField(null=True, blank=True)
auth_request_to = models.EmailField(null=True, blank=True) auth_request_to = models.EmailField(null=True, blank=True)
@@ -485,7 +482,7 @@ class Event(models.Model, RevisionMixin):
class EventItem(models.Model): class EventItem(models.Model):
event = models.ForeignKey('Event', related_name='items', blank=True) event = models.ForeignKey('Event', related_name='items', blank=True, on_delete=models.CASCADE)
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
description = models.TextField(blank=True, null=True) description = models.TextField(blank=True, null=True)
quantity = models.IntegerField() quantity = models.IntegerField()
@@ -504,8 +501,8 @@ class EventItem(models.Model):
class EventCrew(models.Model): class EventCrew(models.Model):
event = models.ForeignKey('Event', related_name='crew') event = models.ForeignKey('Event', related_name='crew', on_delete=models.CASCADE)
user = models.ForeignKey(settings.AUTH_USER_MODEL) user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
rig = models.BooleanField(default=False) rig = models.BooleanField(default=False)
run = models.BooleanField(default=False) run = models.BooleanField(default=False)
derig = models.BooleanField(default=False) derig = models.BooleanField(default=False)
@@ -514,13 +511,13 @@ class EventCrew(models.Model):
@reversion.register @reversion.register
class EventAuthorisation(models.Model, RevisionMixin): class EventAuthorisation(models.Model, RevisionMixin):
event = models.OneToOneField('Event', related_name='authorisation') event = models.OneToOneField('Event', related_name='authorisation', on_delete=models.CASCADE)
email = models.EmailField() email = models.EmailField()
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
uni_id = models.CharField(max_length=10, blank=True, null=True, verbose_name="University ID") uni_id = models.CharField(max_length=10, blank=True, null=True, verbose_name="University ID")
account_code = models.CharField(max_length=50, blank=True, null=True) account_code = models.CharField(max_length=50, blank=True, null=True)
amount = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="authorisation amount") amount = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="authorisation amount")
sent_by = models.ForeignKey('RIGS.Profile') sent_by = models.ForeignKey('RIGS.Profile', on_delete=models.CASCADE)
def get_absolute_url(self): def get_absolute_url(self):
return reverse_lazy('event_detail', kwargs={'pk': self.event.pk}) return reverse_lazy('event_detail', kwargs={'pk': self.event.pk})
@@ -530,9 +527,10 @@ class EventAuthorisation(models.Model, RevisionMixin):
return str("N%05d" % self.event.pk + ' (requested by ' + self.sent_by.initials + ')') return str("N%05d" % self.event.pk + ' (requested by ' + self.sent_by.initials + ')')
@reversion.register(follow=['payments'])
@python_2_unicode_compatible @python_2_unicode_compatible
class Invoice(models.Model): class Invoice(models.Model, RevisionMixin):
event = models.OneToOneField('Event') event = models.OneToOneField('Event', on_delete=models.CASCADE)
invoice_date = models.DateField(auto_now_add=True) invoice_date = models.DateField(auto_now_add=True)
void = models.BooleanField(default=False) void = models.BooleanField(default=False)
@@ -546,7 +544,7 @@ class Invoice(models.Model):
@property @property
def payment_total(self): def payment_total(self):
total = self.payment_set.aggregate(total=models.Sum('amount'))['total'] total = self.payments.aggregate(total=models.Sum('amount'))['total']
if total: if total:
return total return total
return Decimal("0.00") return Decimal("0.00")
@@ -584,7 +582,7 @@ class Payment(models.Model):
(ADJUSTMENT, 'TEC Adjustment'), (ADJUSTMENT, 'TEC Adjustment'),
) )
invoice = models.ForeignKey('Invoice') invoice = models.ForeignKey('Invoice', on_delete=models.CASCADE, related_name="payments")
date = models.DateField() date = models.DateField()
amount = models.DecimalField(max_digits=10, decimal_places=2, help_text='Please use ex. VAT') amount = models.DecimalField(max_digits=10, decimal_places=2, help_text='Please use ex. VAT')
method = models.CharField(max_length=2, choices=METHODS, null=True, blank=True) method = models.CharField(max_length=2, choices=METHODS, null=True, blank=True)

View File

@@ -6,12 +6,12 @@ import urllib.parse
from django.contrib.staticfiles.storage import staticfiles_storage from django.contrib.staticfiles.storage import staticfiles_storage
from django.core.mail import EmailMessage, EmailMultiAlternatives from django.core.mail import EmailMessage, EmailMultiAlternatives
from django.views import generic from django.views import generic
from django.core.urlresolvers import reverse_lazy from django.urls import reverse_lazy
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django.template import RequestContext from django.template import RequestContext
from django.template.loader import get_template from django.template.loader import get_template
from django.conf import settings from django.conf import settings
from django.core.urlresolvers import reverse from django.urls import reverse
from django.core import signing from django.core import signing
from django.http import HttpResponse from django.http import HttpResponse
from django.core.exceptions import SuspiciousOperation from django.core.exceptions import SuspiciousOperation
@@ -138,7 +138,11 @@ class EventDuplicate(EventUpdate):
old = super(EventDuplicate, self).get_object(queryset) # Get the object (the event you're duplicating) old = super(EventDuplicate, self).get_object(queryset) # Get the object (the event you're duplicating)
new = copy.copy(old) # Make a copy of the object in memory new = copy.copy(old) # Make a copy of the object in memory
new.based_on = old # Make the new event based on the old event new.based_on = old # Make the new event based on the old event
new.purchase_order = None new.purchase_order = None # Remove old PO
# Clear checked in by if it's a dry hire
if new.dry_hire is True:
new.checked_in_by = None
# Remove all the authorisation information from the new event # Remove all the authorisation information from the new event
new.auth_request_to = None new.auth_request_to = None
@@ -340,8 +344,10 @@ class EventAuthorisationRequest(generic.FormView, generic.detail.SingleObjectMix
'sent_by': self.request.user.pk, 'sent_by': self.request.user.pk,
}), }),
} }
if email == event.person.email: if event.person is not None and email == event.person.email:
context['to_name'] = event.person.name context['to_name'] = event.person.name
elif event.organisation is not None and email == event.organisation.email:
context['to_name'] = event.organisation.name
msg = EmailMultiAlternatives( msg = EmailMultiAlternatives(
"N%05d | %s - Event Authorisation Request" % (self.object.pk, self.object.name), "N%05d | %s - Event Authorisation Request" % (self.object.pk, self.object.name),

View File

@@ -50,8 +50,10 @@ def send_eventauthorisation_success_email(instance):
'object': instance, 'object': instance,
} }
if instance.email == instance.event.person.email: if instance.event.person is not None and instance.email == instance.event.person.email:
context['to_name'] = instance.event.person.name context['to_name'] = instance.event.person.name
elif instance.event.organisation is not None and instance.email == instance.event.organisation.email:
context['to_name'] = instance.event.organisation.name
subject = "N%05d | %s - Event Authorised" % (instance.event.pk, instance.event.name) subject = "N%05d | %s - Event Authorised" % (instance.event.pk, instance.event.name)
@@ -89,6 +91,10 @@ def send_eventauthorisation_success_email(instance):
client_email.send(fail_silently=True) client_email.send(fail_silently=True)
mic_email.send(fail_silently=True) mic_email.send(fail_silently=True)
# Set event to booked now that it's authorised
instance.event.status = models.Event.BOOKED
instance.event.save()
def on_revision_commit(sender, instance, created, **kwargs): def on_revision_commit(sender, instance, created, **kwargs):
if created: if created:

View File

@@ -264,7 +264,7 @@
</para> </para>
</td> </td>
</tr> </tr>
{% for payment in object.invoice.payment_set.all %} {% for payment in object.invoice.payments.all %}
<tr> <tr>
<td>{{ payment.get_method_display }}</td> <td>{{ payment.get_method_display }}</td>
<td>{{ payment.date }}</td> <td>{{ payment.date }}</td>

View File

@@ -6,20 +6,21 @@
<div class="col-sm-12"> <div class="col-sm-12">
<div class="row"> <div class="row">
<div class="col-sm-8"> <div class="col-sm-8">
<h2>Invoice {{ object.pk }} ({{ object.invoice_date|date:"d/m/Y"}})</h2> <h2>Invoice {{ object.pk }} ({{ object.invoice_date|date:"d/m/Y" }})</h2>
</div> </div>
<div class="col-sm-4 text-right"> <div class="col-sm-4 text-right">
<div class="btn-group btn-page"> <div class="btn-group btn-page">
<a href="{% url 'invoice_delete' object.pk %}" class="btn btn-default" title="Void Invoice"> <a href="{% url 'invoice_delete' object.pk %}" class="btn btn-default" title="Delete Invoice">
<span class="glyphicon glyphicon-remove"></span> <span <span class="glyphicon glyphicon-remove"></span> <span
class="hidden-xs">Delete</span> class="hidden-xs">Delete</span>
</a> </a>
<a href="{% url 'invoice_void' object.pk %}" class="btn btn-default" title="Void Invoice"> <a href="{% url 'invoice_void' object.pk %}" class="btn btn-default" title="Void Invoice">
<span class="glyphicon glyphicon-ban-circle"></span> <span <span class="glyphicon glyphicon-ban-circle"></span> <span
class="hidden-xs">Void</span> class="hidden-xs">Void</span>
</a> </a>
<a href="{% url 'invoice_print' object.pk %}" target="_blank" class="btn btn-default"><span <a href="{% url 'invoice_print' object.pk %}" target="_blank" title="Print Invoice"
class="btn btn-default"><span
class="glyphicon glyphicon-print"></span> <span class="glyphicon glyphicon-print"></span> <span
class="hidden-xs">Print</span></a> class="hidden-xs">Print</span></a>
</div> </div>
@@ -83,9 +84,11 @@
<dt>Authorised by</dt> <dt>Authorised by</dt>
<dd> <dd>
{% if object.event.authorised %} {% if object.event.authorised %}
{{ object.event.authorisation.name }} {{ object.event.authorisation.name }}
(<a href="mailto:{{ object.event.authorisation.email }}">{{ object.event.authorisation.email }}</a>) (
<a href="mailto:{{ object.event.authorisation.email }}">{{ object.event.authorisation.email }}</a>
)
{% endif %} {% endif %}
</dd> </dd>
@@ -140,7 +143,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for payment in object.payment_set.all %} {% for payment in object.payments.all %}
<tr> <tr>
<td>{{ payment.date }}</td> <td>{{ payment.date }}</td>
<td>{{ payment.amount|floatformat:2 }}</td> <td>{{ payment.amount|floatformat:2 }}</td>
@@ -172,6 +175,13 @@
</div> </div>
</div> </div>
</div> </div>
</div>
<div class="col-sm-12 text-right">
<div>
<a href="{% url 'invoice_history' object.pk %}" title="View Revision History">
Last edited at {{ object.last_edited_at }} by {{ object.last_edited_by.name }}
</a>
</div>
</div> </div>
{% endblock %} {% endblock %}

View File

@@ -18,7 +18,7 @@ from selenium.webdriver.support.ui import WebDriverWait
from RIGS import models from RIGS import models
from reversion import revisions as reversion from reversion import revisions as reversion
from django.core.urlresolvers import reverse from django.urls import reverse
from django.core import mail, signing from django.core import mail, signing
@@ -32,6 +32,7 @@ def create_browser():
options.add_argument("--window-size=1920,1080") options.add_argument("--window-size=1920,1080")
if os.environ.get('CI', False): if os.environ.get('CI', False):
options.add_argument("--headless") options.add_argument("--headless")
options.add_argument("--no-sandbox")
driver = webdriver.Chrome(chrome_options=options) driver = webdriver.Chrome(chrome_options=options)
return driver return driver

View File

@@ -2,7 +2,7 @@ from datetime import date
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.core.management import call_command from django.core.management import call_command
from django.core.urlresolvers import reverse from django.urls 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

View File

@@ -1,13 +1,12 @@
from django.conf.urls import url from django.conf.urls import url
from django.contrib.auth.views import password_reset
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from RIGS import models, views, rigboard, finance, ical, versioning, forms from django.contrib.auth.views import password_reset
from django.views.generic import RedirectView
from django.views.decorators.clickjacking import xframe_options_exempt from django.views.decorators.clickjacking import xframe_options_exempt
from django.views.generic import RedirectView
from PyRIGS.decorators import permission_required_with_403
from PyRIGS.decorators import api_key_required from PyRIGS.decorators import api_key_required
from PyRIGS.decorators import permission_required_with_403
from RIGS import models, views, rigboard, finance, ical, versioning, forms
urlpatterns = [ urlpatterns = [
# Examples: # Examples:
@@ -144,6 +143,10 @@ urlpatterns = [
url(r'^invoice/(?P<pk>\d+)/delete/$', url(r'^invoice/(?P<pk>\d+)/delete/$',
permission_required_with_403('RIGS.change_invoice')(finance.InvoiceDelete.as_view()), permission_required_with_403('RIGS.change_invoice')(finance.InvoiceDelete.as_view()),
name='invoice_delete'), name='invoice_delete'),
url(r'^invoice/(?P<pk>\d+)/history/$',
permission_required_with_403('RIGS.view_invoice')(versioning.VersionHistory.as_view()),
name='invoice_history', kwargs={'model': models.Invoice}),
url(r'^payment/create/$', url(r'^payment/create/$',
permission_required_with_403('RIGS.add_payment')(finance.PaymentCreate.as_view()), permission_required_with_403('RIGS.add_payment')(finance.PaymentCreate.as_view()),
name='payment_create'), name='payment_create'),

View File

@@ -1,7 +1,7 @@
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.http.response import HttpResponseRedirect from django.http.response import HttpResponseRedirect
from django.http import HttpResponse from django.http import HttpResponse
from django.core.urlresolvers import reverse_lazy, reverse, NoReverseMatch from django.urls import reverse_lazy, reverse, NoReverseMatch
from django.views import generic from django.views import generic
from django.db.models import Q from django.db.models import Q
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
@@ -34,7 +34,7 @@ class Index(generic.TemplateView):
def login(request, **kwargs): def login(request, **kwargs):
if request.user.is_authenticated(): if request.user.is_authenticated:
next = request.GET.get('next', '/') next = request.GET.get('next', '/')
return HttpResponseRedirect(next) return HttpResponseRedirect(next)
else: else:
@@ -49,7 +49,7 @@ def login(request, **kwargs):
# check for it before logging the user in # check for it before logging the user in
@csrf_exempt @csrf_exempt
def login_embed(request, **kwargs): def login_embed(request, **kwargs):
if request.user.is_authenticated(): if request.user.is_authenticated:
next = request.GET.get('next', '/') next = request.GET.get('next', '/')
return HttpResponseRedirect(next) return HttpResponseRedirect(next)
else: else:

View File

@@ -1,37 +1,38 @@
beautifulsoup4==4.6.0 beautifulsoup4==4.6.0
contextlib2==0.5.5 contextlib2==0.5.5
diff-match-patch==20121119 diff-match-patch==20121119
dj-database-url==0.4.2 dj-database-url==0.5.0
dj-static==0.0.6 dj-static==0.0.6
Django==1.11.5 Django==2.0.5
django-debug-toolbar==1.8 django-debug-toolbar==1.9.1
django-ical==1.4 django-ical==1.4
django-recaptcha==1.3.1 django-recaptcha==1.4.0
django-registration-redux==1.7 django-registration-redux==2.4
django-reversion==2.0.10 django-reversion==2.0.13
django-toolbelt==0.0.1 django-toolbelt==0.0.1
premailer==3.1.1 premailer==3.2.0
django-widget-tweaks==1.4.1 #django-widget-tweaks==1.4.1
gunicorn==19.7.1 git+git://github.com/jazzband/django-widget-tweaks.git@1.4.2
icalendar==3.11.7 gunicorn==19.8.1
lxml==4.0.0 icalendar==4.0.1
Markdown==2.6.9 lxml==4.2.1
Pillow==4.2.1 Markdown==2.6.11
psycopg2==2.7.3.1 Pillow==5.1.0
psycopg2==2.7.4
Pygments==2.2.0 Pygments==2.2.0
PyPDF2==1.26.0 PyPDF2==1.26.0
python-dateutil==2.6.1 python-dateutil==2.7.2
pytz==2017.2 pytz==2018.4
raven==6.2.1 raven==6.7.0
reportlab==3.4.0 reportlab==3.4.0
selenium==3.5.0 selenium==3.12.0
simplejson==3.11.1 simplejson==3.14.0
six==1.11.0 six==1.11.0
sqlparse==0.2.3 sqlparse==0.2.4
static3==0.7.0 static3==0.7.0
svg2rlg==0.3 svg2rlg==0.3
yolk==0.4.3 yolk==0.4.3
z3c.rml==3.2.0 z3c.rml==3.5.0
zope.event==4.3.0 zope.event==4.3.0
zope.interface==4.4.3 zope.interface==4.5.0
zope.schema==4.5.0 zope.schema==4.5.0