GiftCard: Add more information to transactions (#3308)

This commit is contained in:
Raphael Michel
2023-05-12 09:38:35 +02:00
committed by GitHub
parent 916ee0697f
commit c0419518c3
19 changed files with 247 additions and 85 deletions

View File

@@ -0,0 +1,24 @@
# Generated by Django 3.2.18 on 2023-05-11 11:02
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pretixbase', '0238_giftcard_owner_ticket'),
]
operations = [
migrations.AddField(
model_name='giftcardtransaction',
name='acceptor',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='gift_card_transactions', to='pretixbase.organizer'),
),
migrations.AddField(
model_name='giftcardtransaction',
name='info',
field=models.JSONField(null=True),
),
]

View File

@@ -25,7 +25,9 @@ from django.conf import settings
from django.core.validators import RegexValidator
from django.db import models
from django.db.models import Sum
from django.urls import reverse
from django.utils.crypto import get_random_string
from django.utils.html import format_html
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _, pgettext_lazy
@@ -160,6 +162,61 @@ class GiftCardTransaction(models.Model):
on_delete=models.PROTECT
)
text = models.TextField(blank=True, null=True)
info = models.JSONField(
null=True, blank=True,
)
acceptor = models.ForeignKey(
'Organizer',
related_name='gift_card_transactions',
on_delete=models.PROTECT,
null=True, blank=True
)
class Meta:
ordering = ("datetime",)
def save(self, *args, **kwargs):
if not self.pk and not self.acceptor:
raise ValueError("`acceptor` should be set on all new gift card transactions.")
super().save(*args, **kwargs)
def display(self, customer_facing=True):
from ..signals import gift_card_transaction_display
for receiver, response in gift_card_transaction_display.send(self, transaction=self, customer_facing=customer_facing):
if response:
return response
if self.order_id:
if not self.text:
if not customer_facing:
return format_html(
'<a href="{}">{}</a>',
reverse(
"control:event.order",
kwargs={
"event": self.order.event.slug,
"organizer": self.order.event.organizer.slug,
"code": self.order.code,
}
),
self.order.full_code
)
return self.order.full_code
else:
return self.text
else:
if self.text:
return format_html(
'<em>{}:</em> {}',
_('Manual transaction'),
self.text,
)
else:
return _('Manual transaction')
def display_backend(self):
return self.display(customer_facing=False)
def display_presale(self):
return self.display(customer_facing=True)

View File

@@ -1469,7 +1469,8 @@ class GiftCardPayment(BasePaymentProvider):
trans = gc.transactions.create(
value=-1 * payment.amount,
order=payment.order,
payment=payment
payment=payment,
acceptor=self.event.organizer,
)
payment.info_data = {
'gift_card': gc.pk,
@@ -1490,7 +1491,8 @@ class GiftCardPayment(BasePaymentProvider):
trans = gc.transactions.create(
value=refund.amount,
order=refund.order,
refund=refund
refund=refund,
acceptor=self.event.organizer,
)
refund.info_data = {
'gift_card': gc.pk,

View File

@@ -235,7 +235,7 @@ def reactivate_order(order: Order, force: bool=False, user: User=None, auth=None
for gc in position.issued_gift_cards.all():
gc = GiftCard.objects.select_for_update(of=OF_SELF).get(pk=gc.pk)
gc.transactions.create(value=position.price, order=order)
gc.transactions.create(value=position.price, order=order, acceptor=order.event.organizer)
break
for m in position.granted_memberships.all():
@@ -513,7 +513,7 @@ def _cancel_order(order, user=None, send_mail: bool=True, api_token=None, device
)
)
else:
gc.transactions.create(value=-position.price, order=order)
gc.transactions.create(value=-position.price, order=order, acceptor=order.event.organizer)
for m in position.granted_memberships.all():
m.canceled = True
@@ -2186,7 +2186,7 @@ class OrderChangeManager:
card=gc.secret
))
else:
gc.transactions.create(value=-op.position.price, order=self.order)
gc.transactions.create(value=-op.position.price, order=self.order, acceptor=self.order.event.organizer)
for m in op.position.granted_memberships.with_usages().all():
m.canceled = True
@@ -2202,7 +2202,7 @@ class OrderChangeManager:
card=gc.secret
))
else:
gc.transactions.create(value=-opa.position.price, order=self.order)
gc.transactions.create(value=-opa.position.price, order=self.order, acceptor=self.order.event.organizer)
for m in opa.granted_memberships.with_usages().all():
m.canceled = True
@@ -2918,7 +2918,7 @@ def signal_listener_issue_giftcards(sender: Event, order: Order, **kwargs):
currency=sender.currency, issued_in=p, testmode=order.testmode,
expires=sender.organizer.default_gift_card_expiry,
)
gc.transactions.create(value=p.price - issued, order=order)
gc.transactions.create(value=p.price - issued, order=order, acceptor=sender.organizer)
any_giftcards = True
p.secret = gc.secret
p.save(update_fields=['secret'])

View File

@@ -578,6 +578,20 @@ All plugins that are installed may send fields for the global settings form, as
an OrderedDict of (setting name, form field).
"""
gift_card_transaction_display = django.dispatch.Signal()
"""
Arguments: ``transaction``, ``customer_facing``
To display an instance of the ``GiftCardTransaction`` model to a human user,
``pretix.base.signals.gift_card_transaction_display`` will be sent out with a ``transaction`` argument.
The ``customer_facing`` argument specifies whether the HTML will be shown to an end-user or if it is being
used in the backend.
The first received response that is not ``None`` will be used to display the log entry
to the user. The receivers are expected to return a string (that might be marked with ``mark_safe`` from Django if
it contains HTML).
"""
order_fee_calculation = EventPluginSignal()
"""
Arguments: ``positions``, ``invoice_address``, ``meta_info``, ``total``, ``gift_cards``, ``payment_requests``