Add Order.custom_followup_at (#2124)

This commit is contained in:
Raphael Michel
2021-06-11 17:08:13 +02:00
committed by GitHub
parent 3235f90876
commit 97d67d58d5
14 changed files with 108 additions and 11 deletions

View File

@@ -654,7 +654,7 @@ class OrderSerializer(I18nAwareModelSerializer):
model = Order
fields = (
'code', 'status', 'testmode', 'secret', 'email', 'phone', 'locale', 'datetime', 'expires', 'payment_date',
'payment_provider', 'fees', 'total', 'comment', 'invoice_address', 'positions', 'downloads',
'payment_provider', 'fees', 'total', 'comment', 'custom_followup_at', 'invoice_address', 'positions', 'downloads',
'checkin_attention', 'last_modified', 'payments', 'refunds', 'require_approval', 'sales_channel',
'url', 'customer'
)
@@ -685,7 +685,7 @@ class OrderSerializer(I18nAwareModelSerializer):
def update(self, instance, validated_data):
# Even though all fields that shouldn't be edited are marked as read_only in the serializer
# (hopefully), we'll be extra careful here and be explicit about the model fields we update.
update_fields = ['comment', 'checkin_attention', 'email', 'locale', 'phone']
update_fields = ['comment', 'custom_followup_at', 'checkin_attention', 'email', 'locale', 'phone']
if 'invoice_address' in validated_data:
iadata = validated_data.pop('invoice_address')
@@ -925,6 +925,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
min_length=5
)
comment = serializers.CharField(required=False, allow_blank=True)
custom_followup_at = serializers.DateField(required=False, allow_null=True)
payment_provider = serializers.CharField(required=False, allow_null=True)
payment_info = CompatibleJSONField(required=False)
consume_carts = serializers.ListField(child=serializers.CharField(), required=False)
@@ -943,7 +944,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
model = Order
fields = ('code', 'status', 'testmode', 'email', 'phone', 'locale', 'payment_provider', 'fees', 'comment', 'sales_channel',
'invoice_address', 'positions', 'checkin_attention', 'payment_info', 'payment_date', 'consume_carts',
'force', 'send_email', 'simulate', 'customer')
'force', 'send_email', 'simulate', 'customer', 'custom_followup_at')
def validate_payment_provider(self, pp):
if pp is None:

View File

@@ -692,6 +692,16 @@ class OrderViewSet(viewsets.ModelViewSet):
}
)
if 'custom_followup_at' in self.request.data and serializer.instance.custom_followup_at != self.request.data.get('custom_followup_at'):
serializer.instance.log_action(
'pretix.event.order.custom_followup_at',
user=self.request.user,
auth=self.request.auth,
data={
'new_custom_followup_at': self.request.data.get('custom_followup_at')
}
)
if 'checkin_attention' in self.request.data and serializer.instance.checkin_attention != self.request.data.get('checkin_attention'):
serializer.instance.log_action(
'pretix.event.order.checkin_attention',

View File

@@ -288,6 +288,7 @@ class OrderListExporter(MultiSheetListExporter):
headers.append(_('Sales channel'))
headers.append(_('Requires special attention'))
headers.append(_('Comment'))
headers.append(_('Follow-up date'))
headers.append(_('Positions'))
headers.append(_('E-mail address verified'))
headers.append(_('Payment providers'))
@@ -393,6 +394,7 @@ class OrderListExporter(MultiSheetListExporter):
row.append(order.sales_channel)
row.append(_('Yes') if order.checkin_attention else _('No'))
row.append(order.comment or "")
row.append(order.custom_followup_at.strftime("%Y-%m-%d") if order.custom_followup_at else "")
row.append(order.pcnt)
row.append(_('Yes') if order.email_known_to_work else _('No'))
row.append(', '.join([
@@ -574,6 +576,7 @@ class OrderListExporter(MultiSheetListExporter):
_('Seat row'),
_('Seat number'),
_('Order comment'),
_('Follow-up date'),
]
questions = list(Question.objects.filter(event__in=self.events))
@@ -677,6 +680,7 @@ class OrderListExporter(MultiSheetListExporter):
row += ['', '', '', '', '']
row.append(order.comment)
row.append(order.custom_followup_at.strftime("%Y-%m-%d") if order.custom_followup_at else "")
acache = {}
for a in op.answers.all():
# We do not want to localize Date, Time and Datetime question answers, as those can lead
@@ -780,7 +784,7 @@ class PaymentListExporter(ListExporter):
headers = [
_('Event slug'), _('Order'), _('Payment ID'), _('Creation date'), _('Completion date'), _('Status'),
_('Status code'), _('Amount'), _('Payment method'), _('Comment')
_('Status code'), _('Amount'), _('Payment method'), _('Comment'),
]
yield headers

View File

@@ -0,0 +1,25 @@
# Generated by Django 3.2.3 on 2021-06-11 13:55
import django.db.models.manager
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pretixbase', '0192_checkin_more_fields'),
]
operations = [
migrations.AlterModelManagers(
name='checkin',
managers=[
('all', django.db.models.manager.Manager()),
],
),
migrations.AddField(
model_name='order',
name='custom_followup_at',
field=models.DateField(blank=True, null=True),
),
]

View File

@@ -60,7 +60,7 @@ from django.utils.crypto import get_random_string
from django.utils.encoding import escape_uri_path
from django.utils.formats import date_format
from django.utils.functional import cached_property
from django.utils.timezone import make_aware, now
from django.utils.timezone import get_current_timezone, make_aware, now
from django.utils.translation import gettext_lazy as _, pgettext_lazy
from django_countries.fields import Country
from django_scopes import ScopedManager, scopes_disabled
@@ -217,6 +217,11 @@ class Order(LockModel, LoggedModel):
help_text=_("The text entered in this field will not be visible to the user and is available for your "
"convenience.")
)
custom_followup_at = models.DateField(
verbose_name=_("Follow-up date"),
help_text=_('We\'ll show you this order to be due for a follow-up on this day.'),
null=True, blank=True
)
checkin_attention = models.BooleanField(
verbose_name=_('Requires special attention'),
default=False,
@@ -300,6 +305,10 @@ class Order(LockModel, LoggedModel):
"""
return self.all_fees(manager='objects')
@property
def custom_followup_due(self):
return self.custom_followup_at and self.custom_followup_at <= now().astimezone(get_current_timezone()).date()
@cached_property
@scopes_disabled()
def count_positions(self):

View File

@@ -205,6 +205,10 @@ class OrderFilterForm(FilterForm):
('na', _('Approved, payment pending')),
('pa', _('Approval pending')),
)),
(_('Follow-up date'), (
('custom_followup_at', _('Follow-up configured')),
('custom_followup_due', _('Follow-up due')),
)),
('testmode', _('Test mode')),
),
required=False,
@@ -324,6 +328,14 @@ class OrderFilterForm(FilterForm):
status=Order.STATUS_PENDING,
require_approval=False
)
elif s == 'custom_followup_at':
qs = qs.filter(
custom_followup_at__isnull=False
)
elif s == 'custom_followup_due':
qs = qs.filter(
custom_followup_at__lte=now().astimezone(get_current_timezone()).date()
)
elif s == 'testmode':
qs = qs.filter(
testmode=True

View File

@@ -230,12 +230,13 @@ class ExporterForm(forms.Form):
class CommentForm(I18nModelForm):
class Meta:
model = Order
fields = ['comment', 'checkin_attention']
fields = ['comment', 'checkin_attention', 'custom_followup_at']
widgets = {
'comment': forms.Textarea(attrs={
'rows': 3,
'class': 'helper-width-100',
}),
'custom_followup_at': DatePickerWidget(),
}

View File

@@ -360,6 +360,7 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs):
'pretix.event.order.invoice.regenerated': _('The invoice has been regenerated.'),
'pretix.event.order.invoice.reissued': _('The invoice has been reissued.'),
'pretix.event.order.comment': _('The order\'s internal comment has been updated.'),
'pretix.event.order.custom_followup_at': _('The order\'s follow-up date has been updated.'),
'pretix.event.order.checkin_attention': _('The order\'s flag to require attention at check-in has been '
'toggled.'),
'pretix.event.order.payment.changed': _('A new payment {local_id} has been started instead of the previous one.'),

View File

@@ -890,10 +890,9 @@
<form class="form" method="post"
action="{% url "control:event.order.comment" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}">
{% csrf_token %}
<div class="row">
{% bootstrap_field comment_form.comment layout="horizontal" show_help=True show_label=False horizontal_field_class="col-md-12" %}
{% bootstrap_field comment_form.checkin_attention layout="horizontal" show_help=True show_label=False horizontal_field_class="col-md-12" %}
</div>
{% bootstrap_field comment_form.comment show_help=True show_label=False %}
{% bootstrap_field comment_form.custom_followup_at %}
{% bootstrap_field comment_form.checkin_attention show_help=True show_label=False %}
<button class="btn btn-default">
{% trans "Update comment" %}
</button>

View File

@@ -134,6 +134,11 @@
{% if o.testmode %}
<span class="label label-warning">{% trans "TEST MODE" %}</span>
{% endif %}
{% if o.custom_followup_due %}
<span class="label label-danger">{% blocktrans with date=o.custom_followup_at|date:"SHORT_DATE_FORMAT" context "followup" %}TODO {{ date }}{% endblocktrans %}</span>
{% elif o.custom_followup_at %}
<span class="label label-default">{% blocktrans with date=o.custom_followup_at|date:"SHORT_DATE_FORMAT" context "followup" %}TODO {{ date }}{% endblocktrans %}</span>
{% endif %}
</td>
<td>
{{ o.email|default_if_none:"" }}

View File

@@ -69,6 +69,11 @@
{% if o.testmode %}
<span class="label label-warning">{% trans "TEST MODE" %}</span>
{% endif %}
{% if o.custom_followup_due %}
<span class="label label-danger">{% blocktrans with date=o.custom_followup_at|date:"SHORT_DATE_FORMAT" context "followup" %}TODO {{ date }}{% endblocktrans %}</span>
{% elif o.custom_followup_at %}
<span class="label label-default">{% blocktrans with date=o.custom_followup_at|date:"SHORT_DATE_FORMAT" context "followup" %}TODO {{ date }}{% endblocktrans %}</span>
{% endif %}
</td>
<td>{{ o.event.name }}</td>
<td>

View File

@@ -303,6 +303,7 @@ class OrderDetail(OrderView):
ctx['invoices'] = list(self.order.invoices.all().select_related('event'))
ctx['comment_form'] = CommentForm(initial={
'comment': self.order.comment,
'custom_followup_at': self.order.custom_followup_at,
'checkin_attention': self.order.checkin_attention
})
ctx['display_locale'] = dict(settings.LANGUAGES)[self.object.locale or self.request.event.settings.locale]
@@ -487,12 +488,21 @@ class OrderComment(OrderView):
'new_comment': form.cleaned_data.get('comment')
})
if form.cleaned_data.get('custom_followup_at') != self.order.custom_followup_at:
self.order.custom_followup_at = form.cleaned_data.get('custom_followup_at')
self.order.log_action('pretix.event.order.custom_followup_at', user=self.request.user, data={
'new_custom_followup_at': form.cleaned_data.get('custom_followup_at')
})
if form.cleaned_data.get('checkin_attention') != self.order.checkin_attention:
self.order.checkin_attention = form.cleaned_data.get('checkin_attention')
self.order.log_action('pretix.event.order.checkin_attention', user=self.request.user, data={
'new_value': form.cleaned_data.get('checkin_attention')
})
self.order.save(update_fields=['checkin_attention', 'comment'])
print(self.order.custom_followup_at)
self.order.save(update_fields=['checkin_attention', 'comment', 'custom_followup_at'])
self.order.refresh_from_db()
print(self.order.custom_followup_at)
messages.success(self.request, _('The comment has been updated.'))
else:
messages.error(self.request, _('Could not update the comment.'))

View File

@@ -256,6 +256,7 @@ TEST_ORDER_RES = {
"payment_provider": "banktransfer",
"total": "23.00",
"comment": "",
"custom_followup_at": None,
"checkin_attention": False,
"invoice_address": {
"last_modified": "2017-12-01T10:00:00Z",
@@ -1739,6 +1740,7 @@ def test_order_create_simulate(token_client, organizer, event, item, quota, ques
],
'total': '23.25',
'comment': '',
"custom_followup_at": None,
'invoice_address': {
'is_business': False,
'company': 'Sample company',
@@ -4202,6 +4204,7 @@ def test_order_update_allowed_fields(token_client, organizer, event, order):
organizer.slug, event.slug, order.code
), format='json', data={
'comment': 'Here is a comment',
'custom_followup_at': '2021-06-12',
'checkin_attention': True,
'email': 'foo@bar.com',
'phone': '+4962219999',
@@ -4224,6 +4227,7 @@ def test_order_update_allowed_fields(token_client, organizer, event, order):
assert resp.status_code == 200
order.refresh_from_db()
assert order.comment == 'Here is a comment'
assert order.custom_followup_at.isoformat() == '2021-06-12'
assert order.checkin_attention
assert order.email == 'foo@bar.com'
assert order.phone == '+4962219999'
@@ -4236,6 +4240,7 @@ def test_order_update_allowed_fields(token_client, organizer, event, order):
assert order.invoice_address.city == "Paris"
with scopes_disabled():
assert order.all_logentries().get(action_type='pretix.event.order.comment')
assert order.all_logentries().get(action_type='pretix.event.order.custom_followup_at')
assert order.all_logentries().get(action_type='pretix.event.order.checkin_attention')
assert order.all_logentries().get(action_type='pretix.event.order.contact.changed')
assert order.all_logentries().get(action_type='pretix.event.order.phone.changed')