Compare commits

..

2 Commits

Author SHA1 Message Date
Mira Weller
1011ef7cc9 Add logging for successfully synced orders
(debugging orders that might get silently skipped)
2026-02-24 15:40:22 +01:00
Mira Weller
8829050eb9 Fix inconsistent log messages 2026-02-24 15:39:22 +01:00
17 changed files with 33 additions and 98 deletions

View File

@@ -365,10 +365,9 @@ class TeamInviteSerializer(serializers.ModelSerializer):
def _send_invite(self, instance): def _send_invite(self, instance):
mail( mail(
instance.email, instance.email,
_('Account invitation'), _('pretix account invitation'),
'pretixcontrol/email/invitation.txt', 'pretixcontrol/email/invitation.txt',
{ {
'instance': settings.PRETIX_INSTANCE_NAME,
'user': self, 'user': self,
'organizer': self.context['organizer'].name, 'organizer': self.context['organizer'].name,
'team': instance.team.name, 'team': instance.team.name,

View File

@@ -346,8 +346,7 @@ class User(AbstractBaseUser, PermissionsMixin, LoggingMixin):
{ {
'user': self, 'user': self,
'messages': msg, 'messages': msg,
'url': build_absolute_uri('control:user.settings'), 'url': build_absolute_uri('control:user.settings')
'instance': settings.PRETIX_INSTANCE_NAME,
}, },
event=None, event=None,
user=self, user=self,
@@ -392,7 +391,6 @@ class User(AbstractBaseUser, PermissionsMixin, LoggingMixin):
'user': self, 'user': self,
'reason': msg, 'reason': msg,
'code': code, 'code': code,
'instance': settings.PRETIX_INSTANCE_NAME,
}, },
event=None, event=None,
user=self, user=self,
@@ -432,7 +430,6 @@ class User(AbstractBaseUser, PermissionsMixin, LoggingMixin):
mail( mail(
self.email, _('Password recovery'), 'pretixcontrol/email/forgot.txt', self.email, _('Password recovery'), 'pretixcontrol/email/forgot.txt',
{ {
'instance': settings.PRETIX_INSTANCE_NAME,
'user': self, 'user': self,
'url': (build_absolute_uri('control:auth.forgot.recover') 'url': (build_absolute_uri('control:auth.forgot.recover')
+ '?id=%d&token=%s' % (self.id, default_token_generator.make_token(self))) + '?id=%d&token=%s' % (self.id, default_token_generator.make_token(self)))

View File

@@ -176,7 +176,6 @@ def shred(self, event: Event, fileid: str, confirm_code: str, user: int=None, lo
_('Data shredding completed'), _('Data shredding completed'),
'pretixbase/email/shred_completed.txt', 'pretixbase/email/shred_completed.txt',
{ {
'instance': settings.PRETIX_INSTANCE_NAME,
'user': user, 'user': user,
'organizer': event.organizer.name, 'organizer': event.organizer.name,
'event': str(event.name), 'event': str(event.name),

View File

@@ -13,5 +13,5 @@ Start time: {{ start_time }} (new data added after this time might not have been
Best regards, Best regards,
Your {{ instance }} team Your pretix team
{% endblocktrans %} {% endblocktrans %}

View File

@@ -1,34 +0,0 @@
#
# This file is part of pretix (Community Edition).
#
# Copyright (C) 2014-2020 Raphael Michel and contributors
# Copyright (C) 2020-today pretix GmbH and contributors
#
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
# Public License as published by the Free Software Foundation in version 3 of the License.
#
# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are
# applicable granting you additional permissions and placing additional restrictions on your usage of this software.
# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive
# this file, see <https://pretix.eu/about/en/license>.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# 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/>.
#
from django import template
from django.utils.html import mark_safe
register = template.Library()
@register.filter("anon_email")
def anon_email(value):
"""Replaces @ with [at] and . with [dot] for anonymization."""
if not isinstance(value, str):
return value
value = value.replace("@", "[at]").replace(".", "[dot]")
return mark_safe(''.join(['&#{0};'.format(ord(char)) for char in value]))

View File

@@ -518,7 +518,6 @@ def pretixcontrol_orderposition_blocked_display(sender: Event, orderposition, bl
'The order requires approval before it can continue to be processed.'), 'The order requires approval before it can continue to be processed.'),
'pretix.event.order.approved': _('The order has been approved.'), 'pretix.event.order.approved': _('The order has been approved.'),
'pretix.event.order.denied': _('The order has been denied (comment: "{comment}").'), 'pretix.event.order.denied': _('The order has been denied (comment: "{comment}").'),
'pretix.event.order.vatid.validated': _('The customer VAT ID has been verified.'),
'pretix.event.order.contact.changed': _('The email address has been changed from "{old_email}" ' 'pretix.event.order.contact.changed': _('The email address has been changed from "{old_email}" '
'to "{new_email}".'), 'to "{new_email}".'),
'pretix.event.order.contact.confirmed': _( 'pretix.event.order.contact.confirmed': _(

View File

@@ -9,5 +9,5 @@ Please do never give this code to another person. Our support team will never as
If this code was not requested by you, please contact us immediately. If this code was not requested by you, please contact us immediately.
Best regards, Best regards,
Your {{ instance }} team Your pretix team
{% endblocktrans %} {% endblocktrans %}

View File

@@ -5,5 +5,5 @@ you requested a new password. Please go to the following page to reset your pass
{{ url }} {{ url }}
Best regards, Best regards,
Your {{ instance }} team Your pretix team
{% endblocktrans %} {% endblocktrans %}

View File

@@ -1,6 +1,6 @@
{% load i18n %}{% blocktrans with url=url|safe %}Hello, {% load i18n %}{% blocktrans with url=url|safe %}Hello,
you have been invited to a team on {{ instance }}, a platform to perform event you have been invited to a team on pretix, a platform to perform event
ticket sales. ticket sales.
Organizer: {{ organizer }} Organizer: {{ organizer }}
@@ -13,5 +13,5 @@ If you do not want to join, you can safely ignore or delete this email.
Best regards, Best regards,
Your {{ instance }} team Your pretix team
{% endblocktrans %} {% endblocktrans %}

View File

@@ -1,6 +1,6 @@
{% load i18n %}{% blocktrans with url=url|safe messages=messages|safe %}Hello, {% load i18n %}{% blocktrans with url=url|safe messages=messages|safe %}Hello,
this is to inform you that the account information of your {{ instance }} account has been this is to inform you that the account information of your pretix account has been
changed. In particular, the following changes have been performed: changed. In particular, the following changes have been performed:
{{ messages }} {{ messages }}
@@ -12,5 +12,5 @@ You can review and change your account settings here:
{{ url }} {{ url }}
Best regards, Best regards,
Your {{ instance }} team Your pretix team
{% endblocktrans %} {% endblocktrans %}

View File

@@ -1641,17 +1641,9 @@ class OrderCheckVATID(OrderView):
try: try:
normalized_id = validate_vat_id(ia.vat_id, str(ia.country)) normalized_id = validate_vat_id(ia.vat_id, str(ia.country))
with transaction.atomic(): ia.vat_id_validated = True
ia.vat_id_validated = True ia.vat_id = normalized_id
ia.vat_id = normalized_id ia.save()
ia.save()
self.order.log_action(
'pretix.event.order.vatid.validated',
data={
'vat_id': normalized_id,
},
user=self.request.user,
)
except VATIDFinalError as e: except VATIDFinalError as e:
messages.error(self.request, e.message) messages.error(self.request, e.message)
except VATIDTemporaryError: except VATIDTemporaryError:

View File

@@ -1039,10 +1039,9 @@ class TeamMemberView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin,
def _send_invite(self, instance): def _send_invite(self, instance):
mail( mail(
instance.email, instance.email,
_('Account invitation'), _('pretix account invitation'),
'pretixcontrol/email/invitation.txt', 'pretixcontrol/email/invitation.txt',
{ {
'instance': settings.PRETIX_INSTANCE_NAME,
'user': self, 'user': self,
'organizer': self.request.organizer.name, 'organizer': self.request.organizer.name,
'team': instance.team.name, 'team': instance.team.name,

View File

@@ -802,37 +802,31 @@ class PaypalMethod(BasePaymentProvider):
all_captures_completed = False all_captures_completed = False
else: else:
any_captures = True any_captures = True
if not (any_captures and all_captures_completed):
# Payment has at least one capture, but it is not yet completed
if any_captures and not all_captures_completed:
messages.warning(request, _('PayPal has not yet approved the payment. We will inform you as ' messages.warning(request, _('PayPal has not yet approved the payment. We will inform you as '
'soon as the payment completed.')) 'soon as the payment completed.'))
payment.info = json.dumps(pp_captured_order.dict()) payment.info = json.dumps(pp_captured_order.dict())
payment.state = OrderPayment.PAYMENT_STATE_PENDING payment.state = OrderPayment.PAYMENT_STATE_PENDING
payment.save() payment.save()
return return
# Payment has at least one capture and all captures are completed
elif any_captures and all_captures_completed:
if pp_captured_order.status != 'COMPLETED':
payment.fail(info=pp_captured_order.dict())
logger.error('Invalid state: %s' % repr(pp_captured_order.dict()))
raise PaymentException(
_('We were unable to process your payment. See below for details on how to proceed.')
)
if payment.state == OrderPayment.PAYMENT_STATE_CONFIRMED: if pp_captured_order.status != 'COMPLETED':
logger.warning('PayPal success event even though order is already marked as paid') payment.fail(info=pp_captured_order.dict())
return logger.error('Invalid state: %s' % repr(pp_captured_order.dict()))
raise PaymentException(
_('We were unable to process your payment. See below for details on how to proceed.')
)
try: if payment.state == OrderPayment.PAYMENT_STATE_CONFIRMED:
payment.info = json.dumps(pp_captured_order.dict()) logger.warning('PayPal success event even though order is already marked as paid')
payment.save(update_fields=['info'])
payment.confirm()
except Quota.QuotaExceededException as e:
raise PaymentException(str(e))
# Payment has not any captures yet - so it's probably in created status
else:
return return
try:
payment.info = json.dumps(pp_captured_order.dict())
payment.save(update_fields=['info'])
payment.confirm()
except Quota.QuotaExceededException as e:
raise PaymentException(str(e))
finally: finally:
if 'payment_paypal_oid' in request.session: if 'payment_paypal_oid' in request.session:
del request.session['payment_paypal_oid'] del request.session['payment_paypal_oid']
@@ -842,7 +836,7 @@ class PaypalMethod(BasePaymentProvider):
try: try:
if ( if (
payment.info payment.info
and payment.info_data['purchase_units'][0]['payments']['captures'][0]['status'] == 'PENDING' and payment.info_data['purchase_units'][0]['payments']['captures'][0]['status'] == 'pending'
): ):
retry = False retry = False
except (KeyError, IndexError): except (KeyError, IndexError):

View File

@@ -6,7 +6,6 @@
{% load eventurl %} {% load eventurl %}
{% load safelink %} {% load safelink %}
{% load rich_text %} {% load rich_text %}
{% load anonymize_email %}
{% block thetitle %} {% block thetitle %}
{% if messages %} {% if messages %}
{{ messages|join:" " }} :: {{ messages|join:" " }} ::
@@ -220,7 +219,7 @@
{% endblock %} {% endblock %}
{% block footernav %} {% block footernav %}
{% if request.event.settings.contact_mail %} {% if request.event.settings.contact_mail %}
<li><a href="{{ 'mailto:'|add:request.event.settings.contact_mail|anon_email }}" target="_blank" rel="noopener">{% trans "Contact" %}</a></li> <li><a href="mailto:{{ request.event.settings.contact_mail }}" target="_blank" rel="noopener">{% trans "Contact" %}</a></li>
{% endif %} {% endif %}
{% if request.event.settings.privacy_url %} {% if request.event.settings.privacy_url %}
<li><a href="{% safelink request.event.settings.privacy_url %}" target="_blank" rel="noopener">{% trans "Privacy policy" %}</a></li> <li><a href="{% safelink request.event.settings.privacy_url %}" target="_blank" rel="noopener">{% trans "Privacy policy" %}</a></li>

View File

@@ -21,5 +21,4 @@
<script type="text/javascript" src="{% static "pretixpresale/js/ui/cart.js" %}"></script> <script type="text/javascript" src="{% static "pretixpresale/js/ui/cart.js" %}"></script>
<script type="text/javascript" src="{% static "pretixpresale/js/ui/iframe.js" %}"></script> <script type="text/javascript" src="{% static "pretixpresale/js/ui/iframe.js" %}"></script>
<script type="text/javascript" src="{% static "pretixbase/js/addressform.js" %}"></script> <script type="text/javascript" src="{% static "pretixbase/js/addressform.js" %}"></script>
<script type="text/javascript" src="{% static "pretixbase/js/deanonymize_email.js" %}"></script>
{% endcompress %} {% endcompress %}

View File

@@ -5,7 +5,6 @@
{% load thumb %} {% load thumb %}
{% load eventurl %} {% load eventurl %}
{% load safelink %} {% load safelink %}
{% load anonymize_email %}
{% block thetitle %} {% block thetitle %}
{% block title %}{% endblock %}{% if url_name != "organizer.index" %} :: {% endif %}{{ organizer.name }} {% block title %}{% endblock %}{% if url_name != "organizer.index" %} :: {% endif %}{{ organizer.name }}
{% endblock %} {% endblock %}
@@ -98,7 +97,7 @@
{% endblock %} {% endblock %}
{% block footernav %} {% block footernav %}
{% if not request.event and request.organizer.settings.contact_mail %} {% if not request.event and request.organizer.settings.contact_mail %}
<li><a href="{{ 'mailto:'|add:request.organizer.settings.contact_mail|anon_email }}" target="_blank" rel="noopener">{% trans "Contact" %}</a></li> <li><a href="mailto:{{ request.organizer.settings.contact_mail }}" target="_blank" rel="noopener">{% trans "Contact" %}</a></li>
{% endif %} {% endif %}
{% if not request.event and request.organizer.settings.privacy_url %} {% if not request.event and request.organizer.settings.privacy_url %}
<li><a href="{% safelink request.organizer.settings.privacy_url %}" target="_blank" rel="noopener">{% trans "Privacy policy" %}</a></li> <li><a href="{% safelink request.organizer.settings.privacy_url %}" target="_blank" rel="noopener">{% trans "Privacy policy" %}</a></li>

View File

@@ -1,7 +0,0 @@
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('a[href^="mailto:"]').forEach(function(link) {
// Replace [at] with @ and the [dot] with . in both the href and the displayed text (if needed)
link.href = link.href.replace('[at]', '@').replace('[dot]', '.');
link.textContent = link.textContent.replace('[at]', '@').replace('[dot]', '.');
});
});