Compare commits

...
9 changed files with 58 additions and 4 deletions
+6
View File
@@ -128,6 +128,10 @@ last_modified datetime Last modificati
The ``custom_followup_at`` attribute has been added.
.. versionchanged:: 4.4
The ``item`` and ``variation`` query parameters have been added.
.. _order-position-resource:
@@ -415,6 +419,8 @@ List of all orders
:query string code: Only return orders that match the given order code
:query string status: Only return orders in the given order status (see above)
:query string search: Only return orders matching a given search query
:query integer item: Only return orders with a position that contains this item ID. *Warning:* Result will also include orders if they contain mixed items, and it will even return orders where the item is only contained in a canceled position.
:query integer variation: Only return orders with a position that contains this variation ID. *Warning:* Result will also include orders if they contain mixed items and variations, and it will even return orders where the variation is only contained in a canceled position.
:query boolean testmode: Only return orders with ``testmode`` set to ``true`` or ``false``
:query boolean require_approval: If set to ``true`` or ``false``, only categories with this value for the field
``require_approval`` will be returned.
+1 -1
View File
@@ -19,4 +19,4 @@
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# <https://www.gnu.org/licenses/>.
#
__version__ = "4.3.0"
__version__ = "4.4.0.dev0"
+2
View File
@@ -92,6 +92,8 @@ with scopes_disabled():
subevent_after = django_filters.IsoDateTimeFilter(method='subevent_after_qs')
subevent_before = django_filters.IsoDateTimeFilter(method='subevent_before_qs')
search = django_filters.CharFilter(method='search_qs')
item = django_filters.CharFilter(field_name='all_positions', lookup_expr='item_id')
variation = django_filters.CharFilter(field_name='all_positions', lookup_expr='variation_id')
class Meta:
model = Order
+16
View File
@@ -539,6 +539,22 @@ def base_placeholders(sender, **kwargs):
'voucher_list', ['voucher_list'], lambda voucher_list: ' \n'.join(voucher_list),
' 68CYU2H6ZTP3WLK5\n 7MB94KKPVEPSMVF2'
),
SimpleFunctionalMailTextPlaceholder(
# join vouchers with two spaces at end of line so markdown-parser inserts a <br>
'voucher_url_list', ['event', 'voucher_list'],
lambda event, voucher_list: ' \n'.join([
build_absolute_uri(
event, 'presale:event.redeem'
) + '?voucher=' + c
for c in voucher_list
]),
lambda event: ' \n'.join([
build_absolute_uri(
event, 'presale:event.redeem'
) + '?voucher=' + c
for c in ['68CYU2H6ZTP3WLK5', '7MB94KKPVEPSMVF2']
]),
),
SimpleFunctionalMailTextPlaceholder(
'url', ['event', 'voucher_list'], lambda event, voucher_list: build_absolute_uri(event, 'presale:event.index', kwargs={
'event': event.slug,
+3
View File
@@ -300,6 +300,9 @@ class Invoice(models.Model):
def __repr__(self):
return '<Invoice {} / {}>'.format(self.full_invoice_no, self.pk)
def __str__(self):
return self.full_invoice_no
class InvoiceLine(models.Model):
"""
+15 -1
View File
@@ -57,7 +57,8 @@ from pretix.base.forms.widgets import (
DatePickerWidget, SplitDateTimePickerWidget,
)
from pretix.base.models import (
InvoiceAddress, ItemAddOn, Order, OrderFee, OrderPosition, TaxRule,
Invoice, InvoiceAddress, ItemAddOn, Order, OrderFee, OrderPosition,
TaxRule,
)
from pretix.base.models.event import SubEvent
from pretix.base.services.pricing import get_price
@@ -609,6 +610,17 @@ class OrderMailForm(forms.Form):
label=_("Subject"),
required=True
)
attach_tickets = forms.BooleanField(
label=_("Attach tickets"),
help_text=_("Will be ignored if all tickets in this order exceed a given size limit to ensure email deliverability."),
required=False
)
attach_invoices = forms.ModelMultipleChoiceField(
label=_("Attach invoices"),
widget=forms.CheckboxSelectMultiple,
required=False,
queryset=Invoice.objects.none()
)
def _set_field_placeholders(self, fn, base_parameters):
phs = [
@@ -641,6 +653,7 @@ class OrderMailForm(forms.Form):
widget=forms.Textarea,
initial=order.event.settings.mail_text_order_custom_mail.localize(order.locale),
)
self.fields['attach_invoices'].queryset = order.invoices.all()
self._set_field_placeholders('message', ['event', 'order'])
@@ -648,6 +661,7 @@ class OrderPositionMailForm(OrderMailForm):
def __init__(self, *args, **kwargs):
position = self.position = kwargs.pop('position')
super().__init__(*args, **kwargs)
del self.fields['attach_invoices']
self.fields['sendto'].initial = position.attendee_email
self.fields['message'] = forms.CharField(
label=_("Message"),
@@ -18,6 +18,10 @@
{% bootstrap_field form.sendto layout='horizontal' %}
{% bootstrap_field form.subject layout='horizontal' %}
{% bootstrap_field form.message layout='horizontal' %}
{% bootstrap_field form.attach_tickets layout='horizontal' %}
{% if form.attach_invoices %}
{% bootstrap_field form.attach_invoices layout='horizontal' %}
{% endif %}
{% if request.method == "POST" %}
<fieldset>
<legend>{% trans "E-mail preview" %}</legend>
+5 -2
View File
@@ -1982,7 +1982,9 @@ class OrderSendMail(EventPermissionRequiredMixin, OrderViewMixin, FormView):
order.send_mail(
form.cleaned_data['subject'], email_template,
email_context, 'pretix.event.order.email.custom_sent',
self.request.user, auto_email=False
self.request.user, auto_email=False,
attach_tickets=form.cleaned_data.get('attach_tickets', False),
invoices=form.cleaned_data.get('attach_invoices', []),
)
messages.success(self.request,
_('Your message has been queued and will be sent to {}.'.format(order.email)))
@@ -2047,7 +2049,8 @@ class OrderPositionSendMail(OrderSendMail):
email_template,
email_context,
'pretix.event.order.position.email.custom_sent',
self.request.user
self.request.user,
attach_tickets=form.cleaned_data.get('attach_tickets', False),
)
messages.success(self.request,
_('Your message has been queued and will be sent to {}.'.format(position.attendee_email)))
@@ -172,6 +172,12 @@ article.item-with-variations:last-child, .product-row:last-child {
}
section.front-page {
margin-top: 30px;
position: sticky;
bottom: 0;
top: 100px;
padding: 10px 0;
background: rgba(255,255,255,.8);
z-index: 10;
}
.offline-banner {
background: $brand-danger;