mirror of
https://github.com/pretix/pretix.git
synced 2025-12-16 15:02:28 +00:00
Compare commits
32 Commits
widget_ema
...
api-create
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4619901a37 | ||
|
|
ee921a6331 | ||
|
|
3310e9670b | ||
|
|
93570d42c7 | ||
|
|
598527073c | ||
|
|
d011651565 | ||
|
|
0079be68d3 | ||
|
|
5bf6980a7b | ||
|
|
7e8ef47537 | ||
|
|
86120d0296 | ||
|
|
e2086a8eca | ||
|
|
ad7c4a957d | ||
|
|
f1fbb08c2b | ||
|
|
73b58cfb89 | ||
|
|
4323366ec3 | ||
|
|
4d6b63e1c2 | ||
|
|
6edc12a89f | ||
|
|
e473d0bfce | ||
|
|
42469402b6 | ||
|
|
fd70d567e0 | ||
|
|
2b4d70fa30 | ||
|
|
3c27aa8591 | ||
|
|
a1d6d636a8 | ||
|
|
373f9e666f | ||
|
|
e524055249 | ||
|
|
85ae181ce8 | ||
|
|
cfae2c62c3 | ||
|
|
9c781a174d | ||
|
|
f7cba6a2bd | ||
|
|
c4436ca319 | ||
|
|
c87401ef5d | ||
|
|
a53def0947 |
@@ -75,8 +75,9 @@ positions list of objects List of order p
|
|||||||
fees list of objects List of fees included in the order total. By default, only
|
fees list of objects List of fees included in the order total. By default, only
|
||||||
non-canceled fees are included.
|
non-canceled fees are included.
|
||||||
├ id integer Internal ID of the fee record
|
├ id integer Internal ID of the fee record
|
||||||
├ fee_type string Type of fee (currently ``payment``, ``passbook``,
|
├ fee_type string Type of fee (currently ``payment``, ``shipping``,
|
||||||
``other``)
|
``service``, ``cancellation``, ``insurance``, ``late``,
|
||||||
|
``other``, ``giftcard``)
|
||||||
├ value money (string) Fee amount
|
├ value money (string) Fee amount
|
||||||
├ description string Human-readable string with more details (can be empty)
|
├ description string Human-readable string with more details (can be empty)
|
||||||
├ internal_type string Internal string (i.e. ID of the payment provider),
|
├ internal_type string Internal string (i.e. ID of the payment provider),
|
||||||
@@ -109,6 +110,7 @@ cancellation_date datetime Time of order c
|
|||||||
Will not be set for partial cancellations and is not
|
Will not be set for partial cancellations and is not
|
||||||
reliable for orders that have been cancelled,
|
reliable for orders that have been cancelled,
|
||||||
reactivated and cancelled again.
|
reactivated and cancelled again.
|
||||||
|
plugin_data object Additional data added by plugins.
|
||||||
===================================== ========================== =======================================================
|
===================================== ========================== =======================================================
|
||||||
|
|
||||||
|
|
||||||
@@ -164,6 +166,10 @@ cancellation_date datetime Time of order c
|
|||||||
|
|
||||||
The ``tax_code`` attribute has been added.
|
The ``tax_code`` attribute has been added.
|
||||||
|
|
||||||
|
.. versionchanged:: 2025.2
|
||||||
|
|
||||||
|
The ``plugin_data`` attribute has been added.
|
||||||
|
|
||||||
.. _order-position-resource:
|
.. _order-position-resource:
|
||||||
|
|
||||||
Order position resource
|
Order position resource
|
||||||
@@ -251,6 +257,7 @@ seat objects The assigned se
|
|||||||
pdf_data object Data object required for ticket PDF generation. By default,
|
pdf_data object Data object required for ticket PDF generation. By default,
|
||||||
this field is missing. It will be added only if you add the
|
this field is missing. It will be added only if you add the
|
||||||
``pdf_data=true`` query parameter to your request.
|
``pdf_data=true`` query parameter to your request.
|
||||||
|
plugin_data object Additional data added by plugins.
|
||||||
===================================== ========================== =======================================================
|
===================================== ========================== =======================================================
|
||||||
|
|
||||||
.. versionchanged:: 4.16
|
.. versionchanged:: 4.16
|
||||||
@@ -265,6 +272,10 @@ pdf_data object Data object req
|
|||||||
|
|
||||||
The ``tax_code`` attribute has been added.
|
The ``tax_code`` attribute has been added.
|
||||||
|
|
||||||
|
.. versionchanged:: 2025.2
|
||||||
|
|
||||||
|
The ``plugin_data`` attribute has been added.
|
||||||
|
|
||||||
.. _order-payment-resource:
|
.. _order-payment-resource:
|
||||||
|
|
||||||
Order payment resource
|
Order payment resource
|
||||||
@@ -461,7 +472,8 @@ List of all orders
|
|||||||
"output": "pdf",
|
"output": "pdf",
|
||||||
"url": "https://pretix.eu/api/v1/organizers/bigevents/events/sampleconf/orderpositions/23442/download/pdf/"
|
"url": "https://pretix.eu/api/v1/organizers/bigevents/events/sampleconf/orderpositions/23442/download/pdf/"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"plugin_data": {}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"downloads": [
|
"downloads": [
|
||||||
@@ -483,7 +495,8 @@ List of all orders
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"refunds": [],
|
"refunds": [],
|
||||||
"cancellation_date": null
|
"cancellation_date": null,
|
||||||
|
"plugin_data": {}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -702,7 +715,8 @@ Fetching individual orders
|
|||||||
"output": "pdf",
|
"output": "pdf",
|
||||||
"url": "https://pretix.eu/api/v1/organizers/bigevents/events/sampleconf/orderpositions/23442/download/pdf/"
|
"url": "https://pretix.eu/api/v1/organizers/bigevents/events/sampleconf/orderpositions/23442/download/pdf/"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"plugin_data": {}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"downloads": [
|
"downloads": [
|
||||||
@@ -724,7 +738,8 @@ Fetching individual orders
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"refunds": [],
|
"refunds": [],
|
||||||
"cancellation_date": null
|
"cancellation_date": null,
|
||||||
|
"plugin_data": {}
|
||||||
}
|
}
|
||||||
|
|
||||||
:param organizer: The ``slug`` field of the organizer to fetch
|
:param organizer: The ``slug`` field of the organizer to fetch
|
||||||
@@ -1671,7 +1686,8 @@ List of all order positions
|
|||||||
"output": "pdf",
|
"output": "pdf",
|
||||||
"url": "https://pretix.eu/api/v1/organizers/bigevents/events/sampleconf/orderpositions/23442/download/pdf/"
|
"url": "https://pretix.eu/api/v1/organizers/bigevents/events/sampleconf/orderpositions/23442/download/pdf/"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"plugin_data": {}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -1798,7 +1814,8 @@ Fetching individual positions
|
|||||||
"output": "pdf",
|
"output": "pdf",
|
||||||
"url": "https://pretix.eu/api/v1/organizers/bigevents/events/sampleconf/orderpositions/23442/download/pdf/"
|
"url": "https://pretix.eu/api/v1/organizers/bigevents/events/sampleconf/orderpositions/23442/download/pdf/"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"plugin_data": {}
|
||||||
}
|
}
|
||||||
|
|
||||||
:param organizer: The ``slug`` field of the organizer to fetch
|
:param organizer: The ``slug`` field of the organizer to fetch
|
||||||
@@ -2228,6 +2245,9 @@ otherwise, such as splitting an order or changing fees.
|
|||||||
|
|
||||||
* ``cancel_fees``: A list of objects with the single key ``fee`` specifying an order fee ID.
|
* ``cancel_fees``: A list of objects with the single key ``fee`` specifying an order fee ID.
|
||||||
|
|
||||||
|
* ``create_fees``: A list of objects describing new order fees with the fields ``fee_type``, ``value``, ``description``,
|
||||||
|
``internal_type``, ``tax_rule``
|
||||||
|
|
||||||
* ``recalculate_taxes``: If set to ``"keep_net"``, all taxes will be recalculated based on the tax rule and invoice
|
* ``recalculate_taxes``: If set to ``"keep_net"``, all taxes will be recalculated based on the tax rule and invoice
|
||||||
address, the net price will be kept. If set to ``"keep_gross"``, the gross price will be kept. If set to ``null``
|
address, the net price will be kept. If set to ``"keep_gross"``, the gross price will be kept. If set to ``null``
|
||||||
(the default) the taxes are not recalculated.
|
(the default) the taxes are not recalculated.
|
||||||
@@ -2247,17 +2267,12 @@ otherwise, such as splitting an order or changing fees.
|
|||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|
||||||
{
|
{
|
||||||
"cancel_positions": [
|
|
||||||
{
|
|
||||||
"position": 12373
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"patch_positions": [
|
"patch_positions": [
|
||||||
{
|
{
|
||||||
"position": 12374,
|
"position": 12374,
|
||||||
"body": {
|
"body": {
|
||||||
"item": 12,
|
"item": 12,
|
||||||
"variation": None,
|
"variation": null,
|
||||||
"subevent": 562,
|
"subevent": 562,
|
||||||
"seat": "seat-guid-2",
|
"seat": "seat-guid-2",
|
||||||
"price": "99.99",
|
"price": "99.99",
|
||||||
@@ -2265,6 +2280,11 @@ otherwise, such as splitting an order or changing fees.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"cancel_positions": [
|
||||||
|
{
|
||||||
|
"position": 12373
|
||||||
|
}
|
||||||
|
],
|
||||||
"split_positions": [
|
"split_positions": [
|
||||||
{
|
{
|
||||||
"position": 12375
|
"position": 12375
|
||||||
@@ -2273,7 +2293,7 @@ otherwise, such as splitting an order or changing fees.
|
|||||||
"create_positions": [
|
"create_positions": [
|
||||||
{
|
{
|
||||||
"item": 12,
|
"item": 12,
|
||||||
"variation": None,
|
"variation": null,
|
||||||
"subevent": 562,
|
"subevent": 562,
|
||||||
"seat": "seat-guid-2",
|
"seat": "seat-guid-2",
|
||||||
"price": "99.99",
|
"price": "99.99",
|
||||||
@@ -2281,12 +2301,7 @@ otherwise, such as splitting an order or changing fees.
|
|||||||
"attendee_name": "Peter",
|
"attendee_name": "Peter",
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"cancel_fees": [
|
"patch_fees": [
|
||||||
{
|
|
||||||
"fee": 49
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"change_fees": [
|
|
||||||
{
|
{
|
||||||
"fee": 51,
|
"fee": 51,
|
||||||
"body": {
|
"body": {
|
||||||
@@ -2294,6 +2309,20 @@ otherwise, such as splitting an order or changing fees.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"cancel_fees": [
|
||||||
|
{
|
||||||
|
"fee": 49
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"create_fees": [
|
||||||
|
{
|
||||||
|
"fee_type": "other",
|
||||||
|
"value": "1.50",
|
||||||
|
"description": "Example Fee",
|
||||||
|
"internal_type": "",
|
||||||
|
"tax_rule": 15
|
||||||
|
}
|
||||||
|
],
|
||||||
"reissue_invoice": true,
|
"reissue_invoice": true,
|
||||||
"send_email": true,
|
"send_email": true,
|
||||||
"recalculate_taxes": "keep_gross"
|
"recalculate_taxes": "keep_gross"
|
||||||
|
|||||||
@@ -103,4 +103,4 @@ API
|
|||||||
|
|
||||||
.. automodule:: pretix.api.signals
|
.. automodule:: pretix.api.signals
|
||||||
:no-index:
|
:no-index:
|
||||||
:members: register_device_security_profile
|
:members: register_device_security_profile, order_api_details, orderposition_api_details
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ LANGUAGES_RTL = {
|
|||||||
'ar', 'hw'
|
'ar', 'hw'
|
||||||
}
|
}
|
||||||
LANGUAGES_INCUBATING = {
|
LANGUAGES_INCUBATING = {
|
||||||
'fi', 'pt-br', 'gl',
|
'pt-br', 'gl',
|
||||||
}
|
}
|
||||||
LANGUAGES = ALL_LANGUAGES
|
LANGUAGES = ALL_LANGUAGES
|
||||||
LOCALE_PATHS = [
|
LOCALE_PATHS = [
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ from pretix.api.serializers.i18n import I18nAwareModelSerializer
|
|||||||
from pretix.api.serializers.item import (
|
from pretix.api.serializers.item import (
|
||||||
InlineItemVariationSerializer, ItemSerializer, QuestionSerializer,
|
InlineItemVariationSerializer, ItemSerializer, QuestionSerializer,
|
||||||
)
|
)
|
||||||
|
from pretix.api.signals import order_api_details, orderposition_api_details
|
||||||
from pretix.base.decimal import round_decimal
|
from pretix.base.decimal import round_decimal
|
||||||
from pretix.base.i18n import language
|
from pretix.base.i18n import language
|
||||||
from pretix.base.models import (
|
from pretix.base.models import (
|
||||||
@@ -494,6 +495,18 @@ class OrderPositionListSerializer(serializers.ListSerializer):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
class OrderPositionPluginDataField(serializers.Field):
|
||||||
|
def to_representation(self, value: OrderPosition):
|
||||||
|
d = {}
|
||||||
|
if value and value.pk:
|
||||||
|
for recv, resp in orderposition_api_details.send(
|
||||||
|
sender=self.context.get("event") or value.order.event,
|
||||||
|
orderposition=value
|
||||||
|
):
|
||||||
|
d.update(resp)
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
class OrderPositionSerializer(I18nAwareModelSerializer):
|
class OrderPositionSerializer(I18nAwareModelSerializer):
|
||||||
checkins = CheckinSerializer(many=True, read_only=True)
|
checkins = CheckinSerializer(many=True, read_only=True)
|
||||||
print_logs = PrintLogSerializer(many=True, read_only=True)
|
print_logs = PrintLogSerializer(many=True, read_only=True)
|
||||||
@@ -504,6 +517,7 @@ class OrderPositionSerializer(I18nAwareModelSerializer):
|
|||||||
seat = InlineSeatSerializer(read_only=True)
|
seat = InlineSeatSerializer(read_only=True)
|
||||||
country = CompatibleCountryField(source='*')
|
country = CompatibleCountryField(source='*')
|
||||||
attendee_name = serializers.CharField(required=False)
|
attendee_name = serializers.CharField(required=False)
|
||||||
|
plugin_data = OrderPositionPluginDataField(source='*', allow_null=True, read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
list_serializer_class = OrderPositionListSerializer
|
list_serializer_class = OrderPositionListSerializer
|
||||||
@@ -513,7 +527,7 @@ class OrderPositionSerializer(I18nAwareModelSerializer):
|
|||||||
'attendee_email', 'voucher', 'tax_rate', 'tax_value', 'secret', 'addon_to', 'subevent', 'checkins',
|
'attendee_email', 'voucher', 'tax_rate', 'tax_value', 'secret', 'addon_to', 'subevent', 'checkins',
|
||||||
'print_logs', 'downloads', 'answers', 'tax_rule', 'pseudonymization_id', 'pdf_data', 'seat', 'canceled',
|
'print_logs', 'downloads', 'answers', 'tax_rule', 'pseudonymization_id', 'pdf_data', 'seat', 'canceled',
|
||||||
'print_logs', 'downloads', 'answers', 'tax_rule', 'tax_code', 'pseudonymization_id', 'pdf_data', 'seat',
|
'print_logs', 'downloads', 'answers', 'tax_rule', 'tax_code', 'pseudonymization_id', 'pdf_data', 'seat',
|
||||||
'canceled', 'valid_from', 'valid_until', 'blocked', 'voucher_budget_use')
|
'canceled', 'valid_from', 'valid_until', 'blocked', 'voucher_budget_use', 'plugin_data')
|
||||||
read_only_fields = (
|
read_only_fields = (
|
||||||
'id', 'order', 'positionid', 'item', 'variation', 'price', 'voucher', 'tax_rate', 'tax_value', 'secret',
|
'id', 'order', 'positionid', 'item', 'variation', 'price', 'voucher', 'tax_rate', 'tax_value', 'secret',
|
||||||
'addon_to', 'subevent', 'checkins', 'downloads', 'answers', 'tax_rule', 'tax_code', 'pseudonymization_id',
|
'addon_to', 'subevent', 'checkins', 'downloads', 'answers', 'tax_rule', 'tax_code', 'pseudonymization_id',
|
||||||
@@ -730,6 +744,18 @@ class OrderListSerializer(serializers.ListSerializer):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
class OrderPluginDataField(serializers.Field):
|
||||||
|
def to_representation(self, value: Order):
|
||||||
|
d = {}
|
||||||
|
if value and value.pk:
|
||||||
|
for recv, resp in order_api_details.send(
|
||||||
|
sender=self.context.get("event") or value.event,
|
||||||
|
order=value
|
||||||
|
):
|
||||||
|
d.update(resp)
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
class OrderSerializer(I18nAwareModelSerializer):
|
class OrderSerializer(I18nAwareModelSerializer):
|
||||||
event = SlugRelatedField(slug_field='slug', read_only=True)
|
event = SlugRelatedField(slug_field='slug', read_only=True)
|
||||||
invoice_address = InvoiceAddressSerializer(allow_null=True)
|
invoice_address = InvoiceAddressSerializer(allow_null=True)
|
||||||
@@ -747,6 +773,7 @@ class OrderSerializer(I18nAwareModelSerializer):
|
|||||||
queryset=SalesChannel.objects.none(),
|
queryset=SalesChannel.objects.none(),
|
||||||
required=False,
|
required=False,
|
||||||
)
|
)
|
||||||
|
plugin_data = OrderPluginDataField(source='*', allow_null=True, read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Order
|
model = Order
|
||||||
@@ -755,7 +782,7 @@ class OrderSerializer(I18nAwareModelSerializer):
|
|||||||
'code', 'event', 'status', 'testmode', 'secret', 'email', 'phone', 'locale', 'datetime', 'expires', 'payment_date',
|
'code', 'event', 'status', 'testmode', 'secret', 'email', 'phone', 'locale', 'datetime', 'expires', 'payment_date',
|
||||||
'payment_provider', 'fees', 'total', 'comment', 'custom_followup_at', 'invoice_address', 'positions', 'downloads',
|
'payment_provider', 'fees', 'total', 'comment', 'custom_followup_at', 'invoice_address', 'positions', 'downloads',
|
||||||
'checkin_attention', 'checkin_text', 'last_modified', 'payments', 'refunds', 'require_approval', 'sales_channel',
|
'checkin_attention', 'checkin_text', 'last_modified', 'payments', 'refunds', 'require_approval', 'sales_channel',
|
||||||
'url', 'customer', 'valid_if_pending', 'api_meta', 'cancellation_date'
|
'url', 'customer', 'valid_if_pending', 'api_meta', 'cancellation_date', 'plugin_data',
|
||||||
)
|
)
|
||||||
read_only_fields = (
|
read_only_fields = (
|
||||||
'code', 'status', 'testmode', 'secret', 'datetime', 'expires', 'payment_date',
|
'code', 'status', 'testmode', 'secret', 'datetime', 'expires', 'payment_date',
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ from rest_framework.exceptions import ValidationError
|
|||||||
|
|
||||||
from pretix.api.serializers.order import (
|
from pretix.api.serializers.order import (
|
||||||
AnswerCreateSerializer, AnswerSerializer, CompatibleCountryField,
|
AnswerCreateSerializer, AnswerSerializer, CompatibleCountryField,
|
||||||
OrderPositionCreateSerializer,
|
OrderFeeCreateSerializer, OrderPositionCreateSerializer,
|
||||||
)
|
)
|
||||||
from pretix.base.models import ItemVariation, Order, OrderFee, OrderPosition
|
from pretix.base.models import ItemVariation, Order, OrderFee, OrderPosition
|
||||||
from pretix.base.services.orders import OrderError
|
from pretix.base.services.orders import OrderError
|
||||||
@@ -104,6 +104,54 @@ class OrderPositionCreateForExistingOrderSerializer(OrderPositionCreateSerialize
|
|||||||
raise ValidationError(str(e))
|
raise ValidationError(str(e))
|
||||||
|
|
||||||
|
|
||||||
|
class OrderFeeCreateForExistingOrderSerializer(OrderFeeCreateSerializer):
|
||||||
|
order = serializers.SlugRelatedField(slug_field='code', queryset=Order.objects.none(), required=True, allow_null=False)
|
||||||
|
value = serializers.DecimalField(required=True, allow_null=False, decimal_places=2,
|
||||||
|
max_digits=13)
|
||||||
|
internal_type = serializers.CharField(required=False, default="")
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = OrderFee
|
||||||
|
fields = ('order', 'fee_type', 'value', 'description', 'internal_type', 'tax_rule')
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
if not self.context:
|
||||||
|
return
|
||||||
|
self.fields['order'].queryset = self.context['event'].orders.all()
|
||||||
|
self.fields['tax_rule'].queryset = self.context['event'].tax_rules.all()
|
||||||
|
if 'order' in self.context:
|
||||||
|
del self.fields['order']
|
||||||
|
|
||||||
|
def validate(self, data):
|
||||||
|
data = super().validate(data)
|
||||||
|
if 'order' in self.context:
|
||||||
|
data['order'] = self.context['order']
|
||||||
|
return data
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
ocm = self.context['ocm']
|
||||||
|
|
||||||
|
try:
|
||||||
|
f = OrderFee(
|
||||||
|
order=validated_data['order'],
|
||||||
|
fee_type=validated_data['fee_type'],
|
||||||
|
value=validated_data.get('value'),
|
||||||
|
description=validated_data.get('description'),
|
||||||
|
internal_type=validated_data.get('internal_type'),
|
||||||
|
tax_rule=validated_data.get('tax_rule'),
|
||||||
|
)
|
||||||
|
f._calculate_tax()
|
||||||
|
ocm.add_fee(f)
|
||||||
|
if self.context.get('commit', True):
|
||||||
|
ocm.commit()
|
||||||
|
return validated_data['order'].fees.order_by('-pk').first()
|
||||||
|
else:
|
||||||
|
return OrderFee() # fake to appease DRF
|
||||||
|
except OrderError as e:
|
||||||
|
raise ValidationError(str(e))
|
||||||
|
|
||||||
|
|
||||||
class OrderPositionInfoPatchSerializer(serializers.ModelSerializer):
|
class OrderPositionInfoPatchSerializer(serializers.ModelSerializer):
|
||||||
answers = AnswerSerializer(many=True)
|
answers = AnswerSerializer(many=True)
|
||||||
country = CompatibleCountryField(source='*')
|
country = CompatibleCountryField(source='*')
|
||||||
@@ -401,6 +449,9 @@ class OrderChangeOperationSerializer(serializers.Serializer):
|
|||||||
self.fields['split_positions'] = SelectPositionSerializer(
|
self.fields['split_positions'] = SelectPositionSerializer(
|
||||||
many=True, required=False, context=self.context
|
many=True, required=False, context=self.context
|
||||||
)
|
)
|
||||||
|
self.fields['create_fees'] = OrderFeeCreateForExistingOrderSerializer(
|
||||||
|
many=True, required=False, context=self.context
|
||||||
|
)
|
||||||
self.fields['patch_fees'] = PatchFeeSerializer(
|
self.fields['patch_fees'] = PatchFeeSerializer(
|
||||||
many=True, required=False, context=self.context
|
many=True, required=False, context=self.context
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ from django.utils.timezone import now
|
|||||||
from django_scopes import scopes_disabled
|
from django_scopes import scopes_disabled
|
||||||
|
|
||||||
from pretix.api.models import ApiCall, WebHookCall
|
from pretix.api.models import ApiCall, WebHookCall
|
||||||
from pretix.base.signals import periodic_task
|
from pretix.base.signals import EventPluginSignal, periodic_task
|
||||||
from pretix.helpers.periodic import minimum_interval
|
from pretix.helpers.periodic import minimum_interval
|
||||||
|
|
||||||
register_webhook_events = Signal()
|
register_webhook_events = Signal()
|
||||||
@@ -43,6 +43,28 @@ return an instance of a subclass of ``pretix.api.auth.devicesecurity.BaseSecurit
|
|||||||
or a list of such instances.
|
or a list of such instances.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
order_api_details = EventPluginSignal()
|
||||||
|
"""
|
||||||
|
Arguments: ``order``
|
||||||
|
|
||||||
|
This signal is sent out to fill the ``plugin_details`` field of the order API. Receivers
|
||||||
|
should return a dictionary that is combined with the dictionaries of all other plugins.
|
||||||
|
Note that doing database or network queries in receivers to this signal is discouraged
|
||||||
|
and could cause serious performance issues. The main purpose is to provide information
|
||||||
|
from e.g. ``meta_info`` to the API consumer,
|
||||||
|
"""
|
||||||
|
|
||||||
|
orderposition_api_details = EventPluginSignal()
|
||||||
|
"""
|
||||||
|
Arguments: ``orderposition``
|
||||||
|
|
||||||
|
This signal is sent out to fill the ``plugin_details`` field of the order API. Receivers
|
||||||
|
should return a dictionary that is combined with the dictionaries of all other plugins.
|
||||||
|
Note that doing database or network queries in receivers to this signal is discouraged
|
||||||
|
and could cause serious performance issues. The main purpose is to provide information
|
||||||
|
from e.g. ``meta_info`` to the API consumer,
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
@receiver(periodic_task)
|
@receiver(periodic_task)
|
||||||
@scopes_disabled()
|
@scopes_disabled()
|
||||||
|
|||||||
@@ -63,7 +63,8 @@ from pretix.api.serializers.order import (
|
|||||||
)
|
)
|
||||||
from pretix.api.serializers.orderchange import (
|
from pretix.api.serializers.orderchange import (
|
||||||
BlockNameSerializer, OrderChangeOperationSerializer,
|
BlockNameSerializer, OrderChangeOperationSerializer,
|
||||||
OrderFeeChangeSerializer, OrderPositionChangeSerializer,
|
OrderFeeChangeSerializer, OrderFeeCreateForExistingOrderSerializer,
|
||||||
|
OrderPositionChangeSerializer,
|
||||||
OrderPositionCreateForExistingOrderSerializer,
|
OrderPositionCreateForExistingOrderSerializer,
|
||||||
OrderPositionInfoPatchSerializer,
|
OrderPositionInfoPatchSerializer,
|
||||||
)
|
)
|
||||||
@@ -988,6 +989,12 @@ class EventOrderViewSet(OrderViewSetMixin, viewsets.ModelViewSet):
|
|||||||
ocm.cancel_fee(r['fee'])
|
ocm.cancel_fee(r['fee'])
|
||||||
canceled_fees.add(r['fee'])
|
canceled_fees.add(r['fee'])
|
||||||
|
|
||||||
|
for r in serializer.validated_data.get('create_fees', []):
|
||||||
|
pos_serializer = OrderFeeCreateForExistingOrderSerializer(
|
||||||
|
context={'ocm': ocm, 'commit': False, 'event': request.event, **self.get_serializer_context()},
|
||||||
|
)
|
||||||
|
pos_serializer.create(r)
|
||||||
|
|
||||||
for r in serializer.validated_data.get('patch_fees', []):
|
for r in serializer.validated_data.get('patch_fees', []):
|
||||||
if r['fee'] in canceled_fees:
|
if r['fee'] in canceled_fees:
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -1308,10 +1308,13 @@ DEFAULTS = {
|
|||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
'form_class': forms.BooleanField,
|
'form_class': forms.BooleanField,
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Show event times and dates on the ticket shop"),
|
label=_("This shop represents an event"),
|
||||||
help_text=_("If disabled, no date or time will be shown on the ticket shop's front page. This settings "
|
help_text=_(
|
||||||
"also affects a few other locations, however it should not be expected that the date of the "
|
"Uncheck this box if you are only selling something that has no specific date, such as gift cards or a "
|
||||||
"event is shown nowhere to users."),
|
"ticket that can be used any time. The system will then stop showing the event date in some places like "
|
||||||
|
"the event start page. Note that pretix still is a system built around events and the date may still "
|
||||||
|
"show up in other places."
|
||||||
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
'show_date_to': {
|
'show_date_to': {
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ class OrderChangeLogEntryType(OrderLogEntryType):
|
|||||||
prefix = _('The order has been changed:')
|
prefix = _('The order has been changed:')
|
||||||
|
|
||||||
def display(self, logentry, data):
|
def display(self, logentry, data):
|
||||||
return self.prefix + ' ' + self.display_prefixed(logentry.event, logentry, data)
|
return format_html('{} {}', self.prefix, self.display_prefixed(logentry.event, logentry, data))
|
||||||
|
|
||||||
def display_prefixed(self, event: Event, logentry: LogEntry, data):
|
def display_prefixed(self, event: Event, logentry: LogEntry, data):
|
||||||
return super().display(logentry, data)
|
return super().display(logentry, data)
|
||||||
@@ -282,12 +282,13 @@ class OrderChangedSplit(OrderChangeLogEntryType):
|
|||||||
'organizer': event.organizer.slug,
|
'organizer': event.organizer.slug,
|
||||||
'code': data['new_order']
|
'code': data['new_order']
|
||||||
})
|
})
|
||||||
return mark_safe(self.prefix + ' ' + _('Position #{posid} ({old_item}, {old_price}) split into new order: {order}').format(
|
return format_html(
|
||||||
|
_('Position #{posid} ({old_item}, {old_price}) split into new order: {order}'),
|
||||||
old_item=escape(old_item),
|
old_item=escape(old_item),
|
||||||
posid=data.get('positionid', '?'),
|
posid=data.get('positionid', '?'),
|
||||||
order='<a href="{}">{}</a>'.format(url, data['new_order']),
|
order=format_html(mark_safe('<a href="{}">{}</a>'), url, data['new_order']),
|
||||||
old_price=money_filter(Decimal(data['old_price']), event.currency),
|
old_price=money_filter(Decimal(data['old_price']), event.currency),
|
||||||
))
|
)
|
||||||
|
|
||||||
|
|
||||||
@log_entry_types.new()
|
@log_entry_types.new()
|
||||||
@@ -295,8 +296,14 @@ class OrderChangedSplitFrom(OrderLogEntryType):
|
|||||||
action_type = 'pretix.event.order.changed.split_from'
|
action_type = 'pretix.event.order.changed.split_from'
|
||||||
|
|
||||||
def display(self, logentry: LogEntry, data):
|
def display(self, logentry: LogEntry, data):
|
||||||
return _('This order has been created by splitting the order {order}').format(
|
url = reverse('control:event.order', kwargs={
|
||||||
order=data['original_order'],
|
'event': logentry.event.slug,
|
||||||
|
'organizer': logentry.event.organizer.slug,
|
||||||
|
'code': data['original_order']
|
||||||
|
})
|
||||||
|
return format_html(
|
||||||
|
_('This order has been created by splitting the order {order}'),
|
||||||
|
order=format_html(mark_safe('<a href="{}">{}</a>'), url, data['original_order']),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -318,7 +325,7 @@ class OrderChangedSplitFrom(OrderLogEntryType):
|
|||||||
})
|
})
|
||||||
class CheckinErrorLogEntryType(OrderLogEntryType):
|
class CheckinErrorLogEntryType(OrderLogEntryType):
|
||||||
def display(self, logentry: LogEntry, data):
|
def display(self, logentry: LogEntry, data):
|
||||||
self.display_plain(self.plain, logentry, data)
|
return self.display_plain(self.plain, logentry, data)
|
||||||
|
|
||||||
def display_plain(self, plain, logentry: LogEntry, data):
|
def display_plain(self, plain, logentry: LogEntry, data):
|
||||||
if isinstance(plain, tuple):
|
if isinstance(plain, tuple):
|
||||||
@@ -330,7 +337,7 @@ class CheckinErrorLogEntryType(OrderLogEntryType):
|
|||||||
|
|
||||||
event = logentry.event
|
event = logentry.event
|
||||||
|
|
||||||
if 'list' in data:
|
if 'list' in data and event:
|
||||||
try:
|
try:
|
||||||
data['list'] = event.checkin_lists.get(pk=data.get('list')).name
|
data['list'] = event.checkin_lists.get(pk=data.get('list')).name
|
||||||
except CheckinList.DoesNotExist:
|
except CheckinList.DoesNotExist:
|
||||||
@@ -343,12 +350,12 @@ class CheckinErrorLogEntryType(OrderLogEntryType):
|
|||||||
|
|
||||||
if 'datetime' in data:
|
if 'datetime' in data:
|
||||||
dt = dateutil.parser.parse(data.get('datetime'))
|
dt = dateutil.parser.parse(data.get('datetime'))
|
||||||
if abs((logentry.datetime - dt).total_seconds()) > 5 or 'forced' in data:
|
if abs((logentry.datetime - dt).total_seconds()) > 5 or data.get('forced'):
|
||||||
tz = event.timezone
|
if event:
|
||||||
data['datetime'] = date_format(dt.astimezone(tz), "SHORT_DATETIME_FORMAT")
|
data['datetime'] = date_format(dt.astimezone(event.timezone), "SHORT_DATETIME_FORMAT")
|
||||||
return str(plain_with_dt).format_map(data)
|
return str(plain_with_dt).format_map(data)
|
||||||
else:
|
|
||||||
return str(plain_without_dt).format_map(data)
|
return str(plain_without_dt).format_map(data)
|
||||||
|
|
||||||
|
|
||||||
@log_entry_types.new('pretix.event.checkin')
|
@log_entry_types.new('pretix.event.checkin')
|
||||||
@@ -410,7 +417,7 @@ class OrderPrintLogEntryType(OrderLogEntryType):
|
|||||||
datetime=date_format(
|
datetime=date_format(
|
||||||
dateutil.parser.parse(data["datetime"]).astimezone(logentry.event.timezone),
|
dateutil.parser.parse(data["datetime"]).astimezone(logentry.event.timezone),
|
||||||
"SHORT_DATETIME_FORMAT"
|
"SHORT_DATETIME_FORMAT"
|
||||||
),
|
) if logentry.event else data["datetime"],
|
||||||
type=dict(PrintLog.PRINT_TYPES)[data["type"]],
|
type=dict(PrintLog.PRINT_TYPES)[data["type"]],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -125,6 +125,15 @@
|
|||||||
<button type="submit" class="btn btn-primary btn-save">
|
<button type="submit" class="btn btn-primary btn-save">
|
||||||
{% trans "Save" %}
|
{% trans "Save" %}
|
||||||
</button>
|
</button>
|
||||||
|
{% if voucher.pk %}
|
||||||
|
<div class="pull-left">
|
||||||
|
<a href="{% url "control:event.voucher.delete" organizer=request.organizer.slug event=request.event.slug voucher=voucher.pk %}"
|
||||||
|
class="btn btn-danger btn-lg">
|
||||||
|
<span class="fa fa-trash"></span>
|
||||||
|
{% trans "Delete voucher" %}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ class MessageView(TemplateView):
|
|||||||
class LogDetailView(AdministratorPermissionRequiredMixin, View):
|
class LogDetailView(AdministratorPermissionRequiredMixin, View):
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
le = get_object_or_404(LogEntry, pk=request.GET.get('pk'))
|
le = get_object_or_404(LogEntry, pk=request.GET.get('pk'))
|
||||||
return JsonResponse({'data': le.parsed_data})
|
return JsonResponse({'action_type': le.action_type, 'content_type': str(le.content_type), 'object_id': le.object_id, 'data': le.parsed_data})
|
||||||
|
|
||||||
|
|
||||||
class PaymentDetailView(AdministratorPermissionRequiredMixin, View):
|
class PaymentDetailView(AdministratorPermissionRequiredMixin, View):
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@ msgstr ""
|
|||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-01-29 13:18+0000\n"
|
"POT-Creation-Date: 2025-01-29 13:18+0000\n"
|
||||||
"PO-Revision-Date: 2025-02-05 20:00+0000\n"
|
"PO-Revision-Date: 2025-02-06 18:00+0000\n"
|
||||||
"Last-Translator: 조정화 <junghwa.jo@om.org>\n"
|
"Last-Translator: 조정화 <junghwa.jo@om.org>\n"
|
||||||
"Language-Team: Korean <https://translate.pretix.eu/projects/pretix/pretix/ko/"
|
"Language-Team: Korean <https://translate.pretix.eu/projects/pretix/pretix/ko/"
|
||||||
">\n"
|
">\n"
|
||||||
@@ -516,52 +516,53 @@ msgstr "이벤트 생성"
|
|||||||
|
|
||||||
#: pretix/api/webhooks.py:329
|
#: pretix/api/webhooks.py:329
|
||||||
msgid "Event details changed"
|
msgid "Event details changed"
|
||||||
msgstr ""
|
msgstr "이벤트 세부 정보가 변경되었습니다"
|
||||||
|
|
||||||
#: pretix/api/webhooks.py:333
|
#: pretix/api/webhooks.py:333
|
||||||
msgid "Event deleted"
|
msgid "Event deleted"
|
||||||
msgstr ""
|
msgstr "이벤트 삭제"
|
||||||
|
|
||||||
#: pretix/api/webhooks.py:337
|
#: pretix/api/webhooks.py:337
|
||||||
msgctxt "subevent"
|
msgctxt "subevent"
|
||||||
msgid "Event series date added"
|
msgid "Event series date added"
|
||||||
msgstr ""
|
msgstr "이벤트 시리즈 날짜 추가"
|
||||||
|
|
||||||
#: pretix/api/webhooks.py:341
|
#: pretix/api/webhooks.py:341
|
||||||
msgctxt "subevent"
|
msgctxt "subevent"
|
||||||
msgid "Event series date changed"
|
msgid "Event series date changed"
|
||||||
msgstr ""
|
msgstr "이벤트 시리즈 날짜 변경"
|
||||||
|
|
||||||
#: pretix/api/webhooks.py:345
|
#: pretix/api/webhooks.py:345
|
||||||
msgctxt "subevent"
|
msgctxt "subevent"
|
||||||
msgid "Event series date deleted"
|
msgid "Event series date deleted"
|
||||||
msgstr ""
|
msgstr "이벤트 시리즈 날짜 삭제"
|
||||||
|
|
||||||
#: pretix/api/webhooks.py:349
|
#: pretix/api/webhooks.py:349
|
||||||
msgid ""
|
msgid ""
|
||||||
"Product changed (including product added or deleted and including changes to "
|
"Product changed (including product added or deleted and including changes to "
|
||||||
"nested objects like variations or bundles)"
|
"nested objects like variations or bundles)"
|
||||||
msgstr ""
|
msgstr "제품 변경(제품 추가 또는 삭제, 변형 또는 번들과 같은 중첩된 객체에 대한 변경 "
|
||||||
|
"포함)"
|
||||||
|
|
||||||
#: pretix/api/webhooks.py:354
|
#: pretix/api/webhooks.py:354
|
||||||
msgid "Shop taken live"
|
msgid "Shop taken live"
|
||||||
msgstr ""
|
msgstr "라이브 촬영 상점"
|
||||||
|
|
||||||
#: pretix/api/webhooks.py:358
|
#: pretix/api/webhooks.py:358
|
||||||
msgid "Shop taken offline"
|
msgid "Shop taken offline"
|
||||||
msgstr ""
|
msgstr "오프라인 쇼핑"
|
||||||
|
|
||||||
#: pretix/api/webhooks.py:362
|
#: pretix/api/webhooks.py:362
|
||||||
msgid "Test-Mode of shop has been activated"
|
msgid "Test-Mode of shop has been activated"
|
||||||
msgstr ""
|
msgstr "상점의 테스트 모드가 활성화되었습니다"
|
||||||
|
|
||||||
#: pretix/api/webhooks.py:366
|
#: pretix/api/webhooks.py:366
|
||||||
msgid "Test-Mode of shop has been deactivated"
|
msgid "Test-Mode of shop has been deactivated"
|
||||||
msgstr ""
|
msgstr "상점의 테스트 모드가 비활성화되었습니다"
|
||||||
|
|
||||||
#: pretix/api/webhooks.py:370
|
#: pretix/api/webhooks.py:370
|
||||||
msgid "Waiting list entry added"
|
msgid "Waiting list entry added"
|
||||||
msgstr ""
|
msgstr "대기자 명단 항목 추가"
|
||||||
|
|
||||||
#: pretix/api/webhooks.py:374
|
#: pretix/api/webhooks.py:374
|
||||||
msgid "Waiting list entry changed"
|
msgid "Waiting list entry changed"
|
||||||
|
|||||||
@@ -292,11 +292,11 @@ def _handle_transaction(trans: BankTransaction, matches: tuple, event: Event = N
|
|||||||
trans.save()
|
trans.save()
|
||||||
|
|
||||||
|
|
||||||
def parse_date(date_str):
|
def parse_date(date_str, region=None):
|
||||||
try:
|
try:
|
||||||
return dateutil.parser.parse(
|
return dateutil.parser.parse(
|
||||||
date_str,
|
date_str,
|
||||||
dayfirst="." in date_str,
|
dayfirst="." in date_str or region in ["GB"],
|
||||||
).date()
|
).date()
|
||||||
except (ValueError, OverflowError):
|
except (ValueError, OverflowError):
|
||||||
pass
|
pass
|
||||||
@@ -339,7 +339,7 @@ def _get_unknown_transactions(job: BankImportJob, data: list, event: Event = Non
|
|||||||
external_id=row.get('external_id'),
|
external_id=row.get('external_id'),
|
||||||
currency=event.currency if event else job.currency)
|
currency=event.currency if event else job.currency)
|
||||||
|
|
||||||
trans.date_parsed = parse_date(trans.date)
|
trans.date_parsed = parse_date(trans.date, (event and event.settings.region) or (organizer and organizer.settings.region) or None)
|
||||||
|
|
||||||
trans.checksum = trans.calculate_checksum()
|
trans.checksum = trans.calculate_checksum()
|
||||||
if trans.checksum not in known_checksums and (not trans.external_id or (trans.external_id, trans.date, trans.amount) not in known_by_external_id):
|
if trans.checksum not in known_checksums and (not trans.external_id or (trans.external_id, trans.date, trans.amount) not in known_by_external_id):
|
||||||
|
|||||||
@@ -244,15 +244,16 @@ class AuthorizeView(View):
|
|||||||
response_mode, state)
|
response_mode, state)
|
||||||
|
|
||||||
if "id_token_hint" in request_data:
|
if "id_token_hint" in request_data:
|
||||||
self._redirect_error("invalid_request", "id_token_hint currently not supported by this server",
|
return self._redirect_error("invalid_request", "id_token_hint currently not supported by this server",
|
||||||
redirect_uri, response_mode, state)
|
redirect_uri, response_mode, state)
|
||||||
|
|
||||||
has_valid_session = bool(request.customer)
|
has_valid_session = bool(request.customer)
|
||||||
if has_valid_session and max_age:
|
if has_valid_session and max_age:
|
||||||
try:
|
try:
|
||||||
has_valid_session = int(time.time() - get_customer_auth_time(request)) < int(max_age)
|
has_valid_session = int(time.time() - get_customer_auth_time(request)) < int(max_age)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self._redirect_error("invalid_request", "invalid max_age value", redirect_uri, response_mode, state)
|
return self._redirect_error("invalid_request", "invalid max_age value", redirect_uri,
|
||||||
|
response_mode, state)
|
||||||
|
|
||||||
if not has_valid_session and prompt and prompt == "none":
|
if not has_valid_session and prompt and prompt == "none":
|
||||||
return self._redirect_error("interaction_required", "user is not logged in but no prompt is allowed",
|
return self._redirect_error("interaction_required", "user is not logged in but no prompt is allowed",
|
||||||
|
|||||||
@@ -1065,11 +1065,17 @@ function add_log_expand_handlers(el) {
|
|||||||
} else if ($a.is("[data-expandpayment]")) {
|
} else if ($a.is("[data-expandpayment]")) {
|
||||||
url += 'payment/'
|
url += 'payment/'
|
||||||
}
|
}
|
||||||
|
function format_data(data) {
|
||||||
|
return Object.entries(data).map(([key, value]) =>
|
||||||
|
$("<div>").append(
|
||||||
|
$("<b>").text(key + ': '),
|
||||||
|
$("<span>").text(JSON.stringify(value, null, 2))));
|
||||||
|
}
|
||||||
$.getJSON(url + '?pk=' + id, function (data) {
|
$.getJSON(url + '?pk=' + id, function (data) {
|
||||||
if ($a.parent().tagName === "p") {
|
if ($a.parent().tagName === "p") {
|
||||||
$("<pre>").text(JSON.stringify(data.data, null, 2)).insertAfter($a.parent());
|
$("<pre>").append(format_data(data)).insertAfter($a.parent());
|
||||||
} else {
|
} else {
|
||||||
$("<pre>").text(JSON.stringify(data.data, null, 2)).appendTo($a.parent());
|
$("<pre>").append(format_data(data)).appendTo($a.parent());
|
||||||
}
|
}
|
||||||
$a.remove();
|
$a.remove();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*global $,u2f */
|
/*global $,u2f */
|
||||||
$(function () {
|
$(function () {
|
||||||
$('.sidebar .dropdown, ul.navbar-nav .dropdown, .navbar-events-collapse').on('shown.bs.collapse shown.bs.dropdown', function () {
|
$('.context-selector.dropdown').on('shown.bs.collapse shown.bs.dropdown', function () {
|
||||||
$(this).parent().find("input").val("").trigger('forceRunQuery').focus();
|
$(this).parent().find("input").val("").trigger('forceRunQuery').focus();
|
||||||
});
|
});
|
||||||
$('.dropdown-menu .form-box input').click(function (e) {
|
$('.dropdown-menu .form-box input').click(function (e) {
|
||||||
|
|||||||
@@ -162,6 +162,7 @@ def test_giftcard_detail_expand(token_client, organizer, event, giftcard):
|
|||||||
"tax_rule": None,
|
"tax_rule": None,
|
||||||
"pseudonymization_id": op.pseudonymization_id,
|
"pseudonymization_id": op.pseudonymization_id,
|
||||||
"pdf_data": {},
|
"pdf_data": {},
|
||||||
|
"plugin_data": {},
|
||||||
"seat": None,
|
"seat": None,
|
||||||
"canceled": False,
|
"canceled": False,
|
||||||
"valid_from": None,
|
"valid_from": None,
|
||||||
|
|||||||
@@ -1797,6 +1797,13 @@ def test_order_change_cancel_and_create(token_client, organizer, event, order, q
|
|||||||
'price': '99.99'
|
'price': '99.99'
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
'create_fees': [
|
||||||
|
{
|
||||||
|
'value': '5.99',
|
||||||
|
'fee_type': 'service',
|
||||||
|
'description': 'Service fee',
|
||||||
|
},
|
||||||
|
],
|
||||||
'cancel_fees': [
|
'cancel_fees': [
|
||||||
{
|
{
|
||||||
'fee': f.pk,
|
'fee': f.pk,
|
||||||
@@ -1818,6 +1825,11 @@ def test_order_change_cancel_and_create(token_client, organizer, event, order, q
|
|||||||
assert p_new.price == Decimal('99.99')
|
assert p_new.price == Decimal('99.99')
|
||||||
f.refresh_from_db()
|
f.refresh_from_db()
|
||||||
assert f.canceled
|
assert f.canceled
|
||||||
|
f_new = order.all_fees.get(fee_type=OrderFee.FEE_TYPE_SERVICE)
|
||||||
|
assert f_new.value == Decimal('5.99')
|
||||||
|
assert f_new.description == "Service fee"
|
||||||
|
assert f_new.internal_type == ""
|
||||||
|
assert f_new.tax_value == Decimal('0.00')
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
|
|||||||
@@ -477,7 +477,8 @@ def test_order_create_simulate(token_client, organizer, event, item, quota, ques
|
|||||||
'zipcode': None,
|
'zipcode': None,
|
||||||
'state': None,
|
'state': None,
|
||||||
'country': None,
|
'country': None,
|
||||||
'canceled': False
|
'canceled': False,
|
||||||
|
'plugin_data': {},
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'downloads': [],
|
'downloads': [],
|
||||||
@@ -487,7 +488,8 @@ def test_order_create_simulate(token_client, organizer, event, item, quota, ques
|
|||||||
'refunds': [],
|
'refunds': [],
|
||||||
'require_approval': False,
|
'require_approval': False,
|
||||||
'sales_channel': 'web',
|
'sales_channel': 'web',
|
||||||
'cancellation_date': None
|
'cancellation_date': None,
|
||||||
|
'plugin_data': {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -533,13 +535,15 @@ def test_order_create_positionids_addons_simulated(token_client, organizer, even
|
|||||||
'street': None, 'zipcode': None, 'city': None, 'country': None, 'state': None, 'attendee_email': None,
|
'street': None, 'zipcode': None, 'city': None, 'country': None, 'state': None, 'attendee_email': None,
|
||||||
'voucher': None, 'tax_rate': '19.00', 'tax_code': 'S/standard', 'tax_value': '3.67', 'discount': None, 'voucher_budget_use': None,
|
'voucher': None, 'tax_rate': '19.00', 'tax_code': 'S/standard', 'tax_value': '3.67', 'discount': None, 'voucher_budget_use': None,
|
||||||
'addon_to': None, 'subevent': None, 'checkins': [], 'print_logs': [], 'downloads': [], 'answers': [], 'tax_rule': item.tax_rule_id,
|
'addon_to': None, 'subevent': None, 'checkins': [], 'print_logs': [], 'downloads': [], 'answers': [], 'tax_rule': item.tax_rule_id,
|
||||||
'pseudonymization_id': 'PREVIEW', 'seat': None, 'canceled': False, 'valid_from': None, 'valid_until': None, 'blocked': None},
|
'pseudonymization_id': 'PREVIEW', 'seat': None, 'canceled': False, 'valid_from': None, 'valid_until': None, 'blocked': None,
|
||||||
|
'plugin_data': {}},
|
||||||
{'id': 0, 'order': '', 'positionid': 2, 'item': item.pk, 'variation': None, 'price': '23.00',
|
{'id': 0, 'order': '', 'positionid': 2, 'item': item.pk, 'variation': None, 'price': '23.00',
|
||||||
'attendee_name': 'Peter', 'attendee_name_parts': {'full_name': 'Peter', '_scheme': 'full'}, 'company': None,
|
'attendee_name': 'Peter', 'attendee_name_parts': {'full_name': 'Peter', '_scheme': 'full'}, 'company': None,
|
||||||
'street': None, 'zipcode': None, 'city': None, 'country': None, 'state': None, 'attendee_email': None,
|
'street': None, 'zipcode': None, 'city': None, 'country': None, 'state': None, 'attendee_email': None,
|
||||||
'voucher': None, 'tax_rate': '19.00', 'tax_code': 'S/standard', 'tax_value': '3.67', 'discount': None, 'voucher_budget_use': None,
|
'voucher': None, 'tax_rate': '19.00', 'tax_code': 'S/standard', 'tax_value': '3.67', 'discount': None, 'voucher_budget_use': None,
|
||||||
'addon_to': 1, 'subevent': None, 'checkins': [], 'print_logs': [], 'downloads': [], 'answers': [], 'tax_rule': item.tax_rule_id,
|
'addon_to': 1, 'subevent': None, 'checkins': [], 'print_logs': [], 'downloads': [], 'answers': [], 'tax_rule': item.tax_rule_id,
|
||||||
'pseudonymization_id': 'PREVIEW', 'seat': None, 'canceled': False, 'valid_from': None, 'valid_until': None, 'blocked': None}
|
'pseudonymization_id': 'PREVIEW', 'seat': None, 'canceled': False, 'valid_from': None, 'valid_until': None, 'blocked': None,
|
||||||
|
'plugin_data': {}}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -236,6 +236,7 @@ TEST_ORDERPOSITION_RES = {
|
|||||||
],
|
],
|
||||||
"subevent": None,
|
"subevent": None,
|
||||||
"canceled": False,
|
"canceled": False,
|
||||||
|
"plugin_data": {},
|
||||||
}
|
}
|
||||||
TEST_PAYMENTS_RES = [
|
TEST_PAYMENTS_RES = [
|
||||||
{
|
{
|
||||||
@@ -333,6 +334,7 @@ TEST_ORDER_RES = {
|
|||||||
"payments": TEST_PAYMENTS_RES,
|
"payments": TEST_PAYMENTS_RES,
|
||||||
"refunds": TEST_REFUNDS_RES,
|
"refunds": TEST_REFUNDS_RES,
|
||||||
"cancellation_date": None,
|
"cancellation_date": None,
|
||||||
|
"plugin_data": {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -203,7 +203,8 @@ def test_medium_detail(token_client, organizer, event, medium, giftcard, custome
|
|||||||
"canceled": False,
|
"canceled": False,
|
||||||
"valid_from": None,
|
"valid_from": None,
|
||||||
"valid_until": None,
|
"valid_until": None,
|
||||||
"blocked": None
|
"blocked": None,
|
||||||
|
"plugin_data": {},
|
||||||
}
|
}
|
||||||
assert resp.data["linked_giftcard"] == {
|
assert resp.data["linked_giftcard"] == {
|
||||||
"id": giftcard.pk,
|
"id": giftcard.pk,
|
||||||
|
|||||||
@@ -790,3 +790,33 @@ def test_ignore_by_external_id(env, job):
|
|||||||
}])
|
}])
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
assert BankTransaction.objects.count() == 2
|
assert BankTransaction.objects.count() == 2
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_ambigious_date_without_region(env, job):
|
||||||
|
process_banktransfers(job, [{
|
||||||
|
'payer': 'Karla Kundin',
|
||||||
|
'reference': 'Bestellung DUMMY1Z3AS',
|
||||||
|
'date': '03/05/2016',
|
||||||
|
'amount': '23.00'
|
||||||
|
}])
|
||||||
|
env[2].refresh_from_db()
|
||||||
|
|
||||||
|
with scopes_disabled():
|
||||||
|
assert env[2].payments.last().info_data["date"] == "2016-03-05"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_ambigious_date_with_region(env, job):
|
||||||
|
env[0].settings.region = "GB"
|
||||||
|
|
||||||
|
process_banktransfers(job, [{
|
||||||
|
'payer': 'Karla Kundin',
|
||||||
|
'reference': 'Bestellung DUMMY1Z3AS',
|
||||||
|
'date': '03/05/2016',
|
||||||
|
'amount': '23.00'
|
||||||
|
}])
|
||||||
|
env[2].refresh_from_db()
|
||||||
|
|
||||||
|
with scopes_disabled():
|
||||||
|
assert env[2].payments.last().info_data["date"] == "2016-05-03"
|
||||||
|
|||||||
@@ -40,3 +40,5 @@ def test_date_formats():
|
|||||||
|
|
||||||
assert dt == parse_date("2020-07-01")
|
assert dt == parse_date("2020-07-01")
|
||||||
assert dt == parse_date("2020-7-1")
|
assert dt == parse_date("2020-7-1")
|
||||||
|
|
||||||
|
assert dt == parse_date("01/07/2020", "GB")
|
||||||
|
|||||||
Reference in New Issue
Block a user