summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMagnus Hagander2020-03-31 16:13:41 +0000
committerMagnus Hagander2020-03-31 16:13:41 +0000
commit6d6244a77d5f78a08d904004ef41808721ac14d1 (patch)
tree93e455900ab5c0d76049b31a0a70b55d057e9a37
parent52b52f86add49409759900cea07df9fd8cac6248 (diff)
Create abstraction for getting "today"
This will work differently for conferences and non-conferences once we add proper timezone support, so abstract it out into a separate couple of functions. For now they both return the same thing, but this will change in a later commit. In passing, fix missing datetime.now() -> timezone.now() conversions.
-rw-r--r--postgresqleu/accounting/util.py4
-rw-r--r--postgresqleu/accounting/views.py7
-rwxr-xr-xpostgresqleu/braintreepayment/management/commands/update_braintree_transactions.py4
-rw-r--r--postgresqleu/confreg/forms.py7
-rw-r--r--postgresqleu/confreg/management/commands/confreg_expire_additionaloptions.py5
-rw-r--r--postgresqleu/confreg/management/commands/confreg_frequent_reminders.py11
-rw-r--r--postgresqleu/confreg/models.py7
-rw-r--r--postgresqleu/confreg/util.py3
-rw-r--r--postgresqleu/confreg/views.py19
-rw-r--r--postgresqleu/confsponsor/benefitclasses/attendeelist.py4
-rw-r--r--postgresqleu/confsponsor/forms.py7
-rw-r--r--postgresqleu/confsponsor/invoicehandler.py13
-rw-r--r--postgresqleu/confsponsor/management/commands/sponsor_generate_discount_invoices.py12
-rw-r--r--postgresqleu/confsponsor/views.py9
-rw-r--r--postgresqleu/elections/views.py17
-rw-r--r--postgresqleu/invoices/views.py7
-rw-r--r--postgresqleu/membership/invoicehandler.py12
-rw-r--r--postgresqleu/membership/models.py5
-rw-r--r--postgresqleu/membership/views.py11
-rw-r--r--postgresqleu/transferwise/api.py3
-rw-r--r--postgresqleu/util/time.py9
-rw-r--r--postgresqleu/views.py17
22 files changed, 111 insertions, 82 deletions
diff --git a/postgresqleu/accounting/util.py b/postgresqleu/accounting/util.py
index 4518caf0..8e35e2dc 100644
--- a/postgresqleu/accounting/util.py
+++ b/postgresqleu/accounting/util.py
@@ -7,9 +7,9 @@ from django.db.models import Max
from django.conf import settings
from decimal import Decimal
-import datetime
from postgresqleu.mailqueue.util import send_simple_mail
+from postgresqleu.util.time import today_global
from .models import JournalEntry, JournalItem, JournalUrl
from .models import Object, Account, Year
@@ -33,7 +33,7 @@ def create_accounting_entry(items,
if not settings.ENABLE_AUTO_ACCOUNTING:
return
- date = datetime.date.today()
+ date = today_global()
sid = transaction.savepoint()
try:
diff --git a/postgresqleu/accounting/views.py b/postgresqleu/accounting/views.py
index 10bc390b..f2c4057d 100644
--- a/postgresqleu/accounting/views.py
+++ b/postgresqleu/accounting/views.py
@@ -7,10 +7,11 @@ from django.db.models import Max
from django.db import connection, transaction
from django.core.paginator import Paginator
-from datetime import datetime, date
+from datetime import datetime
from postgresqleu.util.request import get_int_or_error
from postgresqleu.util.auth import authenticate_backend_group
+from postgresqleu.util.time import today_global
from .models import JournalEntry, JournalItem, JournalUrl, Year, Object
from .models import IncomingBalance, Account
@@ -21,7 +22,7 @@ from .forms import CloseYearForm
def index(request):
authenticate_backend_group(request, 'Accounting managers')
# Always redirect to the current year
- return HttpResponseRedirect("%s/" % datetime.today().year)
+ return HttpResponseRedirect("%s/" % today_global().year)
def _setup_search(request, term):
@@ -75,7 +76,7 @@ def year(request, year):
year = Year.objects.get(year=int(year))
except Year.DoesNotExist:
# Year does not exist, but what do we do about it?
- if int(year) == date.today().year:
+ if int(year) == today_global().year:
# For current year, we automatically create the year and move on
year = Year(year=int(year), isopen=True)
year.save()
diff --git a/postgresqleu/braintreepayment/management/commands/update_braintree_transactions.py b/postgresqleu/braintreepayment/management/commands/update_braintree_transactions.py
index 9a7ae4c5..308c1112 100755
--- a/postgresqleu/braintreepayment/management/commands/update_braintree_transactions.py
+++ b/postgresqleu/braintreepayment/management/commands/update_braintree_transactions.py
@@ -7,7 +7,7 @@
#
import logging
-from datetime import datetime, timedelta
+from datetime import timedelta
from django.core.management.base import BaseCommand
from django.db import transaction
@@ -117,7 +117,7 @@ class Command(BaseCommand):
accrows.append((pm.config('accounting_fee'), accstr, t.amount - t.disbursedamount, t.accounting_object))
create_accounting_entry(accrows, False)
- elif datetime.today() - t.settledat > timedelta(days=10):
+ elif timezone.now() - t.settledat > timedelta(days=10):
BraintreeLog(transid=t.transid,
error=True,
paymentmethod=method,
diff --git a/postgresqleu/confreg/forms.py b/postgresqleu/confreg/forms.py
index da0f2797..efc93d5f 100644
--- a/postgresqleu/confreg/forms.py
+++ b/postgresqleu/confreg/forms.py
@@ -21,10 +21,11 @@ from postgresqleu.util.widgets import EmailTextWidget, MonospaceTextarea
from postgresqleu.util.db import exec_to_list
from postgresqleu.util.magic import magicdb
from postgresqleu.util.backendlookups import GeneralAccountLookup
+from postgresqleu.util.time import today_conference
from postgresqleu.countries.models import Country
-from datetime import datetime, date, timedelta
+from datetime import timedelta
import requests
@@ -84,7 +85,7 @@ class ConferenceRegistrationForm(forms.ModelForm):
if newval and not newval.active:
raise forms.ValidationError('Registration type "%s" is currently not available.' % newval)
- if newval and newval.activeuntil and newval.activeuntil < datetime.today().date():
+ if newval and newval.activeuntil and newval.activeuntil <= today_conference():
raise forms.ValidationError('Registration type "%s" was only available until %s.' % (newval, newval.activeuntil))
if self.instance and self.instance.payconfirmedat:
@@ -133,7 +134,7 @@ class ConferenceRegistrationForm(forms.ModelForm):
c = DiscountCode.objects.get(code=newval, conference=self.instance.conference)
if c.is_invoiced:
raise forms.ValidationError('This discount code is not valid anymore.')
- if c.validuntil and c.validuntil < date.today():
+ if c.validuntil and c.validuntil < today_conference():
raise forms.ValidationError('This discount code has expired.')
if c.maxuses > 0:
if c.registrations.count() >= c.maxuses:
diff --git a/postgresqleu/confreg/management/commands/confreg_expire_additionaloptions.py b/postgresqleu/confreg/management/commands/confreg_expire_additionaloptions.py
index 2f2f89b3..801689ac 100644
--- a/postgresqleu/confreg/management/commands/confreg_expire_additionaloptions.py
+++ b/postgresqleu/confreg/management/commands/confreg_expire_additionaloptions.py
@@ -9,10 +9,11 @@ from django.db import transaction
from collections import defaultdict
from io import StringIO
-from datetime import timedelta, date
+from datetime import timedelta
from postgresqleu.mailqueue.util import send_simple_mail
+from postgresqleu.util.time import today_global
from postgresqleu.confreg.util import expire_additional_options
from postgresqleu.confreg.models import ConferenceRegistration
@@ -31,7 +32,7 @@ class Command(BaseCommand):
# that have additional options with autocancel set
return Conference.objects.filter(active=True,
conferenceadditionaloption__invoice_autocancel_hours__isnull=False,
- enddate__gt=date.today() + timedelta(days=1),
+ enddate__gt=today_global() + timedelta(days=1),
).exists()
@transaction.atomic
diff --git a/postgresqleu/confreg/management/commands/confreg_frequent_reminders.py b/postgresqleu/confreg/management/commands/confreg_frequent_reminders.py
index 9cdaa47f..19558b27 100644
--- a/postgresqleu/confreg/management/commands/confreg_frequent_reminders.py
+++ b/postgresqleu/confreg/management/commands/confreg_frequent_reminders.py
@@ -11,12 +11,13 @@ from django.conf import settings
from django.utils import timezone
import sys
-from datetime import datetime, timedelta
+from datetime import timedelta
from postgresqleu.confreg.models import Conference, ConferenceSession
from postgresqleu.confreg.models import ConferenceRegistration
from postgresqleu.util.messaging.twitter import Twitter
+from postgresqleu.util.time import today_global
class Command(BaseCommand):
@@ -28,8 +29,8 @@ class Command(BaseCommand):
@classmethod
def should_run(self):
return Conference.objects.filter(twitterreminders_active=True,
- startdate__lte=datetime.today() + timedelta(days=1),
- enddate__gte=datetime.today() - timedelta(days=1)) \
+ startdate__lte=today_global() + timedelta(days=1),
+ enddate__gte=today_global() - timedelta(days=1)) \
.exclude(twitter_token='') \
.exclude(twitter_secret='').exists()
@@ -49,8 +50,8 @@ class Command(BaseCommand):
# more plugins.
has_error = False
for conference in Conference.objects.filter(twitterreminders_active=True,
- startdate__lte=datetime.today() + timedelta(days=1),
- enddate__gte=datetime.today() - timedelta(days=1)) \
+ startdate__lte=today_global() + timedelta(days=1),
+ enddate__gte=today_global() - timedelta(days=1)) \
.exclude(twitter_token='') \
.exclude(twitter_secret=''):
tw = Twitter(conference)
diff --git a/postgresqleu/confreg/models.py b/postgresqleu/confreg/models.py
index 575f6ebe..d1adc967 100644
--- a/postgresqleu/confreg/models.py
+++ b/postgresqleu/confreg/models.py
@@ -19,6 +19,7 @@ from postgresqleu.util.validators import TwitterValidator
from postgresqleu.util.validators import PictureUrlValidator
from postgresqleu.util.forms import ChoiceArrayField
from postgresqleu.util.fields import LowercaseEmailField, ImageBinaryField
+from postgresqleu.util.time import today_conference
import base64
import datetime
@@ -267,10 +268,10 @@ class Conference(models.Model):
# conference. Note that this will always be zero if the conference
# is in the past (so we don't end up with unnecessary db queries)
if self.enddate:
- if self.enddate < datetime.datetime.today().date():
+ if self.enddate < today_conference():
return 0
else:
- if self.startdate < datetime.datetime.today().date():
+ if self.startdate < tday_conference():
return 0
return self.conferencesession_set.exclude(status=F('lastnotifiedstatus')).exclude(speaker__isnull=True).count()
@@ -289,7 +290,7 @@ class Conference(models.Model):
@property
def needs_data_purge(self):
- return self.enddate < datetime.date.today() and not self.personal_data_purged
+ return self.enddate < today_conference() and not self.personal_data_purged
def clean(self):
cc = super(Conference, self).clean()
diff --git a/postgresqleu/confreg/util.py b/postgresqleu/confreg/util.py
index 93a2e2dd..5cb6fd40 100644
--- a/postgresqleu/confreg/util.py
+++ b/postgresqleu/confreg/util.py
@@ -13,6 +13,7 @@ import re
from postgresqleu.mailqueue.util import send_simple_mail
from postgresqleu.util.middleware import RedirectException
+from postgresqleu.util.time import today_conference
from postgresqleu.confreg.jinjafunc import JINJA_TEMPLATE_ROOT, render_jinja_conference_template
from postgresqleu.confreg.jinjapdf import render_jinja_ticket
@@ -83,7 +84,7 @@ def invoicerows_for_registration(reg, update_used_vouchers):
# Nonexistant voucher code means discount code was used
try:
d = DiscountCode.objects.get(code=reg.vouchercode, conference=reg.conference)
- if d.validuntil and d.validuntil < date.today():
+ if d.validuntil and d.validuntil < today_conference():
raise InvoicerowsException("Discount code is no longer valid")
elif d.maxuses > 0 and d.registrations.count() >= d.maxuses:
raise InvoicerowsException("Discount code does not have enough remaining instances")
diff --git a/postgresqleu/confreg/views.py b/postgresqleu/confreg/views.py
index 2e44ad66..87c3fcbd 100644
--- a/postgresqleu/confreg/views.py
+++ b/postgresqleu/confreg/views.py
@@ -58,6 +58,7 @@ from .backendforms import ResendWelcomeMailForm
from postgresqleu.util.request import get_int_or_error
from postgresqleu.util.decorators import superuser_required
from postgresqleu.util.random import generate_random_token
+from postgresqleu.util.time import today_conference
from postgresqleu.invoices.models import Invoice, InvoicePaymentMethod, InvoiceRow
from postgresqleu.invoices.util import InvoiceWrapper
from postgresqleu.confwiki.models import Wikipage
@@ -307,7 +308,7 @@ def register(request, confname, whatfor=None):
# Render the dashboard.
return _registration_dashboard(request, conference, reg, has_other_multiregs, redir_root)
else:
- if datetime.now().date() < conference.startdate:
+ if today_conference() < conference.startdate:
return render_conference_response(request, conference, 'reg', 'confreg/not_yet_open.html')
else:
return render_conference_response(request, conference, 'reg', 'confreg/closed.html')
@@ -420,7 +421,7 @@ def multireg(request, confname, regid=None):
is_active = conference.active or conference.testers.filter(pk=request.user.id).exists()
if not is_active:
# Registration not open.
- if datetime.now().date() < conference.startdate:
+ if today_conference() < conference.startdate:
return render_conference_response(request, conference, 'reg', 'confreg/not_yet_open.html')
else:
return render_conference_response(request, conference, 'reg', 'confreg/closed.html')
@@ -585,7 +586,7 @@ def multireg_newinvoice(request, confname):
is_active = conference.active or conference.testers.filter(pk=request.user.id).exists()
if not is_active:
# Registration not open.
- if datetime.now().date() < conference.startdate:
+ if today_conference() < conference.startdate:
return render_conference_response(request, conference, 'reg', 'confreg/not_yet_open.html')
else:
return render_conference_response(request, conference, 'reg', 'confreg/closed.html')
@@ -617,7 +618,7 @@ def multireg_newinvoice(request, confname):
errors.append('{0} has no registration type specified'.format(r.email))
elif not r.regtype.active:
errors.append('{0} uses registration type {1} which is not active'.format(r.email, r.regtype))
- elif r.regtype.activeuntil and r.regtype.activeuntil < date.today():
+ elif r.regtype.activeuntil and r.regtype.activeuntil < today_conference():
errors.append('{0} uses registration type {1} which is not active'.format(r.email, r.regtype))
else:
try:
@@ -702,7 +703,7 @@ def multireg_bulkview(request, confname, bulkid):
is_active = conference.active or conference.testers.filter(pk=request.user.id).exists()
if not is_active:
# Registration not open.
- if datetime.now().date() < conference.startdate:
+ if today_conference() < conference.startdate:
return render_conference_response(request, conference, 'reg', 'confreg/not_yet_open.html')
else:
return render_conference_response(request, conference, 'reg', 'confreg/closed.html')
@@ -822,7 +823,7 @@ def reg_add_options(request, confname):
if a and reg.regtype not in a:
# New regtype is required. Figure out if there is an upsellable
# one available.
- upsellable = o.requires_regtype.filter(Q(upsell_target=True, active=True, specialtype__isnull=True) & (Q(activeuntil__isnull=True) | Q(activeuntil__lt=datetime.today().date())))
+ upsellable = o.requires_regtype.filter(Q(upsell_target=True, active=True, specialtype__isnull=True) & (Q(activeuntil__isnull=True) | Q(activeuntil__lt=today_conference())))
num = len(upsellable)
if num == 0:
messages.warning(request, "Option {0} requires a registration type that's not available.".format(o.name))
@@ -2954,9 +2955,9 @@ def admin_dashboard(request):
current = []
upcoming = []
for c in conferences:
- if abs((date.today() - c.startdate).days) < 14 or abs((date.today() - c.enddate).days) < 14:
+ if abs((today_conference() - c.startdate).days) < 14 or abs((today_conference() - c.enddate).days) < 14:
current.insert(0, c)
- elif c.startdate > date.today():
+ elif c.startdate > today_conference():
upcoming.insert(0, c)
return render(request, 'confreg/admin_dashboard.html', {
@@ -3289,7 +3290,7 @@ def _admin_registration_cancel(request, conference, redirurl, regs):
if conference.vat_registrations:
this_to_refund_vat += (regtotalvat[rid] * pattern.percent / Decimal(100) - pattern.fees * conference.vat_registrations.vatpercent / Decimal(100)).quantize(Decimal('0.01'))
- today = date.today()
+ today = today_conference()
if (pattern.fromdate is None or pattern.fromdate <= today) and \
(pattern.todate is None or pattern.todate >= today):
suggest = "***"
diff --git a/postgresqleu/confsponsor/benefitclasses/attendeelist.py b/postgresqleu/confsponsor/benefitclasses/attendeelist.py
index d7b696b4..3c32e09d 100644
--- a/postgresqleu/confsponsor/benefitclasses/attendeelist.py
+++ b/postgresqleu/confsponsor/benefitclasses/attendeelist.py
@@ -2,7 +2,6 @@ from django import forms
from django.core.exceptions import ValidationError
from postgresqleu.confsponsor.backendforms import BackendSponsorshipLevelBenefitForm
-from datetime import datetime
import base64
import io as StringIO
import csv
@@ -10,6 +9,7 @@ import csv
from .base import BaseBenefit, BaseBenefitForm
from postgresqleu.confreg.models import ConferenceRegistration
+from postgresqleu.util.time import today_conference
class AttendeeListForm(BaseBenefitForm):
@@ -45,7 +45,7 @@ class AttendeeList(BaseBenefit):
if claimedbenefit.declined:
return ""
if claimedbenefit.confirmed:
- if self.level.conference.enddate < datetime.today().date():
+ if self.level.conference.enddate < today_conference():
data = StringIO.StringIO()
c = csv.writer(data, delimiter=';')
for r in ConferenceRegistration.objects.filter(conference=self.level.conference,
diff --git a/postgresqleu/confsponsor/forms.py b/postgresqleu/confsponsor/forms.py
index c2b138af..cc981d32 100644
--- a/postgresqleu/confsponsor/forms.py
+++ b/postgresqleu/confsponsor/forms.py
@@ -16,8 +16,9 @@ from postgresqleu.util.validators import BeforeValidator, AfterValidator, Twitte
from postgresqleu.util.validators import Http200Validator
from postgresqleu.util.widgets import Bootstrap4CheckboxSelectMultiple, EmailTextWidget
from postgresqleu.util.widgets import Bootstrap4HtmlDateTimeInput
+from postgresqleu.util.time import today_conference
-from datetime import date, timedelta
+from datetime import timedelta
from decimal import Decimal
@@ -140,7 +141,7 @@ class PurchaseVouchersForm(forms.Form):
def __init__(self, conference, *args, **kwargs):
self.conference = conference
super(PurchaseVouchersForm, self).__init__(*args, **kwargs)
- activeQ = Q(activeuntil__isnull=True) | Q(activeuntil__gt=date.today())
+ activeQ = Q(activeuntil__isnull=True) | Q(activeuntil__gte=today_conference())
if self.data and self.data.get('regtype', None) and self.data.get('num', None) and _int_with_default(self.data['num'], 0) > 0:
RegistrationType.objects.get(pk=self.data['regtype'])
self.fields['confirm'].help_text = 'Check this box to confirm that you will pay the generated invoice'
@@ -175,7 +176,7 @@ class PurchaseDiscountForm(forms.Form):
self.fields['requiredoptions'].queryset = ConferenceAdditionalOption.objects.filter(conference=conference, public=True)
self.fields['expires'].initial = conference.startdate - timedelta(days=2)
self.fields['expires'].validators.append(BeforeValidator(conference.startdate - timedelta(days=1)))
- self.fields['expires'].validators.append(AfterValidator(date.today() - timedelta(days=1)))
+ self.fields['expires'].validators.append(AfterValidator(today_conference() - timedelta(days=1)))
if not showconfirm:
del self.fields['confirm']
diff --git a/postgresqleu/confsponsor/invoicehandler.py b/postgresqleu/confsponsor/invoicehandler.py
index 00ce3ff6..de730147 100644
--- a/postgresqleu/confsponsor/invoicehandler.py
+++ b/postgresqleu/confsponsor/invoicehandler.py
@@ -1,12 +1,13 @@
from django.utils import timezone
from django.conf import settings
-from datetime import datetime, timedelta, date
+from datetime import timedelta
import base64
import os
from postgresqleu.mailqueue.util import send_simple_mail
from postgresqleu.invoices.util import InvoiceManager
+from postgresqleu.util.time import today_conference
from .models import Sponsor, PurchasedVoucher
from postgresqleu.confreg.models import PrepaidBatch, PrepaidVoucher
@@ -141,10 +142,10 @@ def create_sponsor_invoice(user, sponsor):
invoicerows = [
['%s %s sponsorship' % (conference, level), 1, level.levelcost, vatlevel],
]
- if conference.startdate < date.today() + timedelta(days=5):
+ if conference.startdate < today_conference() + timedelta(days=5):
# If conference happens in the next 5 days, invoice is due immediately
- duedate = date.today()
- elif conference.startdate < date.today() + timedelta(days=30):
+ duedate = today_conferece()
+ elif conference.startdate < today_conference() + timedelta(days=30):
# Less than 30 days before the conference, set the due date to
# 5 days before the conference
duedate = conference.startdate - timedelta(days=5)
@@ -274,8 +275,8 @@ def create_voucher_invoice(conference, invoiceaddr, user, rt, num):
user.first_name + ' ' + user.last_name,
invoiceaddr,
'Prepaid vouchers for %s' % conference.conferencename,
- datetime.now(),
- date.today(),
+ timezone.now(),
+ today_conference(),
invoicerows,
processor=processor,
accounting_account=settings.ACCOUNTING_CONFREG_ACCOUNT,
diff --git a/postgresqleu/confsponsor/management/commands/sponsor_generate_discount_invoices.py b/postgresqleu/confsponsor/management/commands/sponsor_generate_discount_invoices.py
index 35213280..4c956783 100644
--- a/postgresqleu/confsponsor/management/commands/sponsor_generate_discount_invoices.py
+++ b/postgresqleu/confsponsor/management/commands/sponsor_generate_discount_invoices.py
@@ -3,10 +3,11 @@
#
from django.core.management.base import BaseCommand
+from django.utils import timezone
from django.db import transaction
from django.conf import settings
-from datetime import date, datetime, timedelta, time
+from datetime import timedelta
from django.db.models import Q, F, Count
@@ -15,6 +16,7 @@ from postgresqleu.confreg.util import send_conference_mail
from postgresqleu.confsponsor.models import Sponsor
from postgresqleu.mailqueue.util import send_simple_mail
from postgresqleu.invoices.util import InvoiceManager, InvoiceWrapper
+from postgresqleu.util.time import today_global
class Command(BaseCommand):
@@ -32,7 +34,7 @@ class Command(BaseCommand):
def handle(self, *args, **options):
# We're always going to process all conferences, since most will not have any
# open discount codes.
- filt = Q(sponsor__isnull=False, is_invoiced=False) & (Q(validuntil__lt=date.today()) | Q(num_uses__gte=F('maxuses')))
+ filt = Q(sponsor__isnull=False, is_invoiced=False) & (Q(validuntil__lte=today_global()) | Q(num_uses__gte=F('maxuses')))
codes = DiscountCode.objects.annotate(num_uses=Count('registrations')).filter(filt)
for code in codes:
# Either the code has expired, or it is fully used by now. Time to generate the invoice. We'll also
@@ -84,8 +86,8 @@ class Command(BaseCommand):
"{0} {1}".format(code.sponsor_rep.first_name, code.sponsor_rep.last_name),
'%s\n%s' % (code.sponsor.name, code.sponsor.invoiceaddr),
'{0} discount code {1}'.format(code.conference, code.code),
- datetime.now(),
- date.today() + timedelta(days=1),
+ timezone.now(),
+ today_global() + timedelta(days=1),
invoicerows,
accounting_account=settings.ACCOUNTING_CONFREG_ACCOUNT,
accounting_object=code.conference.accounting_object,
@@ -122,7 +124,7 @@ class Command(BaseCommand):
'sponsor': code.sponsor,
'invoice': code.invoice,
'curr': settings.CURRENCY_ABBREV,
- 'expired_time': code.validuntil < date.today(),
+ 'expired_time': code.validuntil < today_global(),
},
sender=code.conference.sponsoraddr,
receivername='{0} {1}'.format(manager.first_name, manager.last_name)
diff --git a/postgresqleu/confsponsor/views.py b/postgresqleu/confsponsor/views.py
index ca5f4dde..1a15cf29 100644
--- a/postgresqleu/confsponsor/views.py
+++ b/postgresqleu/confsponsor/views.py
@@ -9,7 +9,7 @@ from django.contrib import messages
from django.contrib.auth.models import User
from django.utils import timezone
-from datetime import datetime, timedelta
+from datetime import timedelta
import io
import random
from collections import OrderedDict
@@ -25,6 +25,7 @@ from postgresqleu.mailqueue.util import send_simple_mail
from postgresqleu.util.storage import InlineEncodedStorage
from postgresqleu.util.decorators import superuser_required
from postgresqleu.util.request import get_int_or_error
+from postgresqleu.util.time import today_global
from postgresqleu.invoices.util import InvoiceWrapper, InvoiceManager
from .models import Sponsor, SponsorshipLevel, SponsorshipBenefit
@@ -45,9 +46,9 @@ from .vatutil import validate_eu_vat_number
@login_required
def sponsor_dashboard(request):
# We define "past sponsors" as those older than a month - because we have to pick something.
- currentsponsors = Sponsor.objects.filter(managers=request.user, conference__enddate__gte=datetime.today() - timedelta(days=31)).order_by('conference__startdate')
- pastsponsors = Sponsor.objects.filter(managers=request.user, conference__enddate__lt=datetime.today() - timedelta(days=31)).order_by('conference__startdate')
- conferences = Conference.objects.filter(callforsponsorsopen=True, startdate__gt=datetime.today()).order_by('startdate')
+ currentsponsors = Sponsor.objects.filter(managers=request.user, conference__enddate__gte=today_global() - timedelta(days=31)).order_by('conference__startdate')
+ pastsponsors = Sponsor.objects.filter(managers=request.user, conference__enddate__lt=today_global() - timedelta(days=31)).order_by('conference__startdate')
+ conferences = Conference.objects.filter(callforsponsorsopen=True, startdate__gt=today_blobal()).order_by('startdate')
return render(request, 'confsponsor/dashboard.html', {
"currentsponsors": currentsponsors,
diff --git a/postgresqleu/elections/views.py b/postgresqleu/elections/views.py
index 08f7bd6d..e424abb2 100644
--- a/postgresqleu/elections/views.py
+++ b/postgresqleu/elections/views.py
@@ -3,16 +3,17 @@ from django.http import HttpResponseRedirect, Http404
from django.contrib.auth.decorators import login_required
from django.db import connection
+from postgresqleu.utils.time import today_global
from .models import Election, Member, Candidate, Vote
from .forms import VoteForm
-from datetime import date, timedelta
+from datetime import timedelta
def home(request):
elections = Election.objects.filter(isopen=True).order_by('startdate')
- open_elections = [e for e in elections if e.startdate <= date.today() and e.enddate >= date.today()]
- past_elections = [e for e in elections if e.startdate < date.today() and e.enddate < date.today()]
- upcoming_elections = [e for e in elections if e.startdate > date.today()]
+ open_elections = [e for e in elections if e.startdate <= today_global() and e.enddate >= today_global()]
+ past_elections = [e for e in elections if e.startdate < today_global() and e.enddate < today_global()]
+ upcoming_elections = [e for e in elections if e.startdate > today_global()]
return render(request, 'elections/home.html', {
'open': open_elections,
@@ -26,10 +27,10 @@ def election(request, electionid):
if not election.isopen:
raise Http404("This election is not open (yet)")
- if election.startdate > date.today():
+ if election.startdate > today_global():
raise Http404("This election has not started yet")
- if election.enddate < date.today():
+ if election.enddate < today_global():
# Election is closed, consider publishing the results
if not election.resultspublic:
# If user is an admin, show anyway, otherwise throw an error
@@ -67,7 +68,7 @@ def election(request, electionid):
return render(request, 'elections/mustbemember.html', {})
# Make sure that the membership hasn't expired
- if member.paiduntil < date.today():
+ if member.paiduntil < today_global():
return render(request, 'elections/mustbemember.html', {})
# Verify that the user has been a member for at least 28 days.
@@ -110,7 +111,7 @@ def ownvotes(request, electionid):
if not election.isopen:
raise Http404("This election is not open (yet)")
- if election.enddate >= date.today():
+ if election.enddate >= today_global():
raise Http404("This election has not ended yet")
member = get_object_or_404(Member, user=request.user)
diff --git a/postgresqleu/invoices/views.py b/postgresqleu/invoices/views.py
index d81a00f1..4a05275d 100644
--- a/postgresqleu/invoices/views.py
+++ b/postgresqleu/invoices/views.py
@@ -10,12 +10,13 @@ from django.conf import settings
import base64
import io
-from datetime import datetime, timedelta
+from datetime import timedelta
from decimal import Decimal
from postgresqleu.util.auth import authenticate_backend_group
from postgresqleu.util.pagination import simple_pagination
from postgresqleu.util.request import get_int_or_error
+from postgresqleu.util.time import today_global
from .models import Invoice, InvoiceRow, InvoiceHistory, InvoicePaymentMethod, VatRate
from .models import InvoiceRefund
from .forms import InvoiceForm, InvoiceRowForm, RefundForm
@@ -116,8 +117,8 @@ def oneinvoice(request, invoicenum):
# since they're all based on the same model and form.
if invoicenum == 'new':
invoice = Invoice(
- invoicedate=datetime.today(),
- duedate=datetime.today() + timedelta(days=30),
+ invoicedate=today_global(),
+ duedate=today_global() + timedelta(days=30),
)
else:
invoice = get_object_or_404(Invoice, pk=invoicenum)
diff --git a/postgresqleu/membership/invoicehandler.py b/postgresqleu/membership/invoicehandler.py
index 192139e3..cc0c9cd6 100644
--- a/postgresqleu/membership/invoicehandler.py
+++ b/postgresqleu/membership/invoicehandler.py
@@ -1,8 +1,10 @@
from django.conf import settings
+from django.utils import timezone
+from postgresqleu.util.time import today_global
from .models import Member, MemberLog, get_config
-from datetime import datetime, timedelta, date
+from datetime import timedelta
class InvoiceProcessor(object):
@@ -28,21 +30,21 @@ class InvoiceProcessor(object):
# Extend the membership. If already paid to a date in the future,
# extend from that date. Otherwise, from today.
- if member.paiduntil and member.paiduntil > date.today():
+ if member.paiduntil and member.paiduntil > today_global():
member.paiduntil = member.paiduntil + timedelta(days=cfg.membership_years * 365)
else:
- member.paiduntil = date.today() + timedelta(days=cfg.membership_years * 365)
+ member.paiduntil = today_global() + timedelta(days=cfg.membership_years * 365)
member.expiry_warning_sent = None
# If the member isn't already a member, set todays date as the
# starting date.
if not member.membersince:
- member.membersince = date.today()
+ member.membersince = today_global()
member.save()
# Create a log record too, and save it
- MemberLog(member=member, timestamp=datetime.now(), message="Payment for %s years received, membership extended to %s" % (cfg.membership_years, member.paiduntil)).save()
+ MemberLog(member=member, timestamp=timezone.now(), message="Payment for %s years received, membership extended to %s" % (cfg.membership_years, member.paiduntil)).save()
# Process an invoice being canceled. This means we need to unlink
# it from the membership.
diff --git a/postgresqleu/membership/models.py b/postgresqleu/membership/models.py
index 3f53c3d6..cd352f52 100644
--- a/postgresqleu/membership/models.py
+++ b/postgresqleu/membership/models.py
@@ -5,11 +5,12 @@ from django.conf import settings
from django.utils import timezone
from postgresqleu.util.fields import LowercaseEmailField
+from postgresqleu.util.time import today_global
from postgresqleu.countries.models import Country
from postgresqleu.invoices.models import Invoice, InvoicePaymentMethod
from postgresqleu.membership.util import country_validator_choices
-from datetime import date, datetime, timedelta
+from datetime import timedelta
class MembershipConfiguration(models.Model):
@@ -59,7 +60,7 @@ class Member(models.Model):
@property
def expiressoon(self):
if self.paiduntil:
- if self.paiduntil < date.today() + timedelta(60):
+ if self.paiduntil < today_global() + timedelta(days=60):
return True
else:
return False
diff --git a/postgresqleu/membership/views.py b/postgresqleu/membership/views.py
index 5fef422b..811d9bb5 100644
--- a/postgresqleu/membership/views.py
+++ b/postgresqleu/membership/views.py
@@ -12,11 +12,12 @@ from .forms import MemberForm, ProxyVoterForm
from postgresqleu.util.decorators import superuser_required
from postgresqleu.util.random import generate_random_token
+from postgresqleu.util.time import today_global
from postgresqleu.invoices.util import InvoiceManager, InvoicePresentationWrapper
from postgresqleu.invoices.models import InvoiceProcessor
from postgresqleu.mailqueue.util import send_simple_mail
-from datetime import date, datetime, timedelta
+from datetime import timedelta
import json
import base64
import os
@@ -31,7 +32,7 @@ def home(request):
# We have a batch job that expires members, but do it here as well to make sure
# the web is up to date with information if necessary.
- if member.paiduntil and member.paiduntil < date.today():
+ if member.paiduntil and member.paiduntil < today_global():
MemberLog(member=member,
timestamp=timezone.now(),
message="Membership expired").save()
@@ -135,7 +136,7 @@ def meetings(request):
} for m in meetings]
return render(request, 'membership/meetings.html', {
- 'active': member.paiduntil and member.paiduntil >= datetime.today().date(),
+ 'active': member.paiduntil and member.paiduntil >= today_global(),
'member': member,
'meetings': meetinginfo,
})
@@ -143,7 +144,7 @@ def meetings(request):
@transaction.atomic
def _meeting(request, member, meeting, isproxy):
- if not (member.paiduntil and member.paiduntil >= datetime.today().date()):
+ if not (member.paiduntil and member.paiduntil >= today_global()):
return HttpResponse("Your membership is not active")
if not meeting.allmembers:
@@ -197,7 +198,7 @@ def meeting_proxy(request, meetingid):
meeting = get_object_or_404(Meeting, pk=meetingid)
member = get_object_or_404(Member, user=request.user)
- if not (member.paiduntil and member.paiduntil >= datetime.today().date()):
+ if not (member.paiduntil and member.paiduntil >= today_global()):
return HttpResponse("Your membership is not active")
if not meeting.allmembers:
diff --git a/postgresqleu/transferwise/api.py b/postgresqleu/transferwise/api.py
index 571c31b2..cc7512f0 100644
--- a/postgresqleu/transferwise/api.py
+++ b/postgresqleu/transferwise/api.py
@@ -8,6 +8,7 @@ import json
import re
import uuid
+from postgresqleu.util.time import today_global
from .models import TransferwiseRefund
@@ -82,7 +83,7 @@ class TransferwiseApi(object):
def get_transactions(self, startdate=None, enddate=None):
if not enddate:
- enddate = (datetime.today() + timedelta(days=1)).date()
+ enddate = today_global() + timedelta(days=1)
if not startdate:
startdate = enddate - timedelta(days=60)
diff --git a/postgresqleu/util/time.py b/postgresqleu/util/time.py
new file mode 100644
index 00000000..76567187
--- /dev/null
+++ b/postgresqleu/util/time.py
@@ -0,0 +1,9 @@
+from django.utils import timezone
+
+
+def today_conference():
+ return timezone.now().date()
+
+
+def today_global():
+ return timezone.now().date()
diff --git a/postgresqleu/views.py b/postgresqleu/views.py
index 317cb1d7..5c806d71 100644
--- a/postgresqleu/views.py
+++ b/postgresqleu/views.py
@@ -11,6 +11,7 @@ from postgresqleu.invoices.models import PendingBankTransaction, BankFileUpload,
from postgresqleu.invoices.models import InvoiceRefund
from postgresqleu.util.db import exec_to_dict, conditional_exec_to_scalar
+from postgresqleu.util.time import today_global
import datetime
import markdown
@@ -18,7 +19,7 @@ import markdown
# Handle the frontpage
def index(request):
- events = Conference.objects.filter(promoactive=True, enddate__gte=datetime.datetime.today()).order_by('startdate')
+ events = Conference.objects.filter(promoactive=True, enddate__gte=today_global()).order_by('startdate')
series = ConferenceSeries.objects.filter(visible=True).extra(
where=["EXISTS (SELECT 1 FROM confreg_conference c WHERE c.series_id=confreg_conferenceseries.id AND c.promoactive)"]
)
@@ -58,8 +59,8 @@ ORDER BY priosort DESC, datetime DESC LIMIT 5""")
# Handle the events frontpage
def eventsindex(request):
- events = list(Conference.objects.filter(promoactive=True, enddate__gte=datetime.datetime.today()).order_by('startdate'))
- past = Conference.objects.filter(promoactive=True, enddate__lt=datetime.datetime.today()).order_by('-startdate')[:5]
+ events = list(Conference.objects.filter(promoactive=True, enddate__gte=today_global()).order_by('startdate'))
+ past = Conference.objects.filter(promoactive=True, enddate__lt=today_global()).order_by('-startdate')[:5]
series = ConferenceSeries.objects.filter(visible=True).extra(
where=["EXISTS (SELECT 1 FROM confreg_conference c WHERE c.series_id=confreg_conferenceseries.id AND c.promoactive)"]
)
@@ -76,8 +77,8 @@ def eventsindex(request):
# Handle past events list
def pastevents(request):
- events = list(Conference.objects.filter(promoactive=True, enddate__gte=datetime.datetime.today()).order_by('startdate'))
- past = Conference.objects.filter(promoactive=True, enddate__lt=datetime.datetime.today()).order_by('-startdate')
+ events = list(Conference.objects.filter(promoactive=True, enddate__gte=today_global()).order_by('startdate'))
+ past = Conference.objects.filter(promoactive=True, enddate__lt=today_global()).order_by('-startdate')
series = ConferenceSeries.objects.filter(visible=True).extra(
where=["EXISTS (SELECT 1 FROM confreg_conference c WHERE c.series_id=confreg_conferenceseries.id AND c.promoactive)"]
)
@@ -96,15 +97,15 @@ def eventseries(request, id):
return render(request, 'events/series.html', {
'series': series,
- 'upcoming': [e for e in events if e.enddate >= datetime.datetime.today().date()],
- 'past': [e for e in events if e.enddate < datetime.datetime.today().date()],
+ 'upcoming': [e for e in events if e.enddate >= today_global()],
+ 'past': [e for e in events if e.enddate < today_global()],
})
# Handle a users list of previous events
@login_required
def attendee_events(request):
- events = list(Conference.objects.filter(promoactive=True, enddate__gte=datetime.datetime.today()).order_by('startdate'))
+ events = list(Conference.objects.filter(promoactive=True, enddate__gte=today_global()).order_by('startdate'))
series = ConferenceSeries.objects.filter(visible=True).extra(
where=["EXISTS (SELECT 1 FROM confreg_conference c WHERE c.series_id=confreg_conferenceseries.id AND c.promoactive)"]
)