forked from CGM_Public/pretix_original
Provide support for manipulting order status
This commit is contained in:
24
src/pretix/base/migrations/0022_auto_20150320_2239.py
Normal file
24
src/pretix/base/migrations/0022_auto_20150320_2239.py
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import models, migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('pretixbase', '0021_auto_20150320_1622'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='order',
|
||||||
|
name='payment_manual',
|
||||||
|
field=models.BooleanField(verbose_name='Payment state was manually modified', default=False),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='order',
|
||||||
|
name='status',
|
||||||
|
field=models.CharField(verbose_name='Status', max_length=3, choices=[('n', 'pending'), ('p', 'paid'), ('e', 'expired'), ('c', 'cancelled'), ('r', 'refunded')]),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -1537,6 +1537,10 @@ class Order(Versionable):
|
|||||||
verbose_name=_("Payment information"),
|
verbose_name=_("Payment information"),
|
||||||
null=True, blank=True
|
null=True, blank=True
|
||||||
)
|
)
|
||||||
|
payment_manual = models.BooleanField(
|
||||||
|
verbose_name=_("Payment state was manually modified"),
|
||||||
|
default=False
|
||||||
|
)
|
||||||
total = models.DecimalField(
|
total = models.DecimalField(
|
||||||
decimal_places=2, max_digits=10,
|
decimal_places=2, max_digits=10,
|
||||||
verbose_name=_("Total amount")
|
verbose_name=_("Total amount")
|
||||||
@@ -1590,7 +1594,7 @@ class Order(Versionable):
|
|||||||
return True
|
return True
|
||||||
return False # nothing there to modify
|
return False # nothing there to modify
|
||||||
|
|
||||||
def mark_paid(self, provider, info, date=None):
|
def mark_paid(self, provider=None, info=None, date=None, manual=None):
|
||||||
"""
|
"""
|
||||||
Mark this order as paid. This clones the order object, sets the payment provider,
|
Mark this order as paid. This clones the order object, sets the payment provider,
|
||||||
info and date and returns the cloned order object.
|
info and date and returns the cloned order object.
|
||||||
@@ -1604,9 +1608,11 @@ class Order(Versionable):
|
|||||||
:type date: datetime
|
:type date: datetime
|
||||||
"""
|
"""
|
||||||
order = self.clone()
|
order = self.clone()
|
||||||
order.payment_provider = provider
|
order.payment_provider = provider or order.payment_provider
|
||||||
order.payment_info = info
|
order.payment_info = info or order.payment_info
|
||||||
order.payment_date = date or now()
|
order.payment_date = date or now()
|
||||||
|
if manual is not None:
|
||||||
|
order.payment_manual = manual
|
||||||
order.status = Order.STATUS_PAID
|
order.status = Order.STATUS_PAID
|
||||||
order.save()
|
order.save()
|
||||||
return order
|
return order
|
||||||
|
|||||||
@@ -47,3 +47,10 @@ nav.navbar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-toolbar {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.container-fluid > .alert:first-child {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
@@ -74,6 +74,13 @@
|
|||||||
</nav>
|
</nav>
|
||||||
<div id="page-wrapper">
|
<div id="page-wrapper">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
|
{% if messages %}
|
||||||
|
{% for message in messages %}
|
||||||
|
<div class="alert {{ message.tags }}">
|
||||||
|
{{ message }}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
32
src/pretix/control/templates/pretixcontrol/order/cancel.html
Normal file
32
src/pretix/control/templates/pretixcontrol/order/cancel.html
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
{% extends "pretixcontrol/event/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% block title %}
|
||||||
|
{% trans "Cancel order" %}
|
||||||
|
{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<h1>
|
||||||
|
{% trans "Cancel order" %}
|
||||||
|
</h1>
|
||||||
|
<p>{% blocktrans trimmed %}
|
||||||
|
Do you really want to cancel this order? You cannot revert this action.
|
||||||
|
{% endblocktrans %}</p>
|
||||||
|
|
||||||
|
<form method="post" href="">
|
||||||
|
{% csrf_token %}
|
||||||
|
<input type="hidden" name="status" value="c" />
|
||||||
|
<div class="row checkout-button-row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<a class="btn btn-block btn-default btn-lg"
|
||||||
|
href="{% url "control:event.order" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}">
|
||||||
|
{% trans "No, take me back" %}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 col-md-offset-4">
|
||||||
|
<button class="btn btn-block btn-danger btn-lg" type="submit">
|
||||||
|
{% trans "Yes, cancel order" %}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="clearfix"></div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
||||||
@@ -12,6 +12,27 @@
|
|||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
{% include "pretixcontrol/orders/fragment_order_status.html" with order=order class="pull-right" %}
|
{% include "pretixcontrol/orders/fragment_order_status.html" with order=order class="pull-right" %}
|
||||||
</h1>
|
</h1>
|
||||||
|
{% if order.status == 'n' or order.status == 'p' %}
|
||||||
|
<form action="{% url "control:event.order.transition" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}"
|
||||||
|
method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="btn-toolbar" role="toolbar">
|
||||||
|
<div class="btn-group" role="group">
|
||||||
|
{% if order.status == 'n' %}
|
||||||
|
<button name="status" value="p" class="btn btn-default">{% trans "Mark as paid" %}</button>
|
||||||
|
<a href="{% url "control:event.order.transition" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}?status=c" class="btn btn-default">
|
||||||
|
{% trans "Cancel order" %}
|
||||||
|
</a>
|
||||||
|
{% elif order.status == 'p' %}
|
||||||
|
<button name="status" value="n" class="btn btn-default">{% trans "Mark as not paid" %}</button>
|
||||||
|
<a href="{% url "control:event.order.transition" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}?status=r" class="btn btn-default">
|
||||||
|
{% trans "Refund order" %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
<div class="panel panel-primary items">
|
<div class="panel panel-primary items">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h3 class="panel-title">
|
<h3 class="panel-title">
|
||||||
@@ -86,6 +107,11 @@
|
|||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
|
{% if order.payment_manual %}
|
||||||
|
<div class="alert alert-info">
|
||||||
|
{% trans "The payment state of this order was manually modified." %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
{{ payment }}
|
{{ payment }}
|
||||||
{% if order.status == 'n' %}
|
{% if order.status == 'n' %}
|
||||||
<p>{% blocktrans trimmed with date=order.expires %}
|
<p>{% blocktrans trimmed with date=order.expires %}
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ urlpatterns = [
|
|||||||
url(r'^quotas/(?P<quota>[0-9a-f-]+)/delete$', item.QuotaDelete.as_view(),
|
url(r'^quotas/(?P<quota>[0-9a-f-]+)/delete$', item.QuotaDelete.as_view(),
|
||||||
name='event.items.quotas.delete'),
|
name='event.items.quotas.delete'),
|
||||||
url(r'^quotas/add$', item.QuotaCreate.as_view(), name='event.items.quotas.add'),
|
url(r'^quotas/add$', item.QuotaCreate.as_view(), name='event.items.quotas.add'),
|
||||||
|
url(r'^orders/(?P<code>[0-9A-Z]+)/transition$', orders.OrderTransition.as_view(),
|
||||||
|
name='event.order.transition'),
|
||||||
url(r'^orders/(?P<code>[0-9A-Z]+)/$', orders.OrderDetail.as_view(), name='event.order'),
|
url(r'^orders/(?P<code>[0-9A-Z]+)/$', orders.OrderDetail.as_view(), name='event.order'),
|
||||||
url(r'^orders/$', orders.OrderList.as_view(), name='event.orders'),
|
url(r'^orders/$', orders.OrderList.as_view(), name='event.orders'),
|
||||||
])),
|
])),
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
from itertools import groupby
|
from itertools import groupby
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from django.http import HttpResponse
|
||||||
|
from django.shortcuts import redirect, render
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.views.generic import ListView, DetailView
|
from django.views.generic import ListView, DetailView
|
||||||
|
|
||||||
@@ -21,11 +26,9 @@ class OrderList(EventPermissionRequiredMixin, ListView):
|
|||||||
).select_related("user")
|
).select_related("user")
|
||||||
|
|
||||||
|
|
||||||
class OrderDetail(EventPermissionRequiredMixin, DetailView):
|
class OrderView(DetailView):
|
||||||
model = Order
|
|
||||||
context_object_name = 'order'
|
context_object_name = 'order'
|
||||||
template_name = 'pretixcontrol/order/index.html'
|
model = Order
|
||||||
permission = 'can_view_orders'
|
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
def get_object(self, queryset=None):
|
||||||
return Order.objects.current.get(
|
return Order.objects.current.get(
|
||||||
@@ -33,6 +36,15 @@ class OrderDetail(EventPermissionRequiredMixin, DetailView):
|
|||||||
code=self.kwargs['code'].upper()
|
code=self.kwargs['code'].upper()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def order(self):
|
||||||
|
return self.get_object()
|
||||||
|
|
||||||
|
|
||||||
|
class OrderDetail(EventPermissionRequiredMixin, OrderView):
|
||||||
|
template_name = 'pretixcontrol/order/index.html'
|
||||||
|
permission = 'can_view_orders'
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def payment_provider(self):
|
def payment_provider(self):
|
||||||
responses = register_payment_providers.send(self.request.event)
|
responses = register_payment_providers.send(self.request.event)
|
||||||
@@ -85,3 +97,51 @@ class OrderDetail(EventPermissionRequiredMixin, DetailView):
|
|||||||
'total': self.object.total,
|
'total': self.object.total,
|
||||||
'payment_fee': self.object.payment_fee,
|
'payment_fee': self.object.payment_fee,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class OrderTransition(EventPermissionRequiredMixin, OrderView):
|
||||||
|
permission = 'can_view_orders'
|
||||||
|
|
||||||
|
def post(self, *args, **kwargs):
|
||||||
|
to = self.request.POST.get('status', '')
|
||||||
|
if self.order.status == 'n' and to == 'p':
|
||||||
|
self.order.mark_paid(manual=True)
|
||||||
|
messages.success(self.request, _('The order has been marked as paid.'))
|
||||||
|
elif self.order.status == 'n' and to == 'c':
|
||||||
|
order = self.order.clone()
|
||||||
|
order.status = Order.STATUS_CANCELLED
|
||||||
|
order.save()
|
||||||
|
messages.success(self.request, _('The order has been cancelled.'))
|
||||||
|
elif self.order.status == 'p' and to == 'n':
|
||||||
|
order = self.order.clone()
|
||||||
|
order.status = Order.STATUS_PENDING
|
||||||
|
order.payment_manual = True
|
||||||
|
order.save()
|
||||||
|
messages.success(self.request, _('The order has been marked as not paid.'))
|
||||||
|
return redirect(reverse(
|
||||||
|
'control:event.order',
|
||||||
|
kwargs={
|
||||||
|
'event': self.request.event.slug,
|
||||||
|
'organizer': self.request.event.organizer.slug,
|
||||||
|
'code': self.order.code,
|
||||||
|
}
|
||||||
|
))
|
||||||
|
|
||||||
|
def get(self, *args, **kwargs):
|
||||||
|
to = self.request.GET.get('status', '')
|
||||||
|
if self.order.status == 'n' and to == 'c':
|
||||||
|
return render(self.request, 'pretixcontrol/order/cancel.html', {
|
||||||
|
'order': self.order,
|
||||||
|
})
|
||||||
|
elif self.order.status == 'p' and to == 'r':
|
||||||
|
messages.error(self.request, _('Refunding orders is not yet implemented.'))
|
||||||
|
return redirect(reverse(
|
||||||
|
'control:event.order',
|
||||||
|
kwargs={
|
||||||
|
'event': self.request.event.slug,
|
||||||
|
'organizer': self.request.event.organizer.slug,
|
||||||
|
'code': self.order.code,
|
||||||
|
}
|
||||||
|
))
|
||||||
|
else:
|
||||||
|
return HttpResponse(status=405)
|
||||||
|
|||||||
Reference in New Issue
Block a user