Refs #126 -- Show order history

This commit is contained in:
Raphael Michel
2016-03-22 13:04:38 +01:00
parent 6280e06e7c
commit 70067fd91a
9 changed files with 259 additions and 173 deletions

View File

@@ -33,7 +33,6 @@ def cached_file_delete(sender, instance, **kwargs):
class LoggingMixin:
logentries = GenericRelation('LogEntry')
def log_action(self, action, data=None, user=None):
"""
@@ -59,6 +58,10 @@ class LoggingMixin:
class LoggedModel(models.Model, LoggingMixin):
logentries = GenericRelation('LogEntry')
class Meta:
abstract = True
def all_logentries(self):
return self.logentries.all().select_related('user')

View File

@@ -28,3 +28,14 @@ class LogEntry(models.Model):
event = models.ForeignKey('Event', null=True, blank=True, on_delete=models.CASCADE)
action_type = models.CharField(max_length=255)
data = models.TextField(default='{}')
class Meta:
ordering = ('-datetime', )
def display(self):
from ..signals import logentry_display
for receiver, response in logentry_display.send(self.event, logentry=self):
if response:
return response
return self.action_type

View File

@@ -87,3 +87,11 @@ as the first argument.
order_paid = EventPluginSignal(
providing_args=["order"]
)
"""
This signal is sent out every time we need to display a LogEntry object and we
don't know how to turn it into human-readable text.
"""
logentry_display = EventPluginSignal(
providing_args=["logentry"]
)

View File

@@ -7,5 +7,6 @@ class PretixControlConfig(AppConfig):
def ready(self):
from .views import dashboards # noqa
from . import logdisplay # noqa
default_app_config = 'pretix.control.PretixControlConfig'

View File

@@ -0,0 +1,20 @@
from django.dispatch import receiver
from django.utils.translation import ugettext_lazy as _
from pretix.base.signals import logentry_display
@receiver(signal=logentry_display, dispatch_uid="pretixcontrol_logentry_display")
def pretixcontrol_logentry_display(sender, logentry, **kwargs):
plains = {
'pretix.event.order.modified': _('The order details have been modified.'),
'pretix.event.order.unpaid': _('The order has been marked as unpaid.'),
'pretix.event.order.resend': _('The link to the order detail page has been resent to the user.'),
'pretix.event.order.expirychanged': _('The order\'s expiry date has been changed.'),
'pretix.event.order.paid': _('The order has been marked as paid.'),
'pretix.event.order.refunded': _('The order has been refunded.'),
'pretix.event.order.cancelled': _('The order has been cancelled.'),
'pretix.event.order.placed': _('The order has been created.'),
}
if logentry.action_type in plains:
return plains[logentry.action_type]

View File

@@ -0,0 +1,16 @@
<ul class="list-group">
{% for log in obj.all_logentries %}
<li class="list-group-item logentry">
<p class="meta">
<span class="fa fa-clock-o"></span> {{ log.datetime|date:"SHORT_DATETIME_FORMAT" }}
{% if log.user %}
<br/><span class="fa fa-user"></span> {{ log.user }}
{% endif %}
</p>
<p>
{{ log.display }}
</p>
</li>
{% endfor %}
</ul>

View File

@@ -47,186 +47,202 @@
</form>
{% endif %}
{% endif %}
<div class="panel panel-primary items">
<div class="panel-heading">
<h3 class="panel-title">
{% trans "Order details" %}
</h3>
</div>
<div class="panel-body">
<dl class="dl-horizontal">
<dt>{% trans "Order code" %}</dt>
<dd>{{ order.code }}</dd>
<dt>{% trans "Order date" %}</dt>
<dd>{{ order.datetime }}</dd>
{% if order.status == "p" %}
<dt>{% trans "Payment date" %}</dt>
<dd>{{ order.payment_date }}</dd>
{% elif order.status == "n" %}
<dt>{% trans "Expiry date" %}</dt>
<dd>{{ order.expires }}</dd>
{% endif %}
<dt>{% trans "User" %}</dt>
<dd>
{{ order.email }}&nbsp;&nbsp;
<form class="form-inline" style="display: inline;" method="post"
action="{% url "control:event.order.resendlink" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}">
{% csrf_token %}
<button class="btn btn-default btn-xs">
{% trans "Resend link" %}
</button>
</form>
</dd>
{% if invoices %}
<dt>{% trans "Invoices" %}</dt>
<dd>
{% for i in invoices %}
<a href="{% url "control:event.invoice.download" invoice=i.pk event=request.event.slug organizer=request.event.organizer.slug %}">
{% if i.is_cancellation %}{% trans "Cancellation" %}{% else %}{% trans "Invoice" %}{% endif %}
{{ i.number }}</a> ({{ i.date|date:"SHORT_DATE_FORMAT" }})
{% if forloop.revcounter0 > 0 %}
<br/>
{% endif %}
{% endfor %}
</dd>
{% endif %}
</dl>
</div>
</div>
<div class="panel panel-default items">
<div class="panel-heading">
<h3 class="panel-title">
{% trans "Ordered items" %}
</h3>
</div>
<div class="panel-body">
{% for line in items.positions %}
<div class="row-fluid product-row">
<div class="col-md-4 col-xs-6">
<strong>{{ line.item.name }}</strong>
{% if line.variation %}
{{ line.variation }}
{% endif %}
{% if line.voucher %}
<br/><span class="fa fa-ticket"></span> {% trans "Voucher code used:" %}
<a href="{% url "control:event.voucher" event=request.event.slug organizer=request.event.organizer.slug voucher=line.voucher.pk %}">
{{ line.voucher.code }}
</a>
{% endif %}
{% if line.has_questions %}
<dl>
{% if line.item.admission and event.settings.attendee_names_asked %}
<dt>{% trans "Attendee name" %}</dt>
<dd>{% if line.attendee_name %}{{ line.attendee_name }}{% else %}
<em>{% trans "not answered" %}</em>{% endif %}</dd>
{% endif %}
{% for q in line.questions %}
<dt>{{ q.question }}</dt>
<dd>{% if q.answer %}{{ q.answer }}{% else %}
<em>{% trans "not answered" %}</em>{% endif %}</dd>
{% endfor %}
</dl>
{% endif %}
</div>
<div class="col-md-2 col-xs-6 count">
{{ line.count }}
</div>
<div class="col-md-3 col-xs-6 price">
{{ event.currency }} {{ line.price|floatformat:2 }}
</div>
<div class="col-md-3 col-xs-6 price">
<strong>{{ event.currency }} {{ line.total|floatformat:2 }}</strong>
{% if line.tax_rate %}
<br/>
<small>{% blocktrans trimmed with rate=line.tax_rate %}
incl. {{ rate }}% taxes
{% endblocktrans %}</small>
{% endif %}
</div>
<div class="clearfix"></div>
</div>
{% endfor %}
{% if items.payment_fee %}
<div class="row-fluid product-row">
<div class="col-md-4 col-xs-6">
<strong>{% trans "Payment method fee" %}</strong>
</div>
<div class="col-md-3 col-xs-6 col-md-offset-5 price">
<strong>{{ event.currency }} {{ items.payment_fee|floatformat:2 }}</strong>
{% if order.payment_fee_tax_rate %}
<br/>
<small>{% blocktrans trimmed with rate=order.payment_fee_tax_rate %}
incl. {{ rate }}% taxes
{% endblocktrans %}</small>
{% endif %}
</div>
<div class="clearfix"></div>
</div>
{% endif %}
<div class="row-fluid product-row total">
<div class="col-md-4 col-xs-6">
<strong>{% trans "Total" %}</strong>
</div>
<div class="col-md-3 col-xs-6 col-md-offset-5 price">
<strong>{{ event.currency }} {{ items.total|floatformat:2 }}</strong>
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
<div class="row">
<div class="{% if request.event.settings.invoice_address_asked %}col-md-6{% else %}col-md-12{% endif %}">
<div class="panel panel-default items">
<div class="col-xs-12 col-lg-10">
<div class="panel panel-primary items">
<div class="panel-heading">
<h3 class="panel-title">
{% trans "Payment information" %}
{% trans "Order details" %}
</h3>
</div>
<div class="panel-body">
{% if order.payment_manual %}
<div class="alert alert-info">
{% trans "The payment state of this order was manually modified." %}
<dl class="dl-horizontal">
<dt>{% trans "Order code" %}</dt>
<dd>{{ order.code }}</dd>
<dt>{% trans "Order date" %}</dt>
<dd>{{ order.datetime }}</dd>
{% if order.status == "p" %}
<dt>{% trans "Payment date" %}</dt>
<dd>{{ order.payment_date }}</dd>
{% elif order.status == "n" %}
<dt>{% trans "Expiry date" %}</dt>
<dd>{{ order.expires }}</dd>
{% endif %}
<dt>{% trans "User" %}</dt>
<dd>
{{ order.email }}&nbsp;&nbsp;
<form class="form-inline" style="display: inline;" method="post"
action="{% url "control:event.order.resendlink" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}">
{% csrf_token %}
<button class="btn btn-default btn-xs">
{% trans "Resend link" %}
</button>
</form>
</dd>
{% if invoices %}
<dt>{% trans "Invoices" %}</dt>
<dd>
{% for i in invoices %}
<a href="{% url "control:event.invoice.download" invoice=i.pk event=request.event.slug organizer=request.event.organizer.slug %}">
{% if i.is_cancellation %}{% trans "Cancellation" %}{% else %}{% trans "Invoice" %}{% endif %}
{{ i.number }}</a> ({{ i.date|date:"SHORT_DATE_FORMAT" }})
{% if forloop.revcounter0 > 0 %}
<br/>
{% endif %}
{% endfor %}
</dd>
{% endif %}
</dl>
</div>
</div>
<div class="panel panel-default items">
<div class="panel-heading">
<h3 class="panel-title">
{% trans "Ordered items" %}
</h3>
</div>
<div class="panel-body">
{% for line in items.positions %}
<div class="row-fluid product-row">
<div class="col-md-4 col-xs-6">
<strong>{{ line.item.name }}</strong>
{% if line.variation %}
{{ line.variation }}
{% endif %}
{% if line.voucher %}
<br/><span class="fa fa-ticket"></span> {% trans "Voucher code used:" %}
<a href="{% url "control:event.voucher" event=request.event.slug organizer=request.event.organizer.slug voucher=line.voucher.pk %}">
{{ line.voucher.code }}
</a>
{% endif %}
{% if line.has_questions %}
<dl>
{% if line.item.admission and event.settings.attendee_names_asked %}
<dt>{% trans "Attendee name" %}</dt>
<dd>{% if line.attendee_name %}{{ line.attendee_name }}{% else %}
<em>{% trans "not answered" %}</em>{% endif %}</dd>
{% endif %}
{% for q in line.questions %}
<dt>{{ q.question }}</dt>
<dd>{% if q.answer %}{{ q.answer }}{% else %}
<em>{% trans "not answered" %}</em>{% endif %}</dd>
{% endfor %}
</dl>
{% endif %}
</div>
<div class="col-md-2 col-xs-6 count">
{{ line.count }}
</div>
<div class="col-md-3 col-xs-6 price">
{{ event.currency }} {{ line.price|floatformat:2 }}
</div>
<div class="col-md-3 col-xs-6 price">
<strong>{{ event.currency }} {{ line.total|floatformat:2 }}</strong>
{% if line.tax_rate %}
<br/>
<small>{% blocktrans trimmed with rate=line.tax_rate %}
incl. {{ rate }}% taxes
{% endblocktrans %}</small>
{% endif %}
</div>
<div class="clearfix"></div>
</div>
{% endfor %}
{% if items.payment_fee %}
<div class="row-fluid product-row">
<div class="col-md-4 col-xs-6">
<strong>{% trans "Payment method fee" %}</strong>
</div>
<div class="col-md-3 col-xs-6 col-md-offset-5 price">
<strong>{{ event.currency }} {{ items.payment_fee|floatformat:2 }}</strong>
{% if order.payment_fee_tax_rate %}
<br/>
<small>{% blocktrans trimmed with rate=order.payment_fee_tax_rate %}
incl. {{ rate }}% taxes
{% endblocktrans %}</small>
{% endif %}
</div>
<div class="clearfix"></div>
</div>
{% endif %}
{{ payment }}
{% if order.status == 'n' %}
<p>{% blocktrans trimmed with date=order.expires %}
The payment has to be completed before {{ date }}.
{% endblocktrans %}</p>
{% endif %}
<div class="row-fluid product-row total">
<div class="col-md-4 col-xs-6">
<strong>{% trans "Total" %}</strong>
</div>
<div class="col-md-3 col-xs-6 col-md-offset-5 price">
<strong>{{ event.currency }} {{ items.total|floatformat:2 }}</strong>
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
<div class="row">
<div class="{% if request.event.settings.invoice_address_asked %}col-md-6{% else %}col-md-12{% endif %}">
<div class="panel panel-default items">
<div class="panel-heading">
<h3 class="panel-title">
{% trans "Payment information" %}
</h3>
</div>
<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 }}
{% if order.status == 'n' %}
<p>{% blocktrans trimmed with date=order.expires %}
The payment has to be completed before {{ date }}.
{% endblocktrans %}</p>
{% endif %}
</div>
</div>
</div>
{% if request.event.settings.invoice_address_asked %}
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
{% trans "Invoice information" %}
</h3>
</div>
<div class="panel-body">
<dl class="dl-horizontal">
<dt>{% trans "Company" %}</dt>
<dd>{{ order.invoice_address.company }}</dd>
<dt>{% trans "Name" %}</dt>
<dd>{{ order.invoice_address.name }}</dd>
<dt>{% trans "Address" %}</dt>
<dd>{{ order.invoice_address.street|linebreaksbr }}</dd>
<dt>{% trans "ZIP code and city" %}</dt>
<dd>{{ order.invoice_address.zipcode }} {{ addr.city }}</dd>
<dt>{% trans "Country" %}</dt>
<dd>{{ order.invoice_address.country }}</dd>
<dt>{% trans "Phone" %}</dt>
<dd>{{ order.invoice_address.phone }}</dd>
{% if request.event.settings.invoice_address_vatid %}
<dt>{% trans "VAT ID" %}</dt>
<dd>{{ order.invoice_address.vat_id }}</dd>
{% endif %}
</dl>
</div>
</div>
</div>
{% endif %}
</div>
</div>
{% if request.event.settings.invoice_address_asked %}
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
{% trans "Invoice information" %}
</h3>
</div>
<div class="panel-body">
<dl class="dl-horizontal">
<dt>{% trans "Company" %}</dt>
<dd>{{ order.invoice_address.company }}</dd>
<dt>{% trans "Name" %}</dt>
<dd>{{ order.invoice_address.name }}</dd>
<dt>{% trans "Address" %}</dt>
<dd>{{ order.invoice_address.street|linebreaksbr }}</dd>
<dt>{% trans "ZIP code and city" %}</dt>
<dd>{{ order.invoice_address.zipcode }} {{ addr.city }}</dd>
<dt>{% trans "Country" %}</dt>
<dd>{{ order.invoice_address.country }}</dd>
<dt>{% trans "Phone" %}</dt>
<dd>{{ order.invoice_address.phone }}</dd>
{% if request.event.settings.invoice_address_vatid %}
<dt>{% trans "VAT ID" %}</dt>
<dd>{{ order.invoice_address.vat_id }}</dd>
{% endif %}
</dl>
</div>
<div class="col-xs-12 col-lg-2">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
{% trans "Order history" %}
</h3>
</div>
{% include "pretixcontrol/includes/logs.html" with obj=order %}
</div>
{% endif %}
</div>
</div>
{% endblock %}

View File

@@ -180,7 +180,7 @@ class OrderTransition(OrderView):
self.order.status = Order.STATUS_PENDING
self.order.payment_manual = True
self.order.save()
self.order.log_action('pretix.base.order.unpaid', user=self.request.user)
self.order.log_action('pretix.event.order.unpaid', user=self.request.user)
messages.success(self.request, _('The order has been marked as not paid.'))
elif self.order.status == 'p' and to == 'r':
ret = self.payment_provider.order_control_refund_perform(self.request, self.order)
@@ -221,7 +221,7 @@ class OrderResendLink(OrderView):
self.order.event, locale=self.order.locale
)
messages.success(self.request, _('The email has been queued to be sent.'))
self.order.log_action('pretix.base.order.resend', user=self.request.user)
self.order.log_action('pretix.event.order.resend', user=self.request.user)
return redirect(self.get_order_url())
@@ -305,7 +305,7 @@ class OrderExtend(OrderView):
if self.form.is_valid():
if oldvalue > now():
messages.success(self.request, _('The payment term has been changed.'))
self.order.log_action('pretix.order.changed', user=self.request.user, data={
self.order.log_action('pretix.event.order.expirychanged', user=self.request.user, data={
'expires': self.order.expires
})
self.form.save()
@@ -315,7 +315,7 @@ class OrderExtend(OrderView):
is_available = self.order._is_still_available()
if is_available is True:
self.form.save()
self.order.log_action('pretix.order.changed', user=self.request.user, data={
self.order.log_action('pretix.event.order.expirychanged', user=self.request.user, data={
'expires': self.order.expires
})
messages.success(self.request, _('The payment term has been changed.'))

View File

@@ -16,6 +16,17 @@
display: none;
}
}
#sumtoggle {
margin-top: 20px;
}
.logentry {
.meta {
font-size: 12px;
margin: 0 0 5px;
}
p:last-child {
margin-bottom: 0;
}
}