forked from CGM_Public/pretix_original
New check-in features (#3022)
This commit is contained in:
@@ -1052,7 +1052,7 @@ class MailSettingsForm(SettingsForm):
|
||||
"value is 0, the mail will never be sent.")
|
||||
)
|
||||
mail_text_order_expire_warning = I18nFormField(
|
||||
label=_("Text"),
|
||||
label=_("Text (if order will expire automatically)"),
|
||||
required=False,
|
||||
widget=I18nTextarea,
|
||||
)
|
||||
@@ -1061,6 +1061,11 @@ class MailSettingsForm(SettingsForm):
|
||||
required=False,
|
||||
widget=I18nTextInput,
|
||||
)
|
||||
mail_text_order_pending_warning = I18nFormField(
|
||||
label=_("Text (if order will not expire automatically)"),
|
||||
required=False,
|
||||
widget=I18nTextarea,
|
||||
)
|
||||
mail_subject_order_pending_warning = I18nFormField(
|
||||
label=_("Subject (if order will not expire automatically)"),
|
||||
required=False,
|
||||
|
||||
@@ -210,6 +210,7 @@ class OrderFilterForm(FilterForm):
|
||||
('', _('All orders')),
|
||||
(_('Valid orders'), (
|
||||
(Order.STATUS_PAID, _('Paid (or canceled with paid fee)')),
|
||||
(Order.STATUS_PAID + 'v', _('Paid or confirmed')),
|
||||
(Order.STATUS_PENDING, _('Pending')),
|
||||
(Order.STATUS_PENDING + Order.STATUS_PAID, _('Pending or paid')),
|
||||
)),
|
||||
@@ -296,6 +297,8 @@ class OrderFilterForm(FilterForm):
|
||||
qs = qs.filter(status__in=[Order.STATUS_PENDING, Order.STATUS_PAID])
|
||||
elif s == 'ne':
|
||||
qs = qs.filter(status__in=[Order.STATUS_PENDING, Order.STATUS_EXPIRED])
|
||||
elif s == 'pv':
|
||||
qs = qs.filter(Q(status=Order.STATUS_PAID) | Q(status=Order.STATUS_PENDING, valid_if_pending=True))
|
||||
elif s in ('p', 'n', 'e', 'c', 'r'):
|
||||
qs = qs.filter(status=s)
|
||||
elif s == 'overpaid':
|
||||
|
||||
@@ -387,7 +387,6 @@ class ItemCreateForm(I18nModelForm):
|
||||
'show_quota_left',
|
||||
'hidden_if_available',
|
||||
'require_bundling',
|
||||
'checkin_attention',
|
||||
'require_membership',
|
||||
'grant_membership_type',
|
||||
'grant_membership_duration_like_event',
|
||||
@@ -800,6 +799,7 @@ class ItemVariationForm(I18nModelForm):
|
||||
'require_membership',
|
||||
'require_membership_hidden',
|
||||
'require_membership_types',
|
||||
'checkin_attention',
|
||||
'available_from',
|
||||
'available_until',
|
||||
'sales_channels',
|
||||
|
||||
@@ -68,12 +68,6 @@ from pretix.helpers.money import change_decimal_field
|
||||
|
||||
|
||||
class ExtendForm(I18nModelForm):
|
||||
quota_ignore = forms.BooleanField(
|
||||
label=_('Overbook quota'),
|
||||
help_text=_('If you check this box, this operation will be performed even if it leads to an overbooked quota '
|
||||
'and you having sold more tickets than you planned!'),
|
||||
required=False
|
||||
)
|
||||
expires = forms.DateField(
|
||||
label=_("Expiration date"),
|
||||
widget=forms.DateInput(attrs={
|
||||
@@ -81,16 +75,35 @@ class ExtendForm(I18nModelForm):
|
||||
'data-is-payment-date': 'true'
|
||||
}),
|
||||
)
|
||||
valid_if_pending = forms.BooleanField(
|
||||
label=_('Confirm order regardless of payment'),
|
||||
help_text=_('If you check this box, this order will behave like a paid order for most purposes, even though it '
|
||||
'is not yet paid. This means that the customer can already download and use tickets regardless '
|
||||
'of your event settings, and the order might be treated as paid by some plugins. If you check '
|
||||
'this, this order will not be marked as "expired" automatically if the payment deadline arrives, '
|
||||
'since we expect that you want to collect the amount somehow and not auto-cancel the order.'),
|
||||
required=False
|
||||
)
|
||||
quota_ignore = forms.BooleanField(
|
||||
label=_('Overbook quota'),
|
||||
help_text=_('If you check this box, this operation will be performed even if it leads to an overbooked quota '
|
||||
'and you having sold more tickets than you planned!'),
|
||||
required=False
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Order
|
||||
fields = []
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs.setdefault('initial', {})
|
||||
kwargs['initial'].setdefault('valid_if_pending', kwargs['instance'].valid_if_pending)
|
||||
kwargs['initial'].setdefault('expires', kwargs['instance'].expires)
|
||||
super().__init__(*args, **kwargs)
|
||||
if self.instance.status == Order.STATUS_PENDING or self.instance._is_still_available(now(),
|
||||
count_waitinglist=False)\
|
||||
is True:
|
||||
if (
|
||||
self.instance.status == Order.STATUS_PENDING or
|
||||
self.instance._is_still_available(now(), count_waitinglist=False) is True
|
||||
):
|
||||
del self.fields['quota_ignore']
|
||||
|
||||
def clean(self):
|
||||
@@ -435,6 +448,20 @@ class OrderPositionChangeForm(forms.Form):
|
||||
localize=True,
|
||||
label=_('New price (gross)')
|
||||
)
|
||||
blocked = forms.BooleanField(
|
||||
required=False,
|
||||
label=_('Ticket is blocked')
|
||||
)
|
||||
valid_from = SplitDateTimeField(
|
||||
required=False,
|
||||
widget=SplitDateTimePickerWidget,
|
||||
label=_('Validity start')
|
||||
)
|
||||
valid_until = SplitDateTimeField(
|
||||
required=False,
|
||||
widget=SplitDateTimePickerWidget,
|
||||
label=_('Validity end')
|
||||
)
|
||||
used_membership = forms.ChoiceField(
|
||||
required=False,
|
||||
)
|
||||
@@ -466,6 +493,9 @@ class OrderPositionChangeForm(forms.Form):
|
||||
initial = kwargs.get('initial', {})
|
||||
|
||||
initial['price'] = instance.price
|
||||
initial['blocked'] = instance.blocked and "admin" in instance.blocked
|
||||
initial['valid_from'] = instance.valid_from
|
||||
initial['valid_until'] = instance.valid_until
|
||||
|
||||
kwargs['initial'] = initial
|
||||
super().__init__(*args, **kwargs)
|
||||
@@ -756,7 +786,8 @@ class EventCancelForm(forms.Form):
|
||||
label=_('Automatically refund money if possible'),
|
||||
initial=True,
|
||||
required=False,
|
||||
help_text=_('Only available for payment method that support automatic refunds.')
|
||||
help_text=_('Only available for payment method that support automatic refunds. Tickets that have been blocked '
|
||||
'(manually or by a plugin) are not auto-canceled and you will need to deal with them manually.')
|
||||
)
|
||||
manual_refund = forms.BooleanField(
|
||||
label=_('Create refund in the manual refund to-do list'),
|
||||
|
||||
@@ -52,7 +52,7 @@ from pretix.base.models import (
|
||||
Checkin, CheckinList, Event, ItemVariation, LogEntry, OrderPosition,
|
||||
TaxRule,
|
||||
)
|
||||
from pretix.base.signals import logentry_display
|
||||
from pretix.base.signals import logentry_display, orderposition_blocked_display
|
||||
from pretix.base.templatetags.money import money_filter
|
||||
|
||||
OVERVIEW_BANLIST = [
|
||||
@@ -162,6 +162,25 @@ def _display_order_changed(event: Event, logentry: LogEntry):
|
||||
return text + ' ' + _('A new secret has been generated for position #{posid}.').format(
|
||||
posid=data.get('positionid', '?'),
|
||||
)
|
||||
elif logentry.action_type == 'pretix.event.order.changed.valid_from':
|
||||
return text + ' ' + _('The validity start date for position #{posid} has been changed to {value}.').format(
|
||||
posid=data.get('positionid', '?'),
|
||||
value=date_format(dateutil.parser.parse(data.get('new_value')), 'SHORT_DATETIME_FORMAT') if data.get(
|
||||
'new_value') else '–'
|
||||
)
|
||||
elif logentry.action_type == 'pretix.event.order.changed.valid_until':
|
||||
return text + ' ' + _('The validity end date for position #{posid} has been changed to {value}.').format(
|
||||
posid=data.get('positionid', '?'),
|
||||
value=date_format(dateutil.parser.parse(data.get('new_value')), 'SHORT_DATETIME_FORMAT') if data.get('new_value') else '–'
|
||||
)
|
||||
elif logentry.action_type == 'pretix.event.order.changed.add_block':
|
||||
return text + ' ' + _('A block has been added for position #{posid}.').format(
|
||||
posid=data.get('positionid', '?'),
|
||||
)
|
||||
elif logentry.action_type == 'pretix.event.order.changed.remove_block':
|
||||
return text + ' ' + _('A block has been removed for position #{posid}.').format(
|
||||
posid=data.get('positionid', '?'),
|
||||
)
|
||||
elif logentry.action_type == 'pretix.event.order.changed.split':
|
||||
old_item = str(event.items.get(pk=data['old_item']))
|
||||
if data['old_variation']:
|
||||
@@ -351,6 +370,8 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs):
|
||||
'pretix.event.order.unpaid': _('The order has been marked as unpaid.'),
|
||||
'pretix.event.order.secret.changed': _('The order\'s secret has been changed.'),
|
||||
'pretix.event.order.expirychanged': _('The order\'s expiry date has been changed.'),
|
||||
'pretix.event.order.valid_if_pending.set': _('The order has been set to be usable before it is paid.'),
|
||||
'pretix.event.order.valid_if_pending.unset': _('The order has been set to require payment before use.'),
|
||||
'pretix.event.order.expired': _('The order has been marked as expired.'),
|
||||
'pretix.event.order.paid': _('The order has been marked as paid.'),
|
||||
'pretix.event.order.cancellationrequest.deleted': _('The cancellation request has been deleted.'),
|
||||
@@ -376,6 +397,8 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs):
|
||||
'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.pretix.event.order.valid_if_pending': _('The order\'s flag to be considered valid even if '
|
||||
'unpaid has been toggled.'),
|
||||
'pretix.event.order.payment.changed': _('A new payment {local_id} has been started instead of the previous one.'),
|
||||
'pretix.event.order.email.sent': _('An unidentified type email has been sent.'),
|
||||
'pretix.event.order.email.error': _('Sending of an email has failed.'),
|
||||
@@ -647,3 +670,11 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs):
|
||||
|
||||
if logentry.action_type == 'pretix.control.auth.user.impersonate_stopped':
|
||||
return str(_('You stopped impersonating {}.')).format(data['other_email'])
|
||||
|
||||
|
||||
@receiver(signal=orderposition_blocked_display, dispatch_uid="pretixcontrol_orderposition_blocked_display")
|
||||
def pretixcontrol_orderposition_blocked_display(sender: Event, orderposition, block_name, **kwargs):
|
||||
if block_name == 'admin':
|
||||
return _('Blocked manually')
|
||||
elif block_name.startswith('api:'):
|
||||
return _('Blocked because of an API integration')
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
{% include "pretixcontrol/event/mail_settings_fragment.html" with pid="order_changed" title=title_order_changed items="mail_subject_order_changed,mail_text_order_changed" %}
|
||||
|
||||
{% blocktrans asvar title_payment_reminder %}Payment reminder{% endblocktrans %}
|
||||
{% include "pretixcontrol/event/mail_settings_fragment.html" with pid="order_expirew" title=title_payment_reminder items="mail_days_order_expire_warning,mail_subject_order_expire_warning,mail_subject_order_pending_warning,mail_text_order_expire_warning" exclude="mail_days_order_expire_warning" %}
|
||||
{% include "pretixcontrol/event/mail_settings_fragment.html" with pid="order_expirew" title=title_payment_reminder items="mail_days_order_expire_warning,mail_subject_order_expire_warning,mail_text_order_expire_warning,mail_subject_order_pending_warning,mail_text_order_pending_warning" exclude="mail_days_order_expire_warning" %}
|
||||
|
||||
{% blocktrans asvar title_waiting_list_notification %}Waiting list notification{% endblocktrans %}
|
||||
{% include "pretixcontrol/event/mail_settings_fragment.html" with pid="waiting_list" title=title_waiting_list_notification items="mail_subject_waiting_list,mail_text_waiting_list" %}
|
||||
|
||||
@@ -107,6 +107,7 @@
|
||||
{% bootstrap_field form.require_membership_hidden layout="control" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% bootstrap_field form.checkin_attention layout="control" %}
|
||||
</div>
|
||||
</details>
|
||||
{% endfor %}
|
||||
@@ -204,6 +205,7 @@
|
||||
{% bootstrap_field formset.empty_form.require_membership_hidden layout="control" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% bootstrap_field formset.empty_form.checkin_attention layout="control" %}
|
||||
</div>
|
||||
</details>
|
||||
{% endescapescript %}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
<select name="status" class="form-control">
|
||||
<option value="" {% if request.GET.status == "" %}selected="selected"{% endif %}>{% trans "All orders" %}</option>
|
||||
<option value="p" {% if request.GET.status == "p" %}selected="selected"{% endif %}>{% trans "Paid" %}</option>
|
||||
<option value="pv" {% if request.GET.status == "pv" %}selected="selected"{% endif %}>{% trans "Paid or confirmed" %}</option>
|
||||
<option value="n" {% if request.GET.status == "n" %}selected="selected"{% endif %}>{% trans "Pending" %}</option>
|
||||
<option value="np" {% if request.GET.status == "np" or "status" not in request.GET %}selected="selected"{% endif %}>{% trans "Pending or paid" %}</option>
|
||||
<option value="o" {% if request.GET.status == "o" %}selected="selected"{% endif %}>{% trans "Pending (overdue)" %}</option>
|
||||
|
||||
@@ -189,6 +189,55 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<strong>{% trans "Ticket block" %}</strong>
|
||||
</div>
|
||||
<div class="col-sm-5">
|
||||
{% if "admin" in position.blocked %}
|
||||
{% trans "Blocked" %}
|
||||
{% elif position.blocked %}
|
||||
{% trans "Blocked due to external constraints" %}
|
||||
{% else %}
|
||||
{% trans "Not blocked" %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
{% bootstrap_field position.form.blocked layout='inline' %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<strong>{% trans "Validity time" %}</strong>
|
||||
</div>
|
||||
<div class="col-sm-5">
|
||||
{% if position.valid_from %}
|
||||
{% blocktrans trimmed with datetime=position.valid_from|date:"SHORT_DATETIME_FORMAT" %}
|
||||
Valid from {{ datetime }}
|
||||
{% endblocktrans %}
|
||||
{% endif %}
|
||||
{% if position.valid_until %}
|
||||
{% if position.valid_from %}
|
||||
<br />
|
||||
{% endif %}
|
||||
{% blocktrans trimmed with datetime=position.valid_from|date:"SHORT_DATETIME_FORMAT" %}
|
||||
Valid until {{ datetime }}
|
||||
{% endblocktrans %}
|
||||
{% endif %}
|
||||
{% if not position.valid_from and not position.valid_until %}
|
||||
{% trans "Unconstrained" %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
{% bootstrap_field position.form.valid_from layout='inline' %}
|
||||
<div class="text-center">
|
||||
{% trans "–" %}
|
||||
</div>
|
||||
{% bootstrap_field position.form.valid_until layout='inline' %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<strong>{% trans "Ticket secret" %}</strong>
|
||||
|
||||
@@ -194,7 +194,10 @@
|
||||
<dt>{% trans "Expiry date" %}</dt>
|
||||
<dd>
|
||||
{{ order.expires|date:"SHORT_DATETIME_FORMAT" }}
|
||||
{% if has_cancellation_fee and request.event.settings.payment_term_expire_automatically %}
|
||||
{% if order.valid_if_pending %}
|
||||
<span class="fa fa-warning text-danger" data-toggle="tooltip"
|
||||
title="{% trans "This order will not expire automatically since it is already confirmed and can be used." %}"></span>
|
||||
{% elif has_cancellation_fee and request.event.settings.payment_term_expire_automatically %}
|
||||
<span class="fa fa-warning text-danger" data-toggle="tooltip"
|
||||
title="{% trans "This order will not expire automatically as it has an open cancellation fee." %}"></span>
|
||||
{% endif %}
|
||||
@@ -390,6 +393,15 @@
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if line.blocked %}
|
||||
<br />
|
||||
<strong class="text-danger">
|
||||
<span class="fa fa-ban fa-fw text-danger"></span>
|
||||
{% for k, block_reason in line.blocked_reasons.items %}
|
||||
{{ block_reason }}
|
||||
{% endfor %}
|
||||
</strong>
|
||||
{% endif %}
|
||||
{% if line.seat %}
|
||||
<br />
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="14" viewBox="0 0 4.7624999 3.7041668" class="svg-icon">
|
||||
@@ -429,6 +441,26 @@
|
||||
</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
{% if line.valid_from or line.valid_until %}
|
||||
<div class="cart-icon-details">
|
||||
<dd>
|
||||
<span class="fa fa-clock-o fa-fw" aria-hidden="true"></span>
|
||||
{% if line.valid_from and line.valid_until %}
|
||||
{% blocktrans trimmed with datetime_from=line.valid_from|date:"SHORT_DATETIME_FORMAT" datetime_until=line.valid_until|date:"SHORT_DATETIME_FORMAT" %}
|
||||
Valid from {{ datetime_from }} until {{ datetime_until }}
|
||||
{% endblocktrans %}
|
||||
{% elif line.valid_from %}
|
||||
{% blocktrans trimmed with datetime=line.valid_from|date:"SHORT_DATETIME_FORMAT" %}
|
||||
Valid from {{ datetime }}
|
||||
{% endblocktrans %}
|
||||
{% elif line.valid_until %}
|
||||
{% blocktrans trimmed with datetime=line.valid_until|date:"SHORT_DATETIME_FORMAT" %}
|
||||
Valid until {{ datetime }}
|
||||
{% endblocktrans %}
|
||||
{% endif %}
|
||||
</dd>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if not line.canceled %}
|
||||
<div class="position-buttons">
|
||||
{% if line.generate_ticket %}
|
||||
|
||||
@@ -6,6 +6,11 @@
|
||||
<span class="fa fa-question-circle"></span>
|
||||
{% trans "Approval pending" %}
|
||||
</span>
|
||||
{% elif order.valid_if_pending %}
|
||||
<span data-toggle="tooltip" class="label label-info {{ class }}">
|
||||
<span class="fa fa-money"></span>
|
||||
{% trans "Pending (confirmed)" context "order state" %}
|
||||
</span>
|
||||
{% else %}
|
||||
<span data-toggle="tooltip" title="{{ order.expires|date:"SHORT_DATETIME_FORMAT" }}"
|
||||
class="label label-warning {{ class }}">
|
||||
|
||||
@@ -36,7 +36,7 @@ import dateutil.parser
|
||||
from django.contrib import messages
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.db import transaction
|
||||
from django.db.models import Exists, Max, OuterRef, Prefetch, Subquery
|
||||
from django.db.models import Exists, Max, OuterRef, Prefetch, Q, Subquery
|
||||
from django.http import Http404, HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.urls import reverse
|
||||
@@ -85,9 +85,16 @@ class CheckInListQueryMixin:
|
||||
m=Max('datetime')
|
||||
).values('m')
|
||||
|
||||
if self.list.include_pending:
|
||||
status_q = Q(order__status__in=[Order.STATUS_PAID, Order.STATUS_PENDING])
|
||||
else:
|
||||
status_q = Q(
|
||||
Q(order__status=Order.STATUS_PAID) |
|
||||
Q(order__status=Order.STATUS_PENDING, order__valid_if_pending=True)
|
||||
)
|
||||
qs = OrderPosition.objects.filter(
|
||||
status_q,
|
||||
order__event=self.request.event,
|
||||
order__status__in=[Order.STATUS_PAID, Order.STATUS_PENDING] if self.list.include_pending else [Order.STATUS_PAID],
|
||||
).annotate(
|
||||
last_entry=Subquery(cqs),
|
||||
last_exit=Subquery(cqs_exit),
|
||||
@@ -199,7 +206,9 @@ class CheckInListBulkActionView(CheckInListQueryMixin, EventPermissionRequiredMi
|
||||
if not request.user.has_event_permission(request.organizer, request.event, 'can_change_orders', request=request):
|
||||
raise PermissionDenied()
|
||||
for op in positions:
|
||||
if op.order.status == Order.STATUS_PAID or (self.list.include_pending and op.order.status == Order.STATUS_PENDING):
|
||||
if op.order.status == Order.STATUS_PAID or (
|
||||
(self.list.include_pending or op.order.valid_if_pending) and op.order.status == Order.STATUS_PENDING
|
||||
):
|
||||
Checkin.objects.filter(position=op, list=self.list).delete()
|
||||
op.order.log_action('pretix.event.checkin.reverted', data={
|
||||
'position': op.id,
|
||||
@@ -213,7 +222,9 @@ class CheckInListBulkActionView(CheckInListQueryMixin, EventPermissionRequiredMi
|
||||
else:
|
||||
t = Checkin.TYPE_EXIT if request.POST.get('checkout') == 'true' else Checkin.TYPE_ENTRY
|
||||
for op in positions:
|
||||
if op.order.status == Order.STATUS_PAID or (self.list.include_pending and op.order.status == Order.STATUS_PENDING):
|
||||
if op.order.status == Order.STATUS_PAID or (
|
||||
(self.list.include_pending or op.order.valid_if_pending) and op.order.status == Order.STATUS_PENDING
|
||||
):
|
||||
lci = op.checkins.filter(list=self.list).first()
|
||||
if self.list.allow_multiple_entries or t != Checkin.TYPE_ENTRY or (lci and lci.type != Checkin.TYPE_ENTRY):
|
||||
ci = Checkin.objects.create(position=op, list=self.list, datetime=now(), type=t)
|
||||
|
||||
@@ -629,6 +629,11 @@ class QuestionView(EventPermissionRequiredMixin, QuestionMixin, ChartContainingV
|
||||
orderposition__order__expires__lt=now().replace(hour=0, minute=0, second=0))
|
||||
elif s == 'np':
|
||||
qs = qs.filter(orderposition__order__status__in=[Order.STATUS_PENDING, Order.STATUS_PAID])
|
||||
elif s == 'pv':
|
||||
qs = qs.filter(
|
||||
Q(orderposition__order__status=Order.STATUS_PAID) |
|
||||
Q(orderposition__order__status=Order.STATUS_PENDING, orderposition__order__valid_if_pending=True)
|
||||
)
|
||||
elif s == 'ne':
|
||||
qs = qs.filter(orderposition__order__status__in=[Order.STATUS_PENDING, Order.STATUS_EXPIRED])
|
||||
else:
|
||||
|
||||
@@ -1520,6 +1520,7 @@ class OrderExtend(OrderView):
|
||||
self.order,
|
||||
new_date=self.form.cleaned_data.get('expires'),
|
||||
force=self.form.cleaned_data.get('quota_ignore', False),
|
||||
valid_if_pending=self.form.cleaned_data.get('valid_if_pending', False),
|
||||
user=self.request.user
|
||||
)
|
||||
messages.success(self.request, _('The payment term has been changed.'))
|
||||
@@ -1773,6 +1774,17 @@ class OrderChange(OrderView):
|
||||
if p.form.cleaned_data['tax_rule'] and p.form.cleaned_data['tax_rule'] != p.tax_rule:
|
||||
ocm.change_tax_rule(p, p.form.cleaned_data['tax_rule'])
|
||||
|
||||
if p.form.cleaned_data["blocked"] and "admin" not in (p.blocked or []):
|
||||
ocm.add_block(p, "admin")
|
||||
elif not p.form.cleaned_data["blocked"] and "admin" in (p.blocked or []):
|
||||
ocm.remove_block(p, "admin")
|
||||
|
||||
if p.form.cleaned_data['valid_from'] != p.valid_from:
|
||||
ocm.change_valid_from(p, p.form.cleaned_data['valid_from'])
|
||||
|
||||
if p.form.cleaned_data['valid_until'] != p.valid_until:
|
||||
ocm.change_valid_until(p, p.form.cleaned_data['valid_until'])
|
||||
|
||||
if p.form.cleaned_data.get('operation_split'):
|
||||
ocm.split(p)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user