Compare commits

..
Author SHA1 Message Date
7eb6ccae5e Update src/pretix/base/invoicing/email.py
Co-authored-by: Raphael Michel <michel@pretix.eu>
2026-08-12 21:41:49 +02:00
Mira Weller 742cc74032 Display invoice transmission in the (re)transmit button tooltip (Z#23241800) 2026-08-07 12:05:16 +02:00
6 changed files with 28 additions and 19 deletions
+8
View File
@@ -82,6 +82,14 @@ class EmailTransmissionType(TransmissionType):
}
return {}
def describe_invoice_destination(self, invoice):
info = (invoice.invoice_to_transmission_info or {})
if info.get("transmission_email_address"):
recipient = info["transmission_email_address"]
else:
recipient = invoice.order.email
return _("Via email to {recipient}").format(recipient=recipient)
@transmission_providers.new()
class EmailTransmissionProvider(TransmissionProvider):
+13
View File
@@ -123,6 +123,19 @@ class TransmissionType:
data.append((f.label, v))
return data
def describe_invoice_destination(self, invoice):
info = self.describe_info(
invoice.invoice_to_transmission_info or {},
invoice.invoice_to_country,
invoice.invoice_to_is_business,
)
destination = ", ".join(f"{k}: {v}" for (k, v) in info)
return "{via} {method}{destination}".format(
via=_("Via"),
method=self.verbose_name,
destination=f" ({destination})" if destination else "",
)
def pdf_watermark(self) -> Optional[str]:
"""
Return a watermark that should be rendered across the PDF file.
+4
View File
@@ -398,6 +398,10 @@ class Invoice(models.Model):
from pretix.base.invoicing.transmission import transmission_types
return transmission_types.get(identifier=self.transmission_type)[0]
@property
def transmission_type_destination_description(self):
return self.transmission_type_instance.describe_invoice_destination(self)
def set_transmission_failed(self, provider, data):
self.transmission_status = Invoice.TRANSMISSION_STATUS_FAILED
self.transmission_date = now()
@@ -357,7 +357,7 @@
action="{% url "control:event.order.retransmitinvoice" event=request.event.slug organizer=request.event.organizer.slug code=order.code id=i.pk %}">
{% csrf_token %}
<button class="btn btn-default btn-xs" data-toggle="tooltip"
title="{{ i.transmission_type_instance.verbose_name }}">
title="{{ i.transmission_type_destination_description }}">
{% if i.transmission_status == "pending" %}
{% trans "Transmit" %}
{% else %}
+2 -17
View File
@@ -23,7 +23,7 @@ import json
import logging
import urllib.parse
from collections import OrderedDict
from datetime import datetime, timedelta
from datetime import timedelta
from decimal import Decimal
from django import forms
@@ -645,7 +645,7 @@ class PaypalMethod(BasePaymentProvider):
def _execute_payment(self, request: HttpRequest, payment: OrderPayment):
payment = OrderPayment.objects.select_for_update(of=OF_SELF).get(pk=payment.pk)
if payment.state == OrderPayment.PAYMENT_STATE_CONFIRMED:
# payment is already confirmed; possible return-view/webhook race-condition
logger.warning('payment is already confirmed; possible return-view/webhook race-condition')
return
try:
@@ -832,7 +832,6 @@ class PaypalMethod(BasePaymentProvider):
payment.info = json.dumps(pp_captured_order.dict())
payment.save(update_fields=['info'])
payment.confirm()
self.log_payment_duration(payment)
except Quota.QuotaExceededException as e:
raise PaymentException(str(e))
# Payment has not any captures yet - so it's probably in created status
@@ -842,20 +841,6 @@ class PaypalMethod(BasePaymentProvider):
if 'payment_paypal_oid' in request.session:
del request.session['payment_paypal_oid']
@staticmethod
def log_payment_duration(payment: OrderPayment):
try:
capture = payment.info_data["purchase_units"][0]["payments"]["captures"][0]
create_time: str | None = capture["create_time"]
update_time: str | None = capture["update_time"]
except (KeyError, IndexError, TypeError):
create_time = None
update_time = None
if create_time is not None and update_time is not None:
duration = datetime.fromisoformat(update_time) - datetime.fromisoformat(create_time)
logger.info('{}: {} - paypal payment processing time'.format(str(payment.global_id), str(duration)))
def payment_pending_render(self, request, payment) -> str:
retry = True
try:
-1
View File
@@ -490,7 +490,6 @@ def webhook(request, *args, **kwargs):
payment.info = json.dumps(sale.dict())
payment.save(update_fields=['info'])
payment.confirm()
prov.log_payment_duration(payment)
except Quota.QuotaExceededException:
pass
elif sale['status'] == 'APPROVED':