mirror of
https://github.com/pretix/pretix.git
synced 2026-05-05 15:14:04 +00:00
Refactor mark_paid out of models
This commit is contained in:
@@ -1,134 +0,0 @@
|
||||
from django.contrib import admin
|
||||
from django.contrib.auth.admin import UserAdmin
|
||||
from django.utils.translation import ugettext as _
|
||||
from django import forms
|
||||
|
||||
from pretix.base.models import (
|
||||
User, Organizer, OrganizerPermission, Event, EventPermission,
|
||||
Property, PropertyValue, Item, ItemVariation, ItemCategory
|
||||
)
|
||||
|
||||
|
||||
class PretixUserCreationForm(forms.ModelForm):
|
||||
|
||||
"""
|
||||
A form that creates a user, with no privileges, from the given username and
|
||||
password.
|
||||
"""
|
||||
error_messages = {
|
||||
'password_mismatch': _("The two password fields didn't match."),
|
||||
}
|
||||
password1 = forms.CharField(label=_("Password"),
|
||||
widget=forms.PasswordInput)
|
||||
password2 = forms.CharField(label=_("Password confirmation"),
|
||||
widget=forms.PasswordInput,
|
||||
help_text=_("Enter the same password as above, for verification."))
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ("email", "username", "event")
|
||||
|
||||
def clean_password2(self):
|
||||
password1 = self.cleaned_data.get("password1")
|
||||
password2 = self.cleaned_data.get("password2")
|
||||
if password1 and password2 and password1 != password2:
|
||||
raise forms.ValidationError(
|
||||
self.error_messages['password_mismatch'],
|
||||
code='password_mismatch',
|
||||
)
|
||||
return password2
|
||||
|
||||
def save(self, commit=True):
|
||||
user = super(PretixUserCreationForm, self).save(commit=False)
|
||||
user.set_password(self.cleaned_data["password1"])
|
||||
if commit:
|
||||
user.save()
|
||||
return user
|
||||
|
||||
|
||||
class PretixUserAdmin(UserAdmin):
|
||||
|
||||
fieldsets = (
|
||||
(None, {'fields': ('identifier', 'event', 'username', 'password')}),
|
||||
(_('Personal info'), {'fields': ('familyname', 'givenname', 'email')}),
|
||||
(_('Locale'), {'fields': ('locale', 'timezone')}),
|
||||
(_('Permissions'), {'fields': ('is_active', 'is_staff',
|
||||
'groups', 'user_permissions')}),
|
||||
)
|
||||
list_display = ('identifier', 'event', 'username', 'email', 'givenname', 'familyname', 'is_staff')
|
||||
search_fields = ('identifier', 'username', 'givenname', 'familyname', 'email')
|
||||
ordering = ('identifier',)
|
||||
list_filter = ('is_staff', 'is_active', 'groups')
|
||||
add_form = PretixUserCreationForm
|
||||
|
||||
|
||||
class OrganizerPermissionInline(admin.TabularInline):
|
||||
|
||||
model = OrganizerPermission
|
||||
extra = 2
|
||||
|
||||
|
||||
class OrganizerAdmin(admin.ModelAdmin):
|
||||
|
||||
model = Organizer
|
||||
inlines = [OrganizerPermissionInline]
|
||||
list_display = ('name', 'slug')
|
||||
search_fields = ('name', 'slug')
|
||||
|
||||
|
||||
class EventPermissionInline(admin.TabularInline):
|
||||
|
||||
model = EventPermission
|
||||
extra = 2
|
||||
|
||||
|
||||
class EventAdmin(admin.ModelAdmin):
|
||||
|
||||
model = Event
|
||||
inlines = [EventPermissionInline]
|
||||
list_display = ('name', 'slug', 'organizer', 'date_from')
|
||||
search_fields = ('name', 'slug')
|
||||
list_filter = ('date_from', 'currency')
|
||||
|
||||
|
||||
class PropertyValueInline(admin.StackedInline):
|
||||
|
||||
model = PropertyValue
|
||||
extra = 4
|
||||
|
||||
|
||||
class PropertyAdmin(admin.ModelAdmin):
|
||||
|
||||
model = Property
|
||||
inlines = [PropertyValueInline]
|
||||
list_display = ('name', 'event')
|
||||
search_fields = ('name', 'event')
|
||||
|
||||
|
||||
class ItemCategoryAdmin(admin.ModelAdmin):
|
||||
|
||||
model = ItemCategory
|
||||
list_display = ('name', 'event')
|
||||
search_fields = ('name', 'event')
|
||||
|
||||
|
||||
class ItemVariationInline(admin.TabularInline):
|
||||
|
||||
model = ItemVariation
|
||||
extra = 4
|
||||
|
||||
|
||||
class ItemAdmin(admin.ModelAdmin):
|
||||
|
||||
model = Item
|
||||
inlines = [ItemVariationInline]
|
||||
list_display = ('name', 'event', 'category')
|
||||
search_fields = ('name', 'event', 'category', 'short_description')
|
||||
|
||||
|
||||
admin.site.register(User, PretixUserAdmin)
|
||||
admin.site.register(Organizer, OrganizerAdmin)
|
||||
admin.site.register(Event, EventAdmin)
|
||||
admin.site.register(Property, PropertyAdmin)
|
||||
admin.site.register(Item, ItemAdmin)
|
||||
admin.site.register(ItemCategory, ItemCategoryAdmin)
|
||||
@@ -5,7 +5,6 @@ import uuid
|
||||
import random
|
||||
import time
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db import models
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
|
||||
@@ -1660,58 +1659,6 @@ class Order(Versionable):
|
||||
quota.release()
|
||||
return True, quotas_locked
|
||||
|
||||
def mark_paid(self, provider=None, info=None, date=None, manual=None, force=False):
|
||||
"""
|
||||
Mark this order as paid. This clones the order object, sets the payment provider,
|
||||
info and date and returns the cloned order object.
|
||||
|
||||
:param provider: The payment provider that marked this as paid
|
||||
:type provider: str
|
||||
:param info: The information to store in order.payment_info
|
||||
:type info: str
|
||||
:param date: The date the payment was received (if you pass ``None``, the current
|
||||
time will be used).
|
||||
:type date: datetime
|
||||
:param force: Whether this payment should be marked as paid even if no remaining
|
||||
quota is available (default: ``False``).
|
||||
:type force: boolean
|
||||
:raises Quota.QuotaExceededException: if the quota is exceeded and ``force`` is ``False``
|
||||
"""
|
||||
can_be_paid, quotas_locked = self._can_be_paid(keep_locked=True)
|
||||
if not force and can_be_paid is not True:
|
||||
raise Quota.QuotaExceededException(can_be_paid)
|
||||
order = self.clone()
|
||||
order.payment_provider = provider or order.payment_provider
|
||||
order.payment_info = info or order.payment_info
|
||||
order.payment_date = date or now()
|
||||
if manual is not None:
|
||||
order.payment_manual = manual
|
||||
order.status = Order.STATUS_PAID
|
||||
order.save()
|
||||
|
||||
if quotas_locked:
|
||||
for quota in quotas_locked:
|
||||
quota.release()
|
||||
|
||||
from pretix.base.mail import mail
|
||||
mail(
|
||||
order.user, _('Payment received for your order: %(code)s') % {'code': order.code},
|
||||
'pretixpresale/email/order_paid.txt',
|
||||
{
|
||||
'user': order.user,
|
||||
'order': order,
|
||||
'event': order.event,
|
||||
'url': settings.SITE_URL + reverse('presale:event.order', kwargs={
|
||||
'event': order.event.slug,
|
||||
'organizer': order.event.organizer.slug,
|
||||
'order': order.code
|
||||
}),
|
||||
'downloads': order.event.settings.get('ticket_download', as_type=bool)
|
||||
},
|
||||
order.event
|
||||
)
|
||||
return order
|
||||
|
||||
|
||||
class QuestionAnswer(Versionable):
|
||||
"""
|
||||
|
||||
@@ -244,11 +244,11 @@ class BasePaymentProvider:
|
||||
containing an URL the user will be redirected to. If you are done with your process
|
||||
you should return the user to the order's detail page.
|
||||
|
||||
If the payment is completed, you should call ``order.mark_paid(provider, info)``
|
||||
If the payment is completed, you should call ``pretix.bsae.services.orders.mark_order_paid(order, provider, info)``
|
||||
with ``provider`` being your :py:attr:`identifier` and ``info`` being any string
|
||||
you might want to store for later usage. Please note, that if you want to store
|
||||
something inside ``order.payment_info``, please do it after the ``mark_paid`` call,
|
||||
as this call does a object clone for you. Please also note that ``mark_paid`` might
|
||||
something inside ``order.payment_info``, please do it after the ``mark_order_paid`` call,
|
||||
as this call does a object clone for you. Please also note that ``mark_order_paid`` might
|
||||
raise a ``Quota.QuotaExceededException`` if (and only if) the payment term of this
|
||||
order is over and some of the items are sold out. You should use the exception message
|
||||
to display a meaningful error to the user.
|
||||
|
||||
58
src/pretix/base/services/orders.py
Normal file
58
src/pretix/base/services/orders.py
Normal file
@@ -0,0 +1,58 @@
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.timezone import now
|
||||
from pretix.base.models import Order, Quota
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
def mark_order_paid(order, provider=None, info=None, date=None, manual=None, force=False):
|
||||
"""
|
||||
Marks an order as paid. This clones the order object, sets the payment provider,
|
||||
info and date and returns the cloned order object.
|
||||
|
||||
:param provider: The payment provider that marked this as paid
|
||||
:type provider: str
|
||||
:param info: The information to store in order.payment_info
|
||||
:type info: str
|
||||
:param date: The date the payment was received (if you pass ``None``, the current
|
||||
time will be used).
|
||||
:type date: datetime
|
||||
:param force: Whether this payment should be marked as paid even if no remaining
|
||||
quota is available (default: ``False``).
|
||||
:type force: boolean
|
||||
:raises Quota.QuotaExceededException: if the quota is exceeded and ``force`` is ``False``
|
||||
"""
|
||||
can_be_paid, quotas_locked = order._can_be_paid(keep_locked=True)
|
||||
if not force and can_be_paid is not True:
|
||||
raise Quota.QuotaExceededException(can_be_paid)
|
||||
order = order.clone()
|
||||
order.payment_provider = provider or order.payment_provider
|
||||
order.payment_info = info or order.payment_info
|
||||
order.payment_date = date or now()
|
||||
if manual is not None:
|
||||
order.payment_manual = manual
|
||||
order.status = Order.STATUS_PAID
|
||||
order.save()
|
||||
|
||||
if quotas_locked:
|
||||
for quota in quotas_locked:
|
||||
quota.release()
|
||||
|
||||
from pretix.base.mail import mail
|
||||
mail(
|
||||
order.user, _('Payment received for your order: %(code)s') % {'code': order.code},
|
||||
'pretixpresale/email/order_paid.txt',
|
||||
{
|
||||
'user': order.user,
|
||||
'order': order,
|
||||
'event': order.event,
|
||||
'url': settings.SITE_URL + reverse('presale:event.order', kwargs={
|
||||
'event': order.event.slug,
|
||||
'organizer': order.event.organizer.slug,
|
||||
'order': order.code
|
||||
}),
|
||||
'downloads': order.event.settings.get('ticket_download', as_type=bool)
|
||||
},
|
||||
order.event
|
||||
)
|
||||
return order
|
||||
@@ -9,6 +9,7 @@ from django.shortcuts import redirect, render
|
||||
from django.utils.functional import cached_property
|
||||
from django.views.generic import ListView, DetailView, TemplateView
|
||||
from pretix.base.models import Order, Quota, OrderPosition
|
||||
from pretix.base.services.orders import mark_order_paid
|
||||
from pretix.base.signals import register_payment_providers
|
||||
from pretix.control.forms.orders import ExtendForm
|
||||
from pretix.control.permissions import EventPermissionRequiredMixin
|
||||
@@ -107,7 +108,7 @@ class OrderTransition(OrderView):
|
||||
to = self.request.POST.get('status', '')
|
||||
if self.order.status == 'n' and to == 'p':
|
||||
try:
|
||||
self.order.mark_paid(manual=True)
|
||||
mark_order_paid(self.order, manual=True)
|
||||
except Quota.QuotaExceededException as e:
|
||||
messages.error(self.request, str(e))
|
||||
else:
|
||||
|
||||
@@ -9,6 +9,7 @@ from django.shortcuts import redirect, render
|
||||
from django.utils.timezone import now
|
||||
from django.views.generic import TemplateView
|
||||
from pretix.base.models import Order, Quota
|
||||
from pretix.base.services.orders import mark_order_paid
|
||||
from pretix.control.permissions import EventPermissionRequiredMixin
|
||||
from pretix.plugins.banktransfer import csvimport, mt940import
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
@@ -36,7 +37,7 @@ class ImportView(EventPermissionRequiredMixin, TemplateView):
|
||||
some_failed = False
|
||||
for order in orders:
|
||||
try:
|
||||
order.mark_paid(provider='banktransfer', info=json.dumps({
|
||||
mark_order_paid(order, provider='banktransfer', info=json.dumps({
|
||||
'reference': self.request.POST.get('reference_%s' % order.code),
|
||||
'date': self.request.POST.get('date_%s' % order.code),
|
||||
'payer': self.request.POST.get('payer_%s' % order.code),
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
from collections import OrderedDict
|
||||
import json
|
||||
import logging
|
||||
|
||||
from django.contrib import messages
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.template.loader import get_template
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import ugettext as __
|
||||
from django import forms
|
||||
|
||||
import paypalrestsdk
|
||||
from pretix.base.models import Quota
|
||||
|
||||
from pretix.base.services.orders import mark_order_paid
|
||||
from pretix.base.payment import BasePaymentProvider
|
||||
|
||||
|
||||
@@ -177,7 +177,7 @@ class Paypal(BasePaymentProvider):
|
||||
return
|
||||
|
||||
try:
|
||||
order.mark_paid('paypal', json.dumps(payment.to_dict()))
|
||||
mark_order_paid(order, 'paypal', json.dumps(payment.to_dict()))
|
||||
messages.success(request, _('We successfully received your payment. Thank you!'))
|
||||
except Quota.QuotaExceededException as e:
|
||||
messages.error(request, str(e))
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
from collections import OrderedDict
|
||||
import json
|
||||
import logging
|
||||
|
||||
from django.contrib import messages
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.template.loader import get_template
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django import forms
|
||||
from pretix.base.models import Quota
|
||||
from pretix.base.services.orders import mark_order_paid
|
||||
import stripe
|
||||
|
||||
from pretix.base.payment import BasePaymentProvider
|
||||
|
||||
|
||||
logger = logging.getLogger('pretix.plugins.stripe')
|
||||
|
||||
|
||||
@@ -99,7 +101,7 @@ class Stripe(BasePaymentProvider):
|
||||
else:
|
||||
if charge.status == 'succeeded' and charge.paid:
|
||||
try:
|
||||
order.mark_paid('paypal', str(charge))
|
||||
mark_order_paid(order, 'paypal', str(charge))
|
||||
messages.success(request, _('We successfully received your payment. Thank you!'))
|
||||
except Quota.QuotaExceededException as e:
|
||||
messages.error(request, str(e))
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
from datetime import timedelta
|
||||
|
||||
from django.test import TestCase
|
||||
from django.utils.timezone import now
|
||||
|
||||
from pretix.base.models import (
|
||||
Event, Organizer, Item, ItemVariation,
|
||||
Property, PropertyValue, User, Quota,
|
||||
Order, OrderPosition, CartPosition)
|
||||
from pretix.base.services.orders import mark_order_paid
|
||||
from pretix.base.types import VariationDict
|
||||
|
||||
|
||||
@@ -314,14 +315,14 @@ class OrderTestCase(BaseQuotaTestCase):
|
||||
def test_paid_in_time(self):
|
||||
self.quota.size = 0
|
||||
self.quota.save()
|
||||
self.order.mark_paid()
|
||||
mark_order_paid(self.order)
|
||||
self.order = Order.objects.current.get(identity=self.order.identity)
|
||||
self.assertEqual(self.order.status, Order.STATUS_PAID)
|
||||
|
||||
def test_paid_expired_available(self):
|
||||
self.order.expires = now() - timedelta(days=2)
|
||||
self.order.save()
|
||||
self.order.mark_paid()
|
||||
mark_order_paid(self.order)
|
||||
self.order = Order.objects.current.get(identity=self.order.identity)
|
||||
self.assertEqual(self.order.status, Order.STATUS_PAID)
|
||||
|
||||
@@ -331,7 +332,7 @@ class OrderTestCase(BaseQuotaTestCase):
|
||||
self.quota.size = 1
|
||||
self.quota.save()
|
||||
try:
|
||||
self.order.mark_paid()
|
||||
mark_order_paid(self.order)
|
||||
self.assertFalse(True, 'This should have raised an exception.')
|
||||
except Quota.QuotaExceededException:
|
||||
pass
|
||||
@@ -344,7 +345,7 @@ class OrderTestCase(BaseQuotaTestCase):
|
||||
self.quota.size = 0
|
||||
self.quota.save()
|
||||
try:
|
||||
self.order.mark_paid()
|
||||
mark_order_paid(self.order)
|
||||
self.assertFalse(True, 'This should have raised an exception.')
|
||||
except Quota.QuotaExceededException:
|
||||
pass
|
||||
@@ -356,6 +357,6 @@ class OrderTestCase(BaseQuotaTestCase):
|
||||
self.order.save()
|
||||
self.quota.size = 0
|
||||
self.quota.save()
|
||||
self.order.mark_paid(force=True)
|
||||
mark_order_paid(self.order, force=True)
|
||||
self.order = Order.objects.current.get(identity=self.order.identity)
|
||||
self.assertEqual(self.order.status, Order.STATUS_PAID)
|
||||
|
||||
Reference in New Issue
Block a user