Compare commits

...

11 Commits

Author SHA1 Message Date
Richard Schreiber
e2afb2300c Update tests.yml 2026-05-12 13:07:26 +02:00
Richard Schreiber
1a2ea42084 try installing playwright as dep 2026-05-12 13:00:22 +02:00
Richard Schreiber
00514f73e8 Update tests.yml 2026-05-12 12:49:08 +02:00
Richard Schreiber
fc8d1a2430 Update tests.yml 2026-05-12 12:36:09 +02:00
Richard Schreiber
508e67d547 Fix playwright install on CI 2026-05-12 12:12:59 +02:00
luelista
80ed6e76cd Fix failing orderlist export if orders with invalid payment provider identifiers exist (Z#23233440) (#6159)
* Fix orderlist export if orders with invalid payment provider identifiers exist (Z#23233440)
* Performance: Move _get_all_payment_methods out of loop
2026-05-12 11:57:18 +02:00
Lukas Bockstaller
bb211be436 use datetime.fromisoformat instead of dateutil.parser (Z#23234093) (#6164)
* use datetime.fromisoformat instead of dateutil.parser

* convert remaining parser usages as well
2026-05-12 10:41:24 +02:00
Richard Schreiber
3b70ef8c84 Allow event being optional in LoggingMixin (#6166) 2026-05-12 09:45:42 +02:00
Richard Schreiber
9d57380c9a Widget: fix missing whitespace in PriceBox 2026-05-12 09:34:17 +02:00
Richard Schreiber
8b468c31a5 Fix translation for order import (#6165) 2026-05-12 09:03:34 +02:00
Richard Schreiber
9aec608601 Fix checkinrules js errors 2026-05-12 08:34:22 +02:00
9 changed files with 28 additions and 24 deletions

View File

@@ -123,7 +123,7 @@ jobs:
working-directory: ./src
run: make all compress
- name: Install Playwright browsers
run: npx playwright install
run: playwright install
- name: Run E2E tests
working-directory: ./src
run: PRETIX_CONFIG_FILE=tests/ci_postgres.cfg py.test tests/e2e/ -v --maxfail=10

View File

@@ -126,6 +126,7 @@ dev = [
"pytest-xdist==3.8.*",
"pytest-playwright",
"pytest==9.0.*",
"playwright",
"responses",
]

View File

@@ -160,7 +160,7 @@ class OrderListExporter(MultiSheetListExporter):
def _get_all_payment_methods(self, qs):
pps = dict(get_all_payment_providers())
return sorted([(pp, pps[pp]) for pp in set(
return sorted([(pp, pps.get(pp, pp)) for pp in set(
OrderPayment.objects.exclude(provider='free').filter(order__event__in=self.events).values_list(
'provider', flat=True
).distinct()
@@ -330,6 +330,7 @@ class OrderListExporter(MultiSheetListExporter):
taxsum=Sum('tax_value'), grosssum=Sum('value')
)
}
payment_methods = None
if form_data.get('include_payment_amounts'):
payment_sum_cache = {
(o['order__id'], o['provider']): o['grosssum'] for o in
@@ -347,6 +348,7 @@ class OrderListExporter(MultiSheetListExporter):
grosssum=Sum('amount')
)
}
payment_methods = self._get_all_payment_methods(qs)
sum_cache = {
(o['order__id'], o['tax_rate']): o for o in
OrderPosition.objects.values('tax_rate', 'order__id').order_by().annotate(
@@ -434,7 +436,6 @@ class OrderListExporter(MultiSheetListExporter):
)
if form_data.get('include_payment_amounts'):
payment_methods = self._get_all_payment_methods(qs)
for id, vn in payment_methods:
row.append(
payment_sum_cache.get((order.id, id), Decimal('0.00')) -

View File

@@ -442,7 +442,7 @@ class AttendeeState(ImportColumn):
@property
def verbose_name(self):
return _('Attendee address') + ': ' + _('State')
return _('Attendee address') + ': ' + pgettext('address', 'State')
def clean(self, value, previous_values):
if value:

View File

@@ -125,7 +125,7 @@ class LoggingMixin:
elif isinstance(self, Event):
event = self
organizer_id = self.organizer_id
elif hasattr(self, 'event'):
elif hasattr(self, 'event') and self.event:
event = self.event
organizer_id = self.event.organizer_id
elif hasattr(self, 'organizer_id'):

View File

@@ -34,11 +34,11 @@
# License for the specific language governing permissions and limitations under the License.
from collections import defaultdict
from datetime import datetime
from decimal import Decimal
from typing import Optional
import bleach
import dateutil.parser
from django.dispatch import receiver
from django.urls import reverse
from django.utils.formats import date_format
@@ -248,7 +248,7 @@ class OrderValidFromChanged(OrderChangeLogEntryType):
def display_prefixed(self, event: Event, logentry: LogEntry, data):
return _('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(
value=date_format(datetime.fromisoformat(data.get('new_value')), 'SHORT_DATETIME_FORMAT') if data.get(
'new_value') else ''
)
@@ -260,7 +260,7 @@ class OrderValidUntilChanged(OrderChangeLogEntryType):
def display_prefixed(self, event: Event, logentry: LogEntry, data):
return _('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 ''
value=date_format(datetime.fromisoformat(data.get('new_value')), 'SHORT_DATETIME_FORMAT') if data.get('new_value') else ''
)
@@ -364,7 +364,7 @@ class CheckinErrorLogEntryType(OrderLogEntryType):
data['posid'] = logentry.parsed_data.get('positionid', '?')
if 'datetime' in data:
dt = dateutil.parser.parse(data.get('datetime'))
dt = datetime.fromisoformat(data.get('datetime'))
if abs((logentry.datetime - dt).total_seconds()) > 5 or data.get('forced'):
if event:
data['datetime'] = date_format(dt.astimezone(event.timezone), "SHORT_DATETIME_FORMAT")
@@ -430,7 +430,7 @@ class OrderPrintLogEntryType(OrderLogEntryType):
return _('Position #{posid} has been printed at {datetime} with type "{type}".').format(
posid=data.get('positionid'),
datetime=date_format(
dateutil.parser.parse(data["datetime"]).astimezone(logentry.event.timezone),
datetime.fromisoformat(data["datetime"]).astimezone(logentry.event.timezone),
"SHORT_DATETIME_FORMAT"
) if logentry.event else data["datetime"],
type=dict(PrintLog.PRINT_TYPES)[data["type"]],
@@ -985,7 +985,7 @@ class LegacyCheckinLogEntryType(OrderLogEntryType):
def display(self, logentry, data):
# deprecated
dt = dateutil.parser.parse(data.get('datetime'))
dt = datetime.fromisoformat(data.get('datetime'))
tz = logentry.event.timezone
dt_formatted = date_format(dt.astimezone(tz), "SHORT_DATETIME_FORMAT")
if 'list' in data:

View File

@@ -89,7 +89,9 @@
</button>
</div>
</form>
{{ items|json_script:"items" }}
{% if items %}
{{ items|json_script:"items" }}
{% endif %}
{% compress js %}
<script type="text/javascript" src="{% static "d3/d3.v6.js" %}"></script>

View File

@@ -180,7 +180,7 @@ g
br
span(v-if="varresult !== null") {{ varresult }}
strong
| {{ op.label }} {{ rightoperand }}
| {{ op?.label}} {{ rightoperand }}
span(v-else-if="vardata && vardata.type === 'int_by_datetime'")
span.fa.fa-sign-in(v-if="variable.startsWith('entries_')")
| {{ vardata.label }}
@@ -193,21 +193,21 @@ g
br
span(v-if="varresult !== null") {{ varresult }}
strong
| {{ op.label }} {{ rightoperand }}
| {{ op?.label }} {{ rightoperand }}
span(v-else-if="vardata && variable === 'now'")
span.fa.fa-clock-o
| {{ vardata.label }}
br
span(v-if="varresult !== null") {{ varresult }}
strong
| {{ op.label }}
| {{ op?.label }}
br
span(v-if="rightoperand.buildTime[0] === 'custom'")
| {{ df(rightoperand.buildTime[1]) }}
span(v-else-if="rightoperand.buildTime[0] === 'customtime'")
| {{ tf(rightoperand.buildTime[1]) }}
span(v-if="rightoperand?.buildTime[0] === 'custom'")
| {{ df(rightoperand?.buildTime[1]) }}
span(v-else-if="rightoperand?.buildTime[0] === 'customtime'")
| {{ tf(rightoperand?.buildTime[1]) }}
span(v-else)
| {{ TEXTS[rightoperand.buildTime[0]] }}
| {{ TEXTS[rightoperand?.buildTime[0]] }}
span(v-if="operands[2]")
span(v-if="operator === 'isBefore'") +
span(v-else) -
@@ -220,14 +220,14 @@ g
span(v-if="varresult !== null") ({{ varresult }})
br
strong
| {{ rightoperand.objectList.map((o: any) => o.lookup[2]).join(", ") }}
| {{ rightoperand?.objectList.map((o: any) => o.lookup[2]).join(", ") }}
span(v-else-if="vardata && vardata.type === 'enum_entry_status'")
span.fa.fa-check-circle-o
| {{ vardata.label }}
span(v-if="varresult !== null") ({{ varresult }})
br
strong
| {{ op.label }} {{ rightoperand }}
| {{ op?.label }} {{ rightoperand }}
g(v-if="result === false", :transform="`translate(${x + boxWidth - 15}, ${y - 10})`")
ellipse(fill="#fff", cx="14.685823", cy="14.318233", rx="12.140151", ry="11.55523")

View File

@@ -93,11 +93,11 @@ const showTaxline = computed(() => props.price.rate !== '0.00' && props.price.gr
span(v-if="!freePrice && !originalPrice", v-html="priceline")
span(v-if="!freePrice && originalPrice")
del.pretix-widget-pricebox-original-price(:aria-label="originalPriceAriaLabel", v-html="originalLine")
|
|!{' '}
ins.pretix-widget-pricebox-new-price(:aria-label="newPriceAriaLabel", v-html="priceline")
div(v-if="freePrice")
span.pretix-widget-pricebox-currency(:id="priceBoxId") {{ store.currency }}
|
|!{' '}
input.pretix-widget-pricebox-price-input(
type="number",
placeholder="0",