Gift cards: Improved support for cross-organizer acceptance (#3311)

Co-authored-by: Martin Gross <martin@pc-coholic.de>
This commit is contained in:
Raphael Michel
2023-06-15 14:17:40 +02:00
committed by GitHub
parent b3c917925c
commit f8be8296dd
22 changed files with 605 additions and 139 deletions

View File

@@ -293,6 +293,19 @@ def test_giftcard_transact_cross_organizer(token_client, organizer, event, other
assert other_giftcard.transactions.last().acceptor == organizer
@pytest.mark.django_db
def test_giftcard_transact_cross_organizer_inactive(token_client, organizer, event, other_giftcard):
organizer.gift_card_issuer_acceptance.update(active=False)
resp = token_client.post(
'/api/v1/organizers/{}/giftcards/{}/transact/?include_accepted=true'.format(organizer.slug, other_giftcard.pk),
{
'value': '10.00',
},
format='json'
)
assert resp.status_code == 404
@pytest.mark.django_db
def test_giftcard_transact_min_zero(token_client, organizer, event, giftcard):
resp = token_client.post(

View File

@@ -19,14 +19,16 @@
# 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 datetime import timedelta
from datetime import datetime, timedelta, timezone
from decimal import Decimal
import pytest
from django.utils.timezone import now
from django_scopes import scopes_disabled
from pretix.base.models import Order, Organizer, ReusableMedium
from pretix.base.models import (
Event, GiftCardAcceptance, Order, Organizer, ReusableMedium,
)
@pytest.fixture
@@ -49,11 +51,28 @@ def organizer2():
@pytest.fixture
def giftcard2(organizer2):
gc = organizer2.issued_gift_cards.create(secret="ABCDEF", currency="EUR")
gc = organizer2.issued_gift_cards.create(secret="IJKLMNOP", currency="EUR")
gc.transactions.create(value=Decimal('23.00'), acceptor=organizer2)
return gc
@pytest.fixture
def medium2(organizer2):
m = organizer2.reusable_media.create(identifier="ABCDEFGH", type="barcode", active=True)
return m
@pytest.fixture
@scopes_disabled()
def org2_event(organizer2):
e = Event.objects.create(
organizer=organizer2, name='Dummy2', slug='dummy2',
date_from=datetime(2017, 12, 27, 10, 0, 0, tzinfo=timezone.utc),
plugins='pretix.plugins.banktransfer,pretix.plugins.ticketoutputpdf'
)
return e
@pytest.fixture
def customer(organizer, event):
return organizer.customers.create(
@@ -67,6 +86,7 @@ def customer(organizer, event):
TEST_MEDIUM_RES = {
"id": 1,
"organizer": "dummy",
"identifier": "ABCDEFGH",
"type": "barcode",
"active": True,
@@ -357,3 +377,64 @@ def test_medium_autocreate(token_client, organizer):
)
assert resp.status_code == 200
assert resp.data["result"] is None
@pytest.mark.django_db
def test_medium_lookup_cross_organizer(token_client, organizer, organizer2, org2_event, medium2, giftcard2):
with scopes_disabled():
o = Order.objects.create(
code='FOO', event=org2_event, email='dummy@dummy.test',
status=Order.STATUS_PENDING, datetime=now(), expires=now() + timedelta(days=10),
total=14, locale='en'
)
ticket = org2_event.items.create(name='Early-bird ticket', category=None, default_price=23, admission=True,
personalized=True)
op = o.positions.create(item=ticket, price=Decimal("14"))
medium2.linked_orderposition = op
medium2.linked_giftcard = giftcard2
medium2.save()
resp = token_client.post(
'/api/v1/organizers/{}/reusablemedia/lookup/'.format(organizer.slug),
{
"type": medium2.type,
"identifier": medium2.identifier,
},
format='json'
)
assert resp.status_code == 200
assert resp.data["result"] is None
gca = GiftCardAcceptance.objects.create(
issuer=organizer2,
acceptor=organizer,
active=True,
reusable_media=False
)
resp = token_client.post(
'/api/v1/organizers/{}/reusablemedia/lookup/'.format(organizer.slug),
{
"type": medium2.type,
"identifier": medium2.identifier,
},
format='json'
)
assert resp.status_code == 200
assert resp.data["result"] is None
gca.reusable_media = True
gca.save()
resp = token_client.post(
'/api/v1/organizers/{}/reusablemedia/lookup/'.format(organizer.slug),
{
"type": medium2.type,
"identifier": medium2.identifier,
},
format='json'
)
assert resp.status_code == 200
assert resp.data["result"] is not None
assert resp.data["result"]["organizer"] == "partner"
assert resp.data["result"]["linked_giftcard"] is not None
assert resp.data["result"]["linked_orderposition"] is None

View File

@@ -51,7 +51,8 @@ def gift_card(organizer):
@pytest.fixture
def admin_user(organizer):
u = User.objects.create_user('dummy@dummy.dummy', 'dummy')
admin_team = Team.objects.create(organizer=organizer, can_manage_gift_cards=True, name='Admin team')
admin_team = Team.objects.create(organizer=organizer, can_manage_gift_cards=True, name='Admin team',
can_change_organizer_settings=True)
admin_team.members.add(u)
return u
@@ -174,24 +175,29 @@ def test_card_detail_view_transact_invalid_value(organizer, admin_user, gift_car
@pytest.mark.django_db
def test_manage_acceptance(organizer, organizer2, admin_user, gift_card, client, team2):
gca = organizer.gift_card_issuer_acceptance.create(issuer=organizer2, active=False)
client.login(email='dummy@dummy.dummy', password='dummy')
client.post('/control/organizer/dummy/giftcards', {
'add': organizer2.slug
client.post('/control/organizer/dummy/giftcards/acceptance', {
'accept_issuer': organizer2.slug
})
assert organizer.gift_card_issuer_acceptance.filter(issuer=organizer2).exists()
client.post('/control/organizer/dummy/giftcards', {
'del': organizer2.slug
gca.refresh_from_db()
assert gca.active
client.post('/control/organizer/dummy/giftcards/acceptance', {
'delete_issuer': organizer2.slug
})
assert not organizer.gift_card_issuer_acceptance.filter(issuer=organizer2).exists()
@pytest.mark.django_db
def test_manage_acceptance_permission_required(organizer, organizer2, admin_user, gift_card, client):
client.login(email='dummy@dummy.dummy', password='dummy')
client.post('/control/organizer/dummy/giftcards', {
'add': organizer2.slug
client.post('/control/organizer/dummy/giftcards/acceptance/invite', {
'acceptor': organizer2.slug
})
assert not organizer.gift_card_issuer_acceptance.filter(issuer=organizer2).exists()
assert organizer.gift_card_acceptor_acceptance.filter(acceptor=organizer2).exists()
client.post('/control/organizer/dummy/giftcards/acceptance', {
'delete_acceptor': organizer2.slug
})
assert not organizer.gift_card_acceptor_acceptance.filter(acceptor=organizer2).exists()
@pytest.mark.django_db

View File

@@ -219,6 +219,8 @@ organizer_urls = [
'organizer/abc/giftcard/add',
'organizer/abc/giftcard/1/',
'organizer/abc/giftcard/1/edit',
'organizer/abc/giftcards/acceptance',
'organizer/abc/giftcards/acceptance/invite',
]
@@ -552,6 +554,8 @@ organizer_permission_urls = [
("can_manage_gift_cards", "organizer/dummy/giftcard/add", 200),
("can_manage_gift_cards", "organizer/dummy/giftcard/1/", 404),
("can_manage_gift_cards", "organizer/dummy/giftcard/1/edit", 404),
("can_change_organizer_settings", "organizer/dummy/giftcards/acceptance", 200),
("can_change_organizer_settings", "organizer/dummy/giftcards/acceptance/invite", 200),
# bank transfer
("can_change_orders", "organizer/dummy/banktransfer/import/", 200),

View File

@@ -1676,6 +1676,24 @@ class CheckoutTestCase(BaseCheckoutTestCase, TestCase):
assert gc.issuer == orga2
assert gc.transactions.last().acceptor == self.orga
def test_giftcard_cross_organizer_inactive(self):
self.orga.issued_gift_cards.create(currency="EUR")
orga2 = Organizer.objects.create(slug="foo2", name="foo2")
gc = orga2.issued_gift_cards.create(currency="EUR")
gc.transactions.create(value=23, acceptor=orga2)
self.orga.gift_card_issuer_acceptance.create(issuer=orga2, active=False)
self.event.settings.set('payment_banktransfer__enabled', True)
with scopes_disabled():
CartPosition.objects.create(
event=self.event, cart_id=self.session_key, item=self.ticket,
price=23, expires=now() + timedelta(minutes=10)
)
response = self.client.post('/%s/%s/checkout/payment/' % (self.orga.slug, self.event.slug), {
'payment': 'giftcard',
'giftcard': gc.secret
}, follow=True)
assert 'This gift card is not known.' in response.content.decode()
def test_giftcard_in_test_mode(self):
gc = self.orga.issued_gift_cards.create(currency="EUR")
gc.transactions.create(value=20, acceptor=self.orga)