Compare commits

..

4 Commits

Author SHA1 Message Date
Raphael Michel
2abd2d0717 One last thing… 2025-10-07 10:57:26 +02:00
Raphael Michel
d5a433e976 Add cancellation to try block 2025-10-07 10:39:31 +02:00
Raphael Michel
4ca36886f3 Add logging 2025-10-07 10:27:56 +02:00
Raphael Michel
9b4403a49a Do not crash if generate_invoice fails 2025-09-23 16:45:46 +02:00
8 changed files with 449 additions and 574 deletions

View File

@@ -764,7 +764,13 @@ class EventOrderViewSet(OrderViewSetMixin, viewsets.ModelViewSet):
) and not order.invoices.last()
invoice = None
if gen_invoice:
invoice = generate_invoice(order, trigger_pdf=True)
try:
invoice = generate_invoice(order, trigger_pdf=True)
except Exception as e:
logger.exception("Could not generate invoice.")
order.log_action("pretix.event.order.invoice.failed", data={
"exception": str(e)
})
# Refresh serializer only after running signals
prefetch_related_objects([order], self._positions_prefetch(request))

View File

@@ -1961,14 +1961,20 @@ class OrderPayment(models.Model):
self.order.invoice_dirty
)
if gen_invoice:
if invoices:
last_i = self.order.invoices.filter(is_cancellation=False).last()
if not last_i.canceled:
generate_cancellation(last_i)
invoice = generate_invoice(
self.order,
trigger_pdf=not send_mail or not self.order.event.settings.invoice_email_attachment
)
try:
if invoices:
last_i = self.order.invoices.filter(is_cancellation=False).last()
if not last_i.canceled:
generate_cancellation(last_i)
invoice = generate_invoice(
self.order,
trigger_pdf=not send_mail or not self.order.event.settings.invoice_email_attachment
)
except Exception as e:
logger.exception("Could not generate invoice.")
self.order.log_action("pretix.event.order.invoice.failed", data={
"exception": str(e)
})
transmit_invoice_task = invoice_transmission_separately(invoice)
transmit_invoice_mail = not transmit_invoice_task and self.order.event.settings.invoice_email_attachment and self.order.email

View File

@@ -19,6 +19,7 @@
# 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/>.
#
import logging
from decimal import Decimal
from typing import List
@@ -43,6 +44,8 @@ from pretix.base.services.tasks import ProfiledEventTask
from pretix.base.signals import order_paid, order_placed
from pretix.celery_app import app
logger = logging.getLogger(__name__)
def _validate(cf: CachedFile, charset: str, cols: List[ImportColumn], settings: dict):
try:
@@ -230,7 +233,13 @@ def import_orders(event: Event, fileid: str, settings: dict, locale: str, user,
(event.settings.get('invoice_generate') == 'paid' and o.status == Order.STATUS_PAID)
) and not o.invoices.last()
if gen_invoice:
generate_invoice(o, trigger_pdf=True)
try:
generate_invoice(o, trigger_pdf=True)
except Exception as e:
logger.exception("Could not generate invoice.")
o.log_action("pretix.event.order.invoice.failed", data={
"exception": str(e)
})
except DataImportError:
raise ValidationError(_('We were not able to process your request completely as the server was too busy. '
'Please try again.'))

View File

@@ -264,7 +264,13 @@ def reactivate_order(order: Order, force: bool=False, user: User=None, auth=None
num_invoices = order.invoices.filter(is_cancellation=False).count()
if num_invoices > 0 and order.invoices.filter(is_cancellation=True).count() >= num_invoices and invoice_qualified(order):
generate_invoice(order)
try:
generate_invoice(order)
except Exception as e:
logger.exception("Could not generate invoice.")
order.log_action("pretix.event.order.invoice.failed", data={
"exception": str(e)
})
def extend_order(order: Order, new_date: datetime, force: bool=False, valid_if_pending: bool=None, user: User=None, auth=None):
@@ -312,7 +318,13 @@ def extend_order(order: Order, new_date: datetime, force: bool=False, valid_if_p
if was_expired:
num_invoices = order.invoices.filter(is_cancellation=False).count()
if num_invoices > 0 and order.invoices.filter(is_cancellation=True).count() >= num_invoices and invoice_qualified(order):
generate_invoice(order)
try:
generate_invoice(order)
except Exception as e:
logger.exception("Could not generate invoice.")
order.log_action("pretix.event.order.invoice.failed", data={
"exception": str(e)
})
order.create_transactions()
with transaction.atomic():
@@ -397,13 +409,19 @@ def approve_order(order, user=None, send_mail: bool=True, auth=None, force=False
if order.event.settings.get('invoice_generate') == 'True' and invoice_qualified(order):
if not invoice:
invoice = generate_invoice(
order,
# send_mail will trigger PDF generation later
trigger_pdf=not transmit_invoice_mail
)
if transmit_invoice_task:
transmit_invoice.apply_async(args=(order.event_id, invoice.pk, False))
try:
invoice = generate_invoice(
order,
# send_mail will trigger PDF generation later
trigger_pdf=not transmit_invoice_mail
)
if transmit_invoice_task:
transmit_invoice.apply_async(args=(order.event_id, invoice.pk, False))
except Exception as e:
logger.exception("Could not generate invoice.")
order.log_action("pretix.event.order.invoice.failed", data={
"exception": str(e)
})
if send_mail:
with language(order.locale, order.event.settings.region):
@@ -608,7 +626,13 @@ def _cancel_order(order, user=None, send_mail: bool=True, api_token=None, device
order.save(update_fields=['status', 'cancellation_date', 'total'])
if cancel_invoice and i:
invoices.append(generate_invoice(order))
try:
invoices.append(generate_invoice(order))
except Exception as e:
logger.exception("Could not generate invoice.")
order.log_action("pretix.event.order.invoice.failed", data={
"exception": str(e)
})
else:
order.status = Order.STATUS_CANCELED
order.cancellation_date = now()
@@ -1306,13 +1330,19 @@ def _perform_order(event: Event, payment_requests: List[dict], position_ids: Lis
)
)
if invoice_required:
invoice = generate_invoice(
order,
# send_mail will trigger PDF generation later
trigger_pdf=not transmit_invoice_mail
)
if transmit_invoice_task:
transmit_invoice.apply_async(args=(event.pk, invoice.pk, False))
try:
invoice = generate_invoice(
order,
# send_mail will trigger PDF generation later
trigger_pdf=not transmit_invoice_mail
)
if transmit_invoice_task:
transmit_invoice.apply_async(args=(event.pk, invoice.pk, False))
except Exception as e:
logger.exception("Could not generate invoice.")
order.log_action("pretix.event.order.invoice.failed", data={
"exception": str(e)
})
if order.email:
if order.require_approval:
@@ -2701,7 +2731,13 @@ class OrderChangeManager:
)
if split_order.total != Decimal('0.00') and self.order.invoices.filter(is_cancellation=False).last():
generate_invoice(split_order)
try:
generate_invoice(split_order)
except Exception as e:
logger.exception("Could not generate invoice.")
split_order.log_action("pretix.event.order.invoice.failed", data={
"exception": str(e)
})
order_split.send(sender=self.order.event, original=self.order, split_order=split_order)
return split_order
@@ -2812,15 +2848,27 @@ class OrderChangeManager:
if order_now_qualified:
if invoice_should_be_generated_now:
if i and not i.canceled:
self._invoices.append(generate_cancellation(i))
self._invoices.append(generate_invoice(self.order))
try:
if i and not i.canceled:
self._invoices.append(generate_cancellation(i))
self._invoices.append(generate_invoice(self.order))
except Exception as e:
logger.exception("Could not generate invoice.")
self.order.log_action("pretix.event.order.invoice.failed", data={
"exception": str(e)
})
elif invoice_should_be_generated_later:
self.order.invoice_dirty = True
self.order.save(update_fields=["invoice_dirty"])
else:
if i and not i.canceled:
self._invoices.append(generate_cancellation(i))
try:
if i and not i.canceled:
self._invoices.append(generate_cancellation(i))
except Exception as e:
logger.exception("Could not generate invoice.")
self.order.log_action("pretix.event.order.invoice.failed", data={
"exception": str(e)
})
def _check_complete_cancel(self):
current = self.order.positions.count()
@@ -3246,8 +3294,14 @@ def change_payment_provider(order: Order, payment_provider, amount=None, new_pay
has_active_invoice = i and not i.canceled
if has_active_invoice and order.total != oldtotal:
generate_cancellation(i)
generate_invoice(order)
try:
generate_cancellation(i)
generate_invoice(order)
except Exception as e:
logger.exception("Could not generate invoice.")
order.log_action("pretix.event.order.invoice.failed", data={
"exception": str(e)
})
new_invoice_created = True
elif (not has_active_invoice or order.invoice_dirty) and invoice_qualified(order):
@@ -3255,13 +3309,19 @@ def change_payment_provider(order: Order, payment_provider, amount=None, new_pay
order.event.settings.get('invoice_generate') == 'paid' and
new_payment.payment_provider.requires_invoice_immediately
):
if has_active_invoice:
generate_cancellation(i)
i = generate_invoice(order)
new_invoice_created = True
order.log_action('pretix.event.order.invoice.generated', data={
'invoice': i.pk
})
try:
if has_active_invoice:
generate_cancellation(i)
i = generate_invoice(order)
new_invoice_created = True
order.log_action('pretix.event.order.invoice.generated', data={
'invoice': i.pk
})
except Exception as e:
logger.exception("Could not generate invoice.")
order.log_action("pretix.event.order.invoice.failed", data={
"exception": str(e)
})
order.create_transactions()
return old_fee, new_fee, fee, new_payment, new_invoice_created

View File

@@ -522,6 +522,7 @@ def pretixcontrol_orderposition_blocked_display(sender: Event, orderposition, bl
'pretix.event.order.customer.changed': _('The customer account has been changed.'),
'pretix.event.order.locale.changed': _('The order locale has been changed.'),
'pretix.event.order.invoice.generated': _('The invoice has been generated.'),
'pretix.event.order.invoice.failed': _('The invoice could not be generated.'),
'pretix.event.order.invoice.regenerated': _('The invoice has been regenerated.'),
'pretix.event.order.invoice.reissued': _('The invoice has been reissued.'),
'pretix.event.order.invoice.sent': _('The invoice {full_invoice_no} has been sent.'),

View File

@@ -1,143 +1,125 @@
ABGEKÜNDIGT
2FA
ABN
AES
Absenderadresse
Absenderinformation
Absendername
ABGEKÜNDIGT
Admin
Adminbereich
Admin-Modus
Admin-Sitzung
Admin-Sitzungen
AES
Affirm
AGPL
AGPLv
Alipay
and
API-Meta-Informationen
APM
App
App-Gebühr
ApplePay
Apps
APM
as
Aufbuchungen
aufeinanderfolgenden
Aufteilungsliste
aufzubuchen
auschecken
Ausgangsscan
Ausgangsscans
ausgecheckt
ausgeklappt
ausgecheckt
auswahl
Auth
Authentication
Authenticator-App
Authenticator
Authentifizierungsmechanismus
Autorisierungs
Autorisierungscode
Autorisierungs-Endpunktes
Backend
Badge
Badge-Druck
Badge-Layout
Badge-Layouts
Badges
Bancontact
Bank-App
BankID
Banking-App
Banking
barcodes
Baskisch
Bcc
BCC-Adresse
Bcc-Kopie
BCC
Beispielevent
Beispielproduktvariantenbeschreibung
Belarus
Benachrichtigungs
Benachrichtigungsart
Benachrichtigungsarten
Benachrichtigungseinstellungen
Benachrichtigungs-Einstellungen
Benachrichtigungs-E-Mail
Benutzer-ID-Feld
Benutzer-ID-Felds
Bestätigungs-E-Mail
Bestellbestätigungs-E-Mail
Bestellbestätigungs-E-Mails
Berechtigungs
Bestätigungs
Bestellbestätigungs
Bestellungsänderungen
Bestellungs-Synchronisation
Bestellungs-Synchronisierung
Bestellungsstatus
Bestellungs
bez
BezahlCode
Bezahlmethode
Blackberry
BLIK
BN-Code
Blogpost
BN
Branding
Browsereinstellungen
BSD
bspw
Bokmål
Boleto
Branding-Informationen
Browsereinstellungen
BSD-Lizenz
bspw
Buchhaltungs
Bundles
Butterfly-Badge
Butterfly
bzw
ca
Cc
Ceuta
Cc
chardet
charge
Charge-ID
Checkbox
Check-in-App
Check-in-Apps
Check-in-QR-Code
Checkout
Chrome
Client-ID
Client-Secret
CODE.txt
Community-Übersetzungen
Choice
Community
CONFIRM
Connect
Cookie-Consent-Management
Cookie-Consent-Mechanismus
Consent
Copyleft
Cronjob
Cronjob-Komponente
Cross-Selling-Bedingung
Cross-Selling-Kategorie
Cross-Selling-Kategorien
Cross-Selling-Schritt
Cross
csv
CSV
CSV-Datei
CSV-Dateien
CSV-Eingabe
CSV-Eingabedaten
CSV-Import
CSV-Input
CSV-Lesen
CSV-Spalte
Customer
CZK
Debug-Modus
Dashboard
Datensynchronisation
Debug
dekodi
Desktop-Apps
deliverability
DNS
Di
Do
Doe
Downloadformat
Downloadseite
Dr
Drag-and-Drop-Interfaces
Drag
Droid
Drop
DSS
Edge
Eingangsscan
Einlassbuchung
Einlassdatum
Einlasskontrolle
Einlassuhrzeita
einzuchecken
email
E-Mail-Renderer
Enterprise-Lizenz
Enterprise-Lizenzen
Enterprise-Plugin
Enterprise-Plugins
eps
Enterprise
EPC
EPS
eps
Erstattungsbetrag
Erstattungsliste
Erstattungsmethode
@@ -145,230 +127,175 @@ Erstattungsoptionen
Erstattungsstatus
Erstattungsweg
erstmalig
Erweiterungs
etc
EU-USt-ID-Nr
Event
Event-Eigenschaft
Eventeingang
Event-Erstellung
Event-Setup-Tool
Event-Ticketing-Software
Event-Ticketshop
Event-Übersicht
Event-Website
Eventfirma
evtl
Explorer
FA
Favicon
F-Droid
Footer
Footer-Link
Footer-Text
Galicisch
Geocoding
Geocoding-Daten
Geo-Koordinaten
Geräte-ID
gehostete
geht's
GENEXAMPLE
Geo
geocoding
gescannt
ggf
Ggf
GiroCode
giropay
GPL
Grants
Gruppierungsspalte
Gruppierungswert
Gruppierungsspalte
Guide
Gutscheineinlöser
Händler-ID
Händler-PayPal-Konto
Hardware-Tokengenerator
herunterscrollen
hochlädst
HTML-E-Mail-Renderer
HTTPS
HTTPS-Verbindungen
HTTPS-Website
IBAN
IBANs
iCal
ics-Kalenderdatei
ics
ID
iDEAL
IDs
Inc
inkl
innen-Badges
innenname
innennamen
innergemeinschaftliche
Innergemeinschaftlicher
Installations-ID
Integrationen
Input
Installations
integrationen
intra
INV
invalidieren
invalidiert
iOS
ISU
iOS
Itaú
iTunes
JavaScript
JSON-Datei
JSON
Kategoriebeschreibung
Key
Klarna
Kombitickets
Kompatibilitätsmodus
Konfigurations
Kosovo
land
landesspezifische
Lead-Scanning
Leaflet-Kacheln
Lead
Leaflet
Linktext
lit
Log-ID
Logindaten
Lösch
loszulegen
Ltd
Macau
MapQuest-API-Key
max
Medien-ID
MariaDB
MapQuest
Melilla
Mercado
Merchandise
Meta
Metadaten
Meta-Eigenschaft
Meta-Eigenschaften
Meta-Informationen
Mi
Mifare
min
Mitgliedschafts
Mitgliedschaftsdauer
Mitgliedschafts-Typ
Mitgliedschafts-Typen
min
Mo
MobilePay
MOTO
MOTO-Zahlungen
Multibanco
Multiple-Choice-Fragen
MwSt
MyBank
name
NFC
NFC-basierte
NFC-Chip
NFC-Chips
NFC-Medien
NFC-Zahlungsmitteln
Nr
NREI
number
NXP
Objekt-IDs
Offline-Scan
OK
Online-Banking
Onlinebanking-Zugangsdaten
On
Onlinebanking
Open
OpenCage-API-Key
OpenCage
OpenID
OpenStreetMap
Opera
Output
OXXO
Pago
parsen
Pago
Pay
PayPal
PayPal-Account
PayPal-Accounts
PayPal-Konto
PayPal-Kontos
PayPal-Sandbox
PayPal-Sandbox-Account
PayPal-Seite
PayPal-Verkaufs-ID
PayPal-Webhook
PayPal-Zahlung
PayPal-Zahlungen
PayPal-Zahlungs-ID
PayPals
PayU
PCI-DSS-Formulare
Peppol-Teilnehmer-ID
Peppol-Teilnehmer-IDs
PCI
Personalisierung
PKCE-Erweiterung
Peppol
PKCE
Platzhalterzeichen
Play
Plugin
Plugins
POS
Postfix
PostgreSQL
PPRO
prefix
Prefix
pretix
pretix-Apps
pretix-Benutzerkennung
pretixdesk-Apps
pretixdesk
pretixdroid
pretix-Enterprise-Lizenz
pretix-Enterprise-Plugins
pretix-Entwickler
pretix-Entwicklern
pretix-Feld
pretix-Installation
pretix-Konto
pretix-Kontos
pretix-Logo
pretix-Logos
pretix-Plugins
pretixPOS
pretixPRINT
pretixPRINT-Version
pretixSCAN
pretix-Support
pretix-Team
pretix-Update
pretix-Version
pretix-Versionen
pretix-Widget
Produkt-ID
Produkt-Metadaten
Professional
Przelewy
pt
px
QR-Code
QR-Code-Bereich
QR-Code-Geheimnis
QR-Code-Inhalt
QR-Code-Reader
QR-Codes
QR-Farbe
Query-Parameter
Query
QR
rabattiert
Rabattiert
Rabattierung
Rechnungs-E-Mail
Reader
Rechnungs
Rechungsdatei
Reddit
Referer
Registrierungs
Registrierungsdatum
Registrierungs-Details
Registrierungsnummer
Registrierungsversuche
remote
Renderer
Request
Requests
Request-URL
Reservierungszeitraum
reverse
Reverse
Reverse-Proxy
Revisionssicherheit
Revolut
Revolut-App
rückabgewickelt
Rundungsdifferenzen
Sa
Saalplan
Sammlungsstücken
SAQ
SCA
Scan
Scanning-Apps
Scans
Scan-Terminals
Scan-Typ
Scan-Zeitpunkt
Scanergebnis
Scanning
schiefgeht
schiefgelaufen
Scope
@@ -377,37 +304,23 @@ SdI
sechsstelligen
Secret
Security
selbst-gehostete
SEPA-Bankeinzug
SEPA-Bankkonto
SEPA-Konten
SEPA-Lastschrift
SEPA-Lastschriften
SEPA-Mandat
SEPA-XML
Session-ID
Selling
SEPA
Shirts
Signaturverfahren
Single-Sign-On
Single-Sign-On-Dienste
Single-Sign-On-Methode
Single-Sign-On-Provider
Sign
Sitzplanmoduls
Sitzplatz-ID
Sitzplatz-IDs
Social-Media-Bild
Social
Sofort
SOFORT
Sorry
Source
Source-Codes
SPF-Eintrag
SPF
SSL
SSO
SSO-Client
SSO-Clients
SSO-Provider
STARTTLS
Steuer-Aufteilungsliste
Steuerregel-ID
Steuerschuldnerschaft
Store
Stornierungsanfrage
Stornobedingungen
Stornobeleg
@@ -417,75 +330,58 @@ Stornogebühren
Stornos
Strg
Stripe
Stripe-Account
Stripe-App
Stripe-Dashboard
Stripe-Konto
Stripe-Kontos
Stripe-Modul
Stripe-Support
Stripe-Test-API
Stripes
Strong
Swish
Synchronisations
systemweiten
Tab
tag
Teammitglied
Teamname
Teilnehmer-Badges
Telephone
Terminal-ID
Termin-ID
Ticketing
Ticketing-Firma
Ticket-Output
Ticket-QR-Code
Timeout
To
Tokengenerator
Toolbar
TODO
To-Do-Liste
TOTP
Trace-Nummer
Trace
Tracking
transaktionale
Trustly
T-Shirts
Turnover-Nummer
Turnover
TWINT
txt
überbuchen
überbucht
überbuchten
überzahlt
Überzahlt
ÜBERZAHLT
überzahlte
Überzahlte
Überzahlten
uhrzeit
UID
UID-Basis
UID-Schutzfunktion
Ultralight
umzubuchen
ungespeicherte
Unkategorisiert
unkategorisiert
Unkategorisierte
unlöschbar
unlöschbaren
untenstehende
untenstehenden
Unterzahlt
unterzahlt
UNTERZAHLT
unzugeordnete
Unzugeordnete
unzugeordneten
umzubuchen
URIs
Ursprüngl
USt
USt-ID
USt-ID-Nr
USt-ID-Nummer
Überweisungs
Überzahlten
Validierung
Validierungsregeln
Varianten-ID
Venmo
Veranstalterdomain
Veranstaltereinstellungen
@@ -498,50 +394,39 @@ Veranstalterseite
Veranstalterübersicht
veranstalterweiten
Veranstaltungs
Veranstaltungs-Metadaten
Veranstalterdomain
veranstaltungsweiten
Verfügbarkeitsberechnung
Verfügbarkeitsstatus
Verkaufs-ID
Verkkopankki
Veröffentlichbarer
Verwendungszweck-Postfix
VIP-Bereiches
Warenkorb-ID
Warenkorb-Timeout
VIP
WebAuthn
WebAuthn-Gerät
WebAuthn-kompatibler
WebAuthn-Token
WebAuthn-Unterstützung
Webhook
Webhooks
Webhook-Wiederholungsaufträge
Weiterleitungs
WeChat
WeChat-Zahlung
Weiterleitungs-URIs
Weiterleitungs-URL
Weiterleitungs-URLs
WhatsApp
Widget
Widget-Code
xlsx
XXX
XXXX
XXXXX
Yubikey
Zahlungs
Zahlungsbestätigungs-E-Mail
Zahlungserinnerungs-E-Mail
Zahlungs-ID
Zahlungspflichtig
Zahlungsbestätigungs
Zahlungserinnerungs
zahlungspflichtig
Zahlungsplugins
Zehnerkarten
Zeitbasiert
zeitbasiert
Zeitslotbuchung
Zimpler
ZIP-Datei
ZIP
zubuchbaren
zurückbuchen
zurückgeleitet
zurückwechseln
zutrittsberechtigt
ZVT-Terminal
zzgl
ZVT

View File

@@ -1,143 +1,125 @@
ABGEKÜNDIGT
2FA
ABN
AES
Absenderadresse
Absenderinformation
Absendername
ABGEKÜNDIGT
Admin
Adminbereich
Admin-Modus
Admin-Sitzung
Admin-Sitzungen
AES
Affirm
AGPL
AGPLv
Alipay
and
API-Meta-Informationen
APM
App
App-Gebühr
ApplePay
Apps
APM
as
Aufbuchungen
aufeinanderfolgenden
Aufteilungsliste
aufzubuchen
auschecken
Ausgangsscan
Ausgangsscans
ausgecheckt
ausgeklappt
ausgecheckt
auswahl
Auth
Authentication
Authenticator-App
Authenticator
Authentifizierungsmechanismus
Autorisierungs
Autorisierungscode
Autorisierungs-Endpunktes
Backend
Badge
Badge-Druck
Badge-Layout
Badge-Layouts
Badges
Bancontact
Bank-App
BankID
Banking-App
Banking
barcodes
Baskisch
Bcc
BCC-Adresse
Bcc-Kopie
BCC
Beispielevent
Beispielproduktvariantenbeschreibung
Belarus
Benachrichtigungs
Benachrichtigungsart
Benachrichtigungsarten
Benachrichtigungseinstellungen
Benachrichtigungs-Einstellungen
Benachrichtigungs-E-Mail
Benutzer-ID-Feld
Benutzer-ID-Felds
Bestätigungs-E-Mail
Bestellbestätigungs-E-Mail
Bestellbestätigungs-E-Mails
Berechtigungs
Bestätigungs
Bestellbestätigungs
Bestellungsänderungen
Bestellungs-Synchronisation
Bestellungs-Synchronisierung
Bestellungsstatus
Bestellungs
bez
BezahlCode
Bezahlmethode
Blackberry
BLIK
BN-Code
Blogpost
BN
Branding
Browsereinstellungen
BSD
bspw
Bokmål
Boleto
Branding-Informationen
Browsereinstellungen
BSD-Lizenz
bspw
Buchhaltungs
Bundles
Butterfly-Badge
Butterfly
bzw
ca
Cc
Ceuta
Cc
chardet
charge
Charge-ID
Checkbox
Check-in-App
Check-in-Apps
Check-in-QR-Code
Checkout
Chrome
Client-ID
Client-Secret
CODE.txt
Community-Übersetzungen
Choice
Community
CONFIRM
Connect
Cookie-Consent-Management
Cookie-Consent-Mechanismus
Consent
Copyleft
Cronjob
Cronjob-Komponente
Cross-Selling-Bedingung
Cross-Selling-Kategorie
Cross-Selling-Kategorien
Cross-Selling-Schritt
Cross
csv
CSV
CSV-Datei
CSV-Dateien
CSV-Eingabe
CSV-Eingabedaten
CSV-Import
CSV-Input
CSV-Lesen
CSV-Spalte
Customer
CZK
Debug-Modus
Dashboard
Datensynchronisation
Debug
dekodi
Desktop-Apps
deliverability
DNS
Di
Do
Doe
Downloadformat
Downloadseite
Dr
Drag-and-Drop-Interfaces
Drag
Droid
Drop
DSS
Edge
Eingangsscan
Einlassbuchung
Einlassdatum
Einlasskontrolle
Einlassuhrzeita
einzuchecken
email
E-Mail-Renderer
Enterprise-Lizenz
Enterprise-Lizenzen
Enterprise-Plugin
Enterprise-Plugins
eps
Enterprise
EPC
EPS
eps
Erstattungsbetrag
Erstattungsliste
Erstattungsmethode
@@ -145,230 +127,175 @@ Erstattungsoptionen
Erstattungsstatus
Erstattungsweg
erstmalig
Erweiterungs
etc
EU-USt-ID-Nr
Event
Event-Eigenschaft
Eventeingang
Event-Erstellung
Event-Setup-Tool
Event-Ticketing-Software
Event-Ticketshop
Event-Übersicht
Event-Website
Eventfirma
evtl
Explorer
FA
Favicon
F-Droid
Footer
Footer-Link
Footer-Text
Galicisch
Geocoding
Geocoding-Daten
Geo-Koordinaten
Geräte-ID
gehostete
geht's
GENEXAMPLE
Geo
geocoding
gescannt
ggf
Ggf
GiroCode
giropay
GPL
Grants
Gruppierungsspalte
Gruppierungswert
Gruppierungsspalte
Guide
Gutscheineinlöser
Händler-ID
Händler-PayPal-Konto
Hardware-Tokengenerator
herunterscrollen
hochlädst
HTML-E-Mail-Renderer
HTTPS
HTTPS-Verbindungen
HTTPS-Website
IBAN
IBANs
iCal
ics-Kalenderdatei
ics
ID
iDEAL
IDs
Inc
inkl
innen-Badges
innenname
innennamen
innergemeinschaftliche
Innergemeinschaftlicher
Installations-ID
Integrationen
Input
Installations
integrationen
intra
INV
invalidieren
invalidiert
iOS
ISU
iOS
Itaú
iTunes
JavaScript
JSON-Datei
JSON
Kategoriebeschreibung
Key
Klarna
Kombitickets
Kompatibilitätsmodus
Konfigurations
Kosovo
land
landesspezifische
Lead-Scanning
Leaflet-Kacheln
Lead
Leaflet
Linktext
lit
Log-ID
Logindaten
Lösch
loszulegen
Ltd
Macau
MapQuest-API-Key
max
Medien-ID
MariaDB
MapQuest
Melilla
Mercado
Merchandise
Meta
Metadaten
Meta-Eigenschaft
Meta-Eigenschaften
Meta-Informationen
Mi
Mifare
min
Mitgliedschafts
Mitgliedschaftsdauer
Mitgliedschafts-Typ
Mitgliedschafts-Typen
min
Mo
MobilePay
MOTO
MOTO-Zahlungen
Multibanco
Multiple-Choice-Fragen
MwSt
MyBank
name
NFC
NFC-basierte
NFC-Chip
NFC-Chips
NFC-Medien
NFC-Zahlungsmitteln
Nr
NREI
number
NXP
Objekt-IDs
Offline-Scan
OK
Online-Banking
Onlinebanking-Zugangsdaten
On
Onlinebanking
Open
OpenCage-API-Key
OpenCage
OpenID
OpenStreetMap
Opera
Output
OXXO
Pago
parsen
Pago
Pay
PayPal
PayPal-Account
PayPal-Accounts
PayPal-Konto
PayPal-Kontos
PayPal-Sandbox
PayPal-Sandbox-Account
PayPal-Seite
PayPal-Verkaufs-ID
PayPal-Webhook
PayPal-Zahlung
PayPal-Zahlungen
PayPal-Zahlungs-ID
PayPals
PayU
PCI-DSS-Formulare
Peppol-Teilnehmer-ID
Peppol-Teilnehmer-IDs
PCI
Personalisierung
PKCE-Erweiterung
Peppol
PKCE
Platzhalterzeichen
Play
Plugin
Plugins
POS
Postfix
PostgreSQL
PPRO
prefix
Prefix
pretix
pretix-Apps
pretix-Benutzerkennung
pretixdesk-Apps
pretixdesk
pretixdroid
pretix-Enterprise-Lizenz
pretix-Enterprise-Plugins
pretix-Entwickler
pretix-Entwicklern
pretix-Feld
pretix-Installation
pretix-Konto
pretix-Kontos
pretix-Logo
pretix-Logos
pretix-Plugins
pretixPOS
pretixPRINT
pretixPRINT-Version
pretixSCAN
pretix-Support
pretix-Team
pretix-Update
pretix-Version
pretix-Versionen
pretix-Widget
Produkt-ID
Produkt-Metadaten
Professional
Przelewy
pt
px
QR-Code
QR-Code-Bereich
QR-Code-Geheimnis
QR-Code-Inhalt
QR-Code-Reader
QR-Codes
QR-Farbe
Query-Parameter
Query
QR
rabattiert
Rabattiert
Rabattierung
Rechnungs-E-Mail
Reader
Rechnungs
Rechungsdatei
Reddit
Referer
Registrierungs
Registrierungsdatum
Registrierungs-Details
Registrierungsnummer
Registrierungsversuche
remote
Renderer
Request
Requests
Request-URL
Reservierungszeitraum
reverse
Reverse
Reverse-Proxy
Revisionssicherheit
Revolut
Revolut-App
rückabgewickelt
Rundungsdifferenzen
Sa
Saalplan
Sammlungsstücken
SAQ
SCA
Scan
Scanning-Apps
Scans
Scan-Terminals
Scan-Typ
Scan-Zeitpunkt
Scanergebnis
Scanning
schiefgeht
schiefgelaufen
Scope
@@ -377,37 +304,23 @@ SdI
sechsstelligen
Secret
Security
selbst-gehostete
SEPA-Bankeinzug
SEPA-Bankkonto
SEPA-Konten
SEPA-Lastschrift
SEPA-Lastschriften
SEPA-Mandat
SEPA-XML
Session-ID
Selling
SEPA
Shirts
Signaturverfahren
Single-Sign-On
Single-Sign-On-Dienste
Single-Sign-On-Methode
Single-Sign-On-Provider
Sign
Sitzplanmoduls
Sitzplatz-ID
Sitzplatz-IDs
Social-Media-Bild
Social
Sofort
SOFORT
Sorry
Source
Source-Codes
SPF-Eintrag
SPF
SSL
SSO
SSO-Client
SSO-Clients
SSO-Provider
STARTTLS
Steuer-Aufteilungsliste
Steuerregel-ID
Steuerschuldnerschaft
Store
Stornierungsanfrage
Stornobedingungen
Stornobeleg
@@ -417,75 +330,58 @@ Stornogebühren
Stornos
Strg
Stripe
Stripe-Account
Stripe-App
Stripe-Dashboard
Stripe-Konto
Stripe-Kontos
Stripe-Modul
Stripe-Support
Stripe-Test-API
Stripes
Strong
Swish
Synchronisations
systemweiten
Tab
tag
Teammitglied
Teamname
Teilnehmer-Badges
Telephone
Terminal-ID
Termin-ID
Ticketing
Ticketing-Firma
Ticket-Output
Ticket-QR-Code
Timeout
To
Tokengenerator
Toolbar
TODO
To-Do-Liste
TOTP
Trace-Nummer
Trace
Tracking
transaktionale
Trustly
T-Shirts
Turnover-Nummer
Turnover
TWINT
txt
überbuchen
überbucht
überbuchten
überzahlt
Überzahlt
ÜBERZAHLT
überzahlte
Überzahlte
Überzahlten
uhrzeit
UID
UID-Basis
UID-Schutzfunktion
Ultralight
umzubuchen
ungespeicherte
Unkategorisiert
unkategorisiert
Unkategorisierte
unlöschbar
unlöschbaren
untenstehende
untenstehenden
Unterzahlt
unterzahlt
UNTERZAHLT
unzugeordnete
Unzugeordnete
unzugeordneten
umzubuchen
URIs
Ursprüngl
USt
USt-ID
USt-ID-Nr
USt-ID-Nummer
Überweisungs
Überzahlten
Validierung
Validierungsregeln
Varianten-ID
Venmo
Veranstalterdomain
Veranstaltereinstellungen
@@ -498,50 +394,39 @@ Veranstalterseite
Veranstalterübersicht
veranstalterweiten
Veranstaltungs
Veranstaltungs-Metadaten
Veranstalterdomain
veranstaltungsweiten
Verfügbarkeitsberechnung
Verfügbarkeitsstatus
Verkaufs-ID
Verkkopankki
Veröffentlichbarer
Verwendungszweck-Postfix
VIP-Bereiches
Warenkorb-ID
Warenkorb-Timeout
VIP
WebAuthn
WebAuthn-Gerät
WebAuthn-kompatibler
WebAuthn-Token
WebAuthn-Unterstützung
Webhook
Webhooks
Webhook-Wiederholungsaufträge
Weiterleitungs
WeChat
WeChat-Zahlung
Weiterleitungs-URIs
Weiterleitungs-URL
Weiterleitungs-URLs
WhatsApp
Widget
Widget-Code
xlsx
XXX
XXXX
XXXXX
Yubikey
Zahlungs
Zahlungsbestätigungs-E-Mail
Zahlungserinnerungs-E-Mail
Zahlungs-ID
Zahlungspflichtig
Zahlungsbestätigungs
Zahlungserinnerungs
zahlungspflichtig
Zahlungsplugins
Zehnerkarten
Zeitbasiert
zeitbasiert
Zeitslotbuchung
Zimpler
ZIP-Datei
ZIP
zubuchbaren
zurückbuchen
zurückgeleitet
zurückwechseln
zutrittsberechtigt
ZVT-Terminal
zzgl
ZVT

View File

@@ -36,6 +36,7 @@ import copy
import hmac
import inspect
import json
import logging
import mimetypes
import os
import re
@@ -98,6 +99,8 @@ from pretix.presale.views import (
from pretix.presale.views.event import get_grouped_items
from pretix.presale.views.robots import NoSearchIndexViewMixin
logger = logging.getLogger(__name__)
class OrderDetailMixin(NoSearchIndexViewMixin):
@@ -734,11 +737,18 @@ class OrderInvoiceCreate(EventViewMixin, OrderDetailMixin, View):
elif self.order.invoices.exists():
messages.error(self.request, _('An invoice for this order already exists.'))
else:
i = generate_invoice(self.order)
self.order.log_action('pretix.event.order.invoice.generated', data={
'invoice': i.pk
})
messages.success(self.request, _('The invoice has been generated.'))
try:
i = generate_invoice(self.order)
self.order.log_action('pretix.event.order.invoice.generated', data={
'invoice': i.pk
})
messages.success(self.request, _('The invoice has been generated.'))
except Exception as e:
logger.exception("Could not generate invoice.")
self.order.log_action("pretix.event.order.invoice.failed", data={
"exception": str(e)
})
messages.error(self.request, _('Invoice generation has failed, please reach out to the organizer.'))
return redirect(self.get_order_url())
@@ -807,24 +817,37 @@ class OrderModify(EventViewMixin, OrderDetailMixin, OrderQuestionsViewMixin, Tem
elif self.order.invoices.exists():
messages.error(self.request, _('An invoice for this order already exists.'))
else:
i = generate_invoice(self.order)
self.order.log_action('pretix.event.order.invoice.generated', data={
'invoice': i.pk
})
messages.success(self.request, _('The invoice has been generated.'))
try:
i = generate_invoice(self.order)
self.order.log_action('pretix.event.order.invoice.generated', data={
'invoice': i.pk
})
messages.success(self.request, _('The invoice has been generated.'))
except Exception as e:
logger.exception("Could not generate invoice.")
self.order.log_action("pretix.event.order.invoice.failed", data={
"exception": str(e)
})
messages.error(self.request, _('Invoice generation has failed, please reach out to the organizer.'))
elif self.request.event.settings.invoice_reissue_after_modify:
if self.invoice_form.changed_data:
inv = self.order.invoices.last()
if inv and not inv.canceled and not inv.shredded:
c = generate_cancellation(inv)
if self.order.status != Order.STATUS_CANCELED:
inv = generate_invoice(self.order)
else:
inv = c
self.order.log_action('pretix.event.order.invoice.reissued', data={
'invoice': inv.pk
try:
inv = self.order.invoices.last()
if inv and not inv.canceled and not inv.shredded:
c = generate_cancellation(inv)
if self.order.status != Order.STATUS_CANCELED:
inv = generate_invoice(self.order)
else:
inv = c
self.order.log_action('pretix.event.order.invoice.reissued', data={
'invoice': inv.pk
})
messages.success(self.request, _('The invoice has been reissued.'))
except Exception as e:
self.order.log_action("pretix.event.order.invoice.failed", data={
"exception": str(e)
})
messages.success(self.request, _('The invoice has been reissued.'))
logger.exception("Could not generate invoice.")
invalidate_cache.apply_async(kwargs={'event': self.request.event.pk, 'order': self.order.pk})
CachedTicket.objects.filter(order_position__order=self.order).delete()