Waiting list: Add edit view for entry (Z#23215496) (#5712)

* add edit view for waitinglist entry

* add test and fix behaviour when name isn't asked for

* fix linting

* add testcases for new edit view

* fix test

* fix linting

* add search to the waitinglist view

* repair settings check

Co-authored-by: Richard Schreiber <schreiber@pretix.eu>

* make name and phone field optional by removing them

* remove item and variation fields from form

rather set those values during clean

* change label from "Item and Variation" to "Product"

* include only products with an enabled waitinglist in the product field

* combine edit.html and transfer.html

* change transfer to edit

* add tests

* code style

* Update src/pretix/control/forms/waitinglist.py

Co-authored-by: Richard Schreiber <schreiber@pretix.eu>

* Update src/pretix/control/forms/waitinglist.py

Co-authored-by: Richard Schreiber <schreiber@pretix.eu>

* Update src/pretix/control/urls.py

Co-authored-by: Richard Schreiber <schreiber@pretix.eu>

* Update src/pretix/control/templates/pretixcontrol/waitinglist/edit.html

Co-authored-by: Richard Schreiber <schreiber@pretix.eu>

* Update src/pretix/control/templates/pretixcontrol/waitinglist/index.html

Co-authored-by: Richard Schreiber <schreiber@pretix.eu>

* Update src/pretix/control/views/waitinglist.py

Co-authored-by: Richard Schreiber <schreiber@pretix.eu>

* Update src/pretix/control/views/waitinglist.py

Co-authored-by: Richard Schreiber <schreiber@pretix.eu>

* Update src/pretix/control/views/waitinglist.py

Co-authored-by: Richard Schreiber <schreiber@pretix.eu>

* remove validations

* remove validations

* replace widget

* implement small review items

* add better assertions

* add test for the different edit form variations

* add queryset to prefetch only active ItemVariations

* add queryset to prefetch only active ItemVariations

* propper use of WrappedPhoneNumberPrefixWidget

* cleanup

* add validation tests

* small review changes

* handle products with only inactive variations

* styling

---------

Co-authored-by: Richard Schreiber <schreiber@pretix.eu>
This commit is contained in:
Lukas Bockstaller
2026-02-23 16:35:24 +01:00
committed by GitHub
parent b2dce51a24
commit eab7d81a51
7 changed files with 320 additions and 67 deletions

View File

@@ -19,19 +19,6 @@
# 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/>.
#
# This file is based on an earlier version of pretix which was released under the Apache License 2.0. The full text of
# the Apache License 2.0 can be obtained at <http://www.apache.org/licenses/LICENSE-2.0>.
#
# This file may have since been changed and any changes are released under the terms of AGPLv3 as described above. A
# full history of changes and contributors is available at <https://github.com/pretix/pretix>.
#
# This file contains Apache-licensed contributions copyrighted by: Daniel
#
# Unless required by applicable law or agreed to in writing, software distributed under the Apache License 2.0 is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under the License.
from datetime import timedelta
import pytest
@@ -39,7 +26,8 @@ from django.utils.timezone import now
from django_scopes import scopes_disabled
from pretix.base.models import (
Event, Item, Organizer, Quota, Team, User, Voucher, WaitingListEntry,
Event, Item, ItemVariation, Organizer, Quota, Team, User, Voucher,
WaitingListEntry,
)
from pretix.control.views.dashboards import waitinglist_widgets
@@ -52,11 +40,12 @@ def env():
date_from=now(), plugins='pretix.plugins.banktransfer,tests.testdummy'
)
event.settings.set('ticketoutput_testdummy__enabled', True)
event.settings.set('waiting_list_names_asked', False)
event.settings.set('waiting_list_names_required', False)
event.settings.set('waiting_list_phones_asked', False)
user = User.objects.create_user('dummy@dummy.dummy', 'dummy')
item1 = Item.objects.create(event=event, name="Ticket", default_price=23,
admission=True)
item2 = Item.objects.create(event=event, name="Ticket", default_price=23,
admission=True)
item1 = Item.objects.create(event=event, name="Ticket", default_price=23, admission=True, allow_waitinglist=True)
item2 = Item.objects.create(event=event, name="Ticket", default_price=23, admission=True)
for i in range(5):
WaitingListEntry.objects.create(
@@ -78,7 +67,16 @@ def env():
t = Team.objects.create(organizer=o, can_view_orders=True, can_change_orders=True)
t.members.add(user)
t.limit_events.add(event)
return event, user, o, item1
wle = WaitingListEntry.objects.filter(item=item1).first()
variation = ItemVariation.objects.create(item=item1)
return {
"event": event,
"item1": item1,
"wle": wle,
"variation": variation,
}
@pytest.mark.django_db
@@ -122,7 +120,7 @@ def test_list(client, env):
assert 'foo0@bar.com' not in response.content.decode()
assert 'valid@example.org' not in response.content.decode()
response = client.get('/control/event/dummy/dummy/waitinglist/?item=%d' % env[3].pk)
response = client.get('/control/event/dummy/dummy/waitinglist/?item=%d' % env['item1'].pk)
assert 'item2@example.org' not in response.content.decode()
assert 'foo0@bar.com' in response.content.decode()
@@ -191,11 +189,161 @@ def test_delete_bulk(client, env):
WaitingListEntry.objects.get(id=wle.id)
@pytest.mark.django_db
def test_edit_settings(client, env):
event = env['event']
wle = env['wle']
client.login(email='dummy@dummy.dummy', password='dummy')
response = client.get('/control/event/dummy/dummy/waitinglist/%s/edit' % wle.id)
assert ['email', 'itemvar'] == list(response.context_data['form'].fields.keys())
event.settings.set('waiting_list_names_asked', True)
response = client.get('/control/event/dummy/dummy/waitinglist/%s/edit' % wle.id)
assert 'name_parts' in list(response.context_data['form'].fields.keys())
event.settings.set('waiting_list_names_required', True)
response = client.get('/control/event/dummy/dummy/waitinglist/%s/edit' % wle.id)
assert response.context_data['form'].fields['name_parts'].required is True
event.settings.set('waiting_list_phones_asked', True)
response = client.get('/control/event/dummy/dummy/waitinglist/%s/edit' % wle.id)
assert 'phone' in list(response.context_data['form'].fields.keys())
@pytest.mark.django_db
def test_edit_itemvariation(client, env):
item = env['item1']
variation = env['variation']
wle = env['wle']
client.login(email='dummy@dummy.dummy', password='dummy')
itemvar = f"{item.pk}-{variation.pk}"
client.post(
'/control/event/dummy/dummy/waitinglist/%s/edit' % wle.id,
data={
"email": f"1_{wle.email}",
"itemvar": itemvar
}
)
wle.refresh_from_db()
assert wle.variation == variation
@pytest.mark.django_db
def test_edit_validations_only_valid_item(client, env):
item = env['item1']
wle = env['wle']
client.login(email='dummy@dummy.dummy', password='dummy')
itemvar = f"{item.pk + 10000}"
response = client.post(
'/control/event/dummy/dummy/waitinglist/%s/edit' % wle.id,
data={
"email": f"1_{wle.email}",
"itemvar": itemvar
}
)
assert response.context_data['form'].errors['itemvar'] == ["Select a valid choice."]
@pytest.mark.django_db
def test_edit_validations_only_valid_variation(client, env):
item = env['item1']
wle = env['wle']
variation = env['variation']
client.login(email='dummy@dummy.dummy', password='dummy')
itemvar = f"{item.pk}-{variation.pk + 1}"
response = client.post(
'/control/event/dummy/dummy/waitinglist/%s/edit' % wle.id,
data={
"email": f"1_{wle.email}",
"itemvar": itemvar
}
)
assert response.context_data['form'].errors['itemvar'] == ["Select a valid choice."]
@pytest.mark.django_db
def test_edit_validations_inactive_item(client, env):
item = env['item1']
wle = env['wle']
item.active = False
item.save()
client.login(email='dummy@dummy.dummy', password='dummy')
response = client.post(
'/control/event/dummy/dummy/waitinglist/%s/edit' % wle.id,
data={
"email": f"1_{wle.email}",
"itemvar": f"{item.pk}"
}
)
assert response.context_data['form'].errors['itemvar'] == ["The selected product is not active."]
@pytest.mark.django_db
def test_edit_validations_inactive_variation(client, env):
item = env['item1']
wle = env['wle']
variation = env['variation']
wle.variation = variation
wle.save()
variation.active = False
variation.save()
client.login(email='dummy@dummy.dummy', password='dummy')
response = client.post(
'/control/event/dummy/dummy/waitinglist/%s/edit' % wle.id,
data={
"email": f"1_{wle.email}",
"itemvar": f"{item.pk}-{variation.pk}"
}
)
assert response.context_data['form'].errors['itemvar'] == ["The selected product is not active."]
@pytest.mark.django_db
def test_edit_voucher_send_out(client, env):
event = env['event']
item = env['item1']
wle = env['wle']
quota = Quota.objects.create(event=event, size=100)
quota.items.add(item)
client.login(email='dummy@dummy.dummy', password='dummy')
with scopes_disabled():
wle.send_voucher()
response = client.post(
'/control/event/dummy/dummy/waitinglist/%s/edit' % wle.id,
data={
"email": f"1_{wle.email}",
"itemvar": item.pk
},
follow=True
)
assert response.status_code == 404
@pytest.mark.django_db
def test_dashboard(client, env):
with scopes_disabled():
quota = Quota.objects.create(name="Test", size=2, event=env[0])
quota.items.add(env[3])
w = waitinglist_widgets(env[0])
quota = Quota.objects.create(name="Test", size=2, event=env['event'])
quota.items.add(env['item1'])
w = waitinglist_widgets(env['event'])
assert '1' in w[0]['content']
assert '5' in w[1]['content']