New implementation of sales channels (#4111)

Co-authored-by: Martin Gross <gross@rami.io>
This commit is contained in:
Raphael Michel
2024-06-30 19:24:30 +02:00
committed by GitHub
parent 95511b0330
commit 4fb5c6bef0
174 changed files with 2902 additions and 616 deletions

View File

@@ -1,6 +1,7 @@
{% extends "pretixcontrol/items/base.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% load static %}
{% load urlreplace %}
{% block title %}{% trans "Check-in lists" %}{% endblock %}
{% block inside %}
@@ -137,9 +138,14 @@
{% endif %}
{% endif %}
<td>
{% for channel in cl.auto_checkin_sales_channels %}
<span class="fa fa-{{ channel.icon }} text-muted"
data-toggle="tooltip" title="{% trans channel.verbose_name %}"></span>
{% for channel in cl.auto_checkin_sales_channels.all %}
{% if "." in channel.icon %}
<img src="{% static channel.icon %}" class="fa-like-image"
data-toggle="tooltip" title="{{ channel.label }}">
{% else %}
<span class="fa fa-{{ channel.icon }} text-muted"
data-toggle="tooltip" title="{{ channel.label }}"></span>
{% endif %}
{% endfor %}
</td>
<td>

View File

@@ -1,5 +1,6 @@
{% extends "pretixcontrol/event/settings_base.html" %}
{% load i18n %}
{% load static %}
{% load bootstrap3 %}
{% block inside %}
<h1>{% trans "Payment settings" %}</h1>
@@ -30,8 +31,13 @@
</td>
<td class="iconcol">
{% for channel in provider.sales_channels %}
<span class="fa fa-{{ channel.icon }} text-muted"
data-toggle="tooltip" title="{% trans channel.verbose_name %}"></span>
{% if "." in channel.icon %}
<img src="{% static channel.icon %}" class="fa-like-image"
data-toggle="tooltip" title="{{ channel.label }}">
{% else %}
<span class="fa fa-{{ channel.icon }} text-muted"
data-toggle="tooltip" title="{{ channel.label }}"></span>
{% endif %}
{% endfor %}
</td>
<td class="text-right flip">

View File

@@ -32,7 +32,8 @@
{% bootstrap_field sform.contact_mail layout="control" %}
{% bootstrap_field sform.imprint_url layout="control" %}
{% bootstrap_field form.is_public layout="control" %}
{% bootstrap_field form.sales_channels layout="control" %}
{% bootstrap_field form.all_sales_channels layout="control" %}
{% bootstrap_field form.limit_sales_channels layout="control" %}
{% if meta_forms %}
<div class="form-group metadata-group">

View File

@@ -1,6 +1,7 @@
{% load i18n %}
{% load bootstrap3 %}
{% load formset_tags %}
{% load static %}
{% load getitem %}
<div class="formset" data-formset data-formset-prefix="{{ formset.prefix }}" id="item_variations">
{{ formset.management_form }}
@@ -40,9 +41,14 @@
title="{% trans "Require a valid membership" %}"></span>
</div>
<div class="col-md-2 col-xs-6">
{% for k, c in sales_channels.items %}
<span class="fa fa-fw fa-{{ c.icon }} text-muted variation-channel-{{ k }} variation-icon-hidden"
data-toggle="tooltip" title="{% trans c.verbose_name %}"></span>
{% for c in sales_channels %}
{% if "." in c.icon %}
<img src="{% static c.icon %}" class="fa-like-image variation-channel-{{ c.id }} variation-icon-hidden"
data-toggle="tooltip" title="{{ c.label }}">
{% else %}
<span class="fa fa-fw fa-{{ c.icon }} text-muted variation-channel-{{ c.id }} variation-icon-hidden"
data-toggle="tooltip" title="{{ c.label }}"></span>
{% endif %}
{% endfor %}
</div>
<div class="col-md-1 col-xs-6 text-right flip variation-price">
@@ -97,7 +103,8 @@
{% endif %}
{% bootstrap_field form.available_from visibility_field=form.available_from_mode layout="control_with_visibility" %}
{% bootstrap_field form.available_until visibility_field=form.available_until_mode layout="control_with_visibility" %}
{% bootstrap_field form.sales_channels layout="control" %}
{% bootstrap_field form.all_sales_channels layout="control" %}
{% bootstrap_field form.limit_sales_channels layout="control" %}
{% bootstrap_field form.hide_without_voucher layout="control" %}
{% bootstrap_field form.require_approval layout="control" %}
{% if form.require_membership %}
@@ -148,9 +155,14 @@
title="{% trans "Require a valid membership" %}"></span>
</div>
<div class="col-md-2 col-xs-6">
{% for k, c in sales_channels.items %}
<span class="fa fa-fw fa-{{ c.icon }} text-muted variation-channel-{{ k }} variation-icon-hidden"
data-toggle="tooltip" title="{% trans c.verbose_name %}"></span>
{% for c in sales_channels %}
{% if "." in c.icon %}
<img src="{% static c.icon %}" class="fa-like-image variation-channel-{{ c.id }} variation-icon-hidden"
data-toggle="tooltip" title="{{ c.label }}">
{% else %}
<span class="fa fa-fw fa-{{ c.icon }} text-muted variation-channel-{{ c.id }} variation-icon-hidden"
data-toggle="tooltip" title="{{ c.label }}"></span>
{% endif %}
{% endfor %}
</div>
<div class="col-md-1 col-xs-6 text-right flip variation-price">
@@ -197,7 +209,8 @@
{% bootstrap_field formset.empty_form.available_from visibility_field=formset.empty_form.available_from_mode layout="control_with_visibility" %}
{% bootstrap_field formset.empty_form.available_until visibility_field=formset.empty_form.available_until_mode layout="control_with_visibility" %}
{% bootstrap_field formset.empty_form.available_until layout="control" %}
{% bootstrap_field formset.empty_form.sales_channels layout="control" %}
{% bootstrap_field formset.empty_form.all_sales_channels layout="control" %}
{% bootstrap_field formset.empty_form.limit_sales_channels layout="control" %}
{% bootstrap_field formset.empty_form.hide_without_voucher layout="control" %}
{% bootstrap_field formset.empty_form.require_approval layout="control" %}
{% if formset.empty_form.require_membership %}

View File

@@ -152,9 +152,8 @@
</fieldset>
<fieldset>
<legend>{% trans "Availability" %}</legend>
{% bootstrap_field form.sales_channels layout="control" horizontal_field_class="col-md-7" %}
{% bootstrap_field form.all_sales_channels layout="control" horizontal_field_class="col-md-7" %}
{% bootstrap_field form.limit_sales_channels layout="control" horizontal_field_class="col-md-7" %}
{% bootstrap_field form.available_from visibility_field=form.available_from_mode layout="control_with_visibility" %}
{% bootstrap_field form.available_until visibility_field=form.available_until_mode layout="control_with_visibility" %}
{% bootstrap_field form.max_per_order layout="control" horizontal_field_class="col-md-7" %}

View File

@@ -15,7 +15,8 @@
{% bootstrap_field form.internal_name layout="control" %}
{% bootstrap_field form.available_from layout="control" %}
{% bootstrap_field form.available_until layout="control" %}
{% bootstrap_field form.sales_channels layout="control" %}
{% bootstrap_field form.all_sales_channels layout="control" %}
{% bootstrap_field form.limit_sales_channels layout="control" %}
</fieldset>
<fieldset>
<legend>{% trans "Condition" context "discount" %}</legend>

View File

@@ -1,5 +1,6 @@
{% extends "pretixcontrol/items/base.html" %}
{% load i18n %}
{% load static %}
{% block title %}{% trans "Automatic discounts" %}{% endblock %}
{% block inside %}
<h1>{% trans "Automatic discounts" %}</h1>
@@ -78,10 +79,15 @@
{% endif %}
</td>
<td>
{% for k, c in sales_channels.items %}
{% if k in d.sales_channels %}
<span class="fa fa-fw fa-{{ c.icon }} text-muted"
data-toggle="tooltip" title="{% trans c.verbose_name %}"></span>
{% for c in sales_channels %}
{% if d.all_sales_channels or c in d.limit_sales_channels.all %}
{% if "." in c.icon %}
<img src="{% static c.icon %}" class="fa-like-image"
data-toggle="tooltip" title="{{ c.label }}">
{% else %}
<span class="fa fa-fw fa-{{ c.icon }} text-muted"
data-toggle="tooltip" title="{{ c.label }}"></span>
{% endif %}
{% else %}
{% endif %}
{% endfor %}

View File

@@ -1,6 +1,7 @@
{% extends "pretixcontrol/items/base.html" %}
{% load i18n %}
{% load money %}
{% load static %}
{% block title %}{% trans "Products" %}{% endblock %}
{% block inside %}
{% blocktrans asvar s_taxes %}taxes{% endblocktrans %}
@@ -66,10 +67,15 @@
<br>
<small class="text-muted">
#{{ i.pk }}
{% for k, c in sales_channels.items %}
{% if k in i.sales_channels %}
<span class="fa fa-fw fa-{{ c.icon }} text-muted"
data-toggle="tooltip" title="{% trans c.verbose_name %}"></span>
{% for c in sales_channels %}
{% if i.all_sales_channels or c in i.limit_sales_channels.all %}
{% if "." in c.icon %}
<img src="{% static c.icon %}" class="fa-like-image"
data-toggle="tooltip" title="{{ c.label }}">
{% else %}
<span class="fa fa-fw fa-{{ c.icon }} text-muted"
data-toggle="tooltip" title="{{ c.label }}"></span>
{% endif %}
{% else %}
{% endif %}
{% endfor %}

View File

@@ -185,9 +185,9 @@
<dt>{% trans "Cancellation date" %}</dt>
<dd>{{ order.cancellation_date|date:"SHORT_DATETIME_FORMAT" }}</dd>
{% endif %}
{% if sales_channel %}
{% if order.sales_channel %}
<dt>{% trans "Sales channel" %}</dt>
<dd>{{ sales_channel.verbose_name }}</dd>
<dd>{{ order.sales_channel.label }}</dd>
{% endif %}
<dt>{% trans "Order locale" %}</dt>
<dd>

View File

@@ -4,6 +4,7 @@
{% load urlreplace %}
{% load money %}
{% load bootstrap3 %}
{% load static %}
{% block title %}{% trans "Orders" %}{% endblock %}
{% block content %}
<h1>{% trans "Orders" %}</h1>
@@ -201,8 +202,13 @@
{% endif %}
</td>
<td>
<span class="fa fa-fw fa-{{ o.sales_channel_obj.icon }} text-muted"
data-toggle="tooltip" title="{% trans o.sales_channel_obj.verbose_name %}"></span>
{% if "." in o.sales_channel.icon %}
<img src="{% static o.sales_channel.icon %}" class="fa-like-image"
data-toggle="tooltip" title="{{ o.sales_channel.label }}">
{% else %}
<span class="fa fa-fw fa-{{ o.sales_channel.icon }} text-muted"
data-toggle="tooltip" title="{{ o.sales_channel.label }}"></span>
{% endif %}
{{ o.datetime|date:"SHORT_DATETIME_FORMAT" }}
</td>
<td class="text-right flip">

View File

@@ -0,0 +1,27 @@
{% extends "pretixcontrol/organizers/base.html" %}
{% load i18n %}
{% load formset_tags %}
{% load bootstrap3 %}
{% block inner %}
<h1>{% trans "Add sales channel" %}</h1>
<form class="form-horizontal" action="" method="post">
{% csrf_token %}
{% bootstrap_form_errors form layout="control" %}
{% bootstrap_field form.label layout="control" %}
<div class="form-group">
<label class="col-md-3 control-label" for="id_identifier">{% trans "Channel type" %}</label>
<div class="col-md-9">
<input type="text" value="{{ type.verbose_name }}" class="form-control" disabled>
</div>
</div>
{% bootstrap_field form.identifier addon_before=identifier_prefix layout="control" %}
<div class="form-group submit-group">
<button type="submit" class="btn btn-primary btn-save">
{% trans "Save" %}
</button>
</div>
</form>
{% endblock %}

View File

@@ -0,0 +1,26 @@
{% extends "pretixcontrol/organizers/base.html" %}
{% load i18n %}
{% load static %}
{% load bootstrap3 %}
{% block inner %}
<h1>{% trans "Add sales channel" %}</h1>
<div class="list-group large-link-group">
{% for t in types %}
<a class="list-group-item" href="?type={{ t.identifier }}">
<h4>
{% if "." in t.icon %}
<img class="fa-like-image" src="{% static t.icon %}" alt="">
{% else %}
<span class="fa fa-fw fa-{{ t.icon }} text-muted"></span>
{% endif %}
{{ t.verbose_name }}
</h4>
{% if t.description %}
<p>
{{ t.description }}
</p>
{% endif %}
</a>
{% endfor %}
</div>
{% endblock %}

View File

@@ -0,0 +1,33 @@
{% extends "pretixcontrol/organizers/base.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% block inner %}
<h1>{% trans "Delete sales channel:" %} {{ channel.label }}</h1>
<form action="" method="post" class="form-horizontal">
{% csrf_token %}
{% if is_allowed %}
<p>
{% blocktrans trimmed %}
Are you sure you want to delete this sales channel?
{% endblocktrans %}
{% else %}
<div class="alert alert-danger">
{% blocktrans trimmed %}
This sales channel cannot be deleted since it has already been used to sell orders or because it is
a core element of the system.
{% endblocktrans %}
</div>
{% endif %}
<div class="form-group submit-group">
<a href="{% url "control:organizer.channels" organizer=request.organizer.slug %}"
class="btn btn-default btn-cancel">
{% trans "Cancel" %}
</a>
{% if is_allowed %}
<button type="submit" class="btn btn-danger btn-save">
{% trans "Delete" %}
</button>
{% endif %}
</div>
</form>
{% endblock %}

View File

@@ -0,0 +1,27 @@
{% extends "pretixcontrol/organizers/base.html" %}
{% load i18n %}
{% load formset_tags %}
{% load bootstrap3 %}
{% block inner %}
<h1>{% trans "Sales channel:" %} {{ channel.label }}</h1>
<form class="form-horizontal" action="" method="post">
{% csrf_token %}
{% bootstrap_form_errors form layout="control" %}
{% bootstrap_field form.label layout="control" %}
<div class="form-group">
<label class="col-md-3 control-label" for="id_identifier">{% trans "Channel type" %}</label>
<div class="col-md-9">
<input type="text" value="{{ type.verbose_name }}" class="form-control" disabled>
</div>
</div>
{% bootstrap_field form.identifier layout="control" %}
<div class="form-group submit-group">
<button type="submit" class="btn btn-primary btn-save">
{% trans "Save" %}
</button>
</div>
</form>
{% endblock %}

View File

@@ -0,0 +1,64 @@
{% extends "pretixcontrol/organizers/base.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% load static %}
{% block inner %}
<h1>{% trans "Sales channels" %}</h1>
<p>
{% blocktrans trimmed %}
On this page, you can manage the different channels your tickets can be sold through. This is useful
to unlock new revenue streams or to separate revenue between different sources for reporting purchases.
{% endblocktrans %}
</p>
<a href="{% url "control:organizer.channel.add" organizer=request.organizer.slug %}" class="btn btn-default">
<span class="fa fa-plus"></span>
{% trans "Add a new channel" %}
</a>
<form method="post">
{% csrf_token %}
<table class="table table-condensed table-hover">
<thead>
<tr>
<th>{% trans "Channel" %}</th>
<th>{% trans "Identifier" %}</th>
<th>{% trans "Channel type" %}</th>
<th class="action-col-2"></th>
<th class="action-col-2"></th>
</tr>
</thead>
<tbody data-dnd-url="{% url "control:organizer.channels.reorder" organizer=request.organizer.slug %}">
{% for c in channels %}
<tr data-dnd-id="{{ c.pk }}">
<td><strong>
<a href="{% url "control:organizer.channel.edit" organizer=request.organizer.slug channel=c.identifier %}">
{{ c.label }}
</a>
</strong></td>
<td>
<code>{{ c.identifier }}</code>
</td>
<td>
{% if "." in c.type_instance.icon %}
<img class="fa-like-image" src="{% static c.icon %}" alt="">
{% else %}
<span class="fa fa-fw fa-{{ c.type_instance.icon }} text-muted"></span>
{% endif %}
{{ c.type_instance.verbose_name }}
</td>
<td>
<button formaction="{% url "control:organizer.channel.up" organizer=request.organizer.slug channel=c.identifier %}" class="btn btn-default btn-sm sortable-up"{% if forloop.counter0 == 0 and not page_obj.has_previous %} disabled{% endif %}><i class="fa fa-arrow-up"></i></button>
<button formaction="{% url "control:organizer.channel.down" organizer=request.organizer.slug channel=c.identifier %}" class="btn btn-default btn-sm sortable-down"{% if forloop.revcounter0 == 0 and not page_obj.has_next %} disabled{% endif %}><i class="fa fa-arrow-down"></i></button>
<span class="dnd-container"></span>
</td>
<td class="text-right flip">
<a href="{% url "control:organizer.channel.edit" organizer=request.organizer.slug channel=c.identifier %}"
class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
<a href="{% url "control:organizer.channel.delete" organizer=request.organizer.slug channel=c.identifier %}"
class="btn btn-danger btn-sm {% if c.type_instance.default_created %}disabled{% endif %}"><i class="fa fa-trash"></i></a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</form>
{% endblock %}

View File

@@ -2,6 +2,7 @@
{% load i18n %}
{% load bootstrap3 %}
{% load money %}
{% load static %}
{% block title %}
{% blocktrans trimmed with id=customer.identifier %}
Customer #{{ id }}
@@ -225,8 +226,13 @@
{{ o.event }}
</td>
<td>
<span class="fa fa-{{ o.sales_channel_obj.icon }} text-muted"
data-toggle="tooltip" title="{% trans o.sales_channel_obj.verbose_name %}"></span>
{% if "." in o.sales_channel.icon %}
<img src="{% static o.sales_channel.icon %}" class="fa-like-image"
data-toggle="tooltip" title="{{ o.sales_channel.label }}">
{% else %}
<span class="fa fa-{{ o.sales_channel.icon }} text-muted"
data-toggle="tooltip" title="{{ o.sales_channel.label }}"></span>
{% endif %}
{{ o.datetime|date:"SHORT_DATETIME_FORMAT" }}
{% if o.customer_id != customer.pk %}
<span class="fa fa-link text-muted"