forked from CGM_Public/pretix_original
Add Item.get_all_variations and a test for it
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
from itertools import product
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
|
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
|
||||||
@@ -462,6 +464,39 @@ class Item(models.Model):
|
|||||||
self.active = False
|
self.active = False
|
||||||
return super().save()
|
return super().save()
|
||||||
|
|
||||||
|
def get_all_variations(self):
|
||||||
|
"""
|
||||||
|
This method returns a list containing all variations of this
|
||||||
|
item, where n is the number of properties connected to this
|
||||||
|
item. The list contains either tupels of PropertyValue objects
|
||||||
|
or ItemVariation objects. The returned list is assumed not to
|
||||||
|
be in any order.
|
||||||
|
"""
|
||||||
|
all_variations = self.variations.all().prefetch_related("values")
|
||||||
|
all_properties = self.properties.all().prefetch_related("values")
|
||||||
|
variations_cache = {}
|
||||||
|
for var in all_variations:
|
||||||
|
key = []
|
||||||
|
for v in var.values.all():
|
||||||
|
key.append((v.prop.pk, v.pk))
|
||||||
|
key = hash(tuple(sorted(key)))
|
||||||
|
variations_cache[key] = var
|
||||||
|
|
||||||
|
result = []
|
||||||
|
for comb in product(*[prop.values.all() for prop in all_properties]):
|
||||||
|
if len(comb) == 0:
|
||||||
|
continue
|
||||||
|
key = []
|
||||||
|
for v in comb:
|
||||||
|
key.append((v.prop.pk, v.pk))
|
||||||
|
key = hash(tuple(sorted(key)))
|
||||||
|
if key in variations_cache:
|
||||||
|
result.append(variations_cache[key])
|
||||||
|
else:
|
||||||
|
result.append(comb)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Item")
|
verbose_name = _("Item")
|
||||||
verbose_name_plural = _("Items")
|
verbose_name_plural = _("Items")
|
||||||
|
|||||||
@@ -1,3 +1,92 @@
|
|||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
from django.utils.timezone import now
|
||||||
|
|
||||||
# Create your tests here.
|
from tixlbase.models import (
|
||||||
|
Event, Organizer, Item, ItemVariation,
|
||||||
|
Property, PropertyValue
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ItemVariationsTest(TestCase):
|
||||||
|
"""
|
||||||
|
This test case tests various methods around the properties /
|
||||||
|
variations concept.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
o = Organizer.objects.create(name='Dummy', slug='dummy')
|
||||||
|
e = Event.objects.create(
|
||||||
|
organizer=o, name='Dummy', slug='dummy',
|
||||||
|
date_from=now(),
|
||||||
|
)
|
||||||
|
p = Property.objects.create(event=e, name='Size')
|
||||||
|
PropertyValue.objects.create(prop=p, value='S')
|
||||||
|
PropertyValue.objects.create(prop=p, value='M')
|
||||||
|
PropertyValue.objects.create(prop=p, value='L')
|
||||||
|
p = Property.objects.create(event=e, name='Color')
|
||||||
|
PropertyValue.objects.create(prop=p, value='black')
|
||||||
|
PropertyValue.objects.create(prop=p, value='blue')
|
||||||
|
|
||||||
|
def test_get_all_variations(self):
|
||||||
|
e = Event.objects.get(name='Dummy', organizer__name='Dummy')
|
||||||
|
i = Item.objects.create(event=e, name='Dummy')
|
||||||
|
|
||||||
|
# No properties available
|
||||||
|
v = i.get_all_variations()
|
||||||
|
self.assertEqual(len(v), 0)
|
||||||
|
|
||||||
|
# One property, no variations
|
||||||
|
p = Property.objects.get(event=e, name='Size')
|
||||||
|
i.properties.add(p)
|
||||||
|
v = i.get_all_variations()
|
||||||
|
self.assertIs(type(v), list)
|
||||||
|
self.assertEqual(len(v), 3)
|
||||||
|
values = []
|
||||||
|
for var in v:
|
||||||
|
self.assertIs(type(var), tuple)
|
||||||
|
self.assertIs(type(var[0]), PropertyValue)
|
||||||
|
values.append(var[0].value)
|
||||||
|
self.assertEqual(sorted(values), sorted(['S', 'M', 'L']))
|
||||||
|
|
||||||
|
# One property, one variation
|
||||||
|
iv = ItemVariation.objects.create(item=i)
|
||||||
|
iv.values.add(PropertyValue.objects.get(prop=p, value='S'))
|
||||||
|
v = i.get_all_variations()
|
||||||
|
self.assertIs(type(v), list)
|
||||||
|
self.assertEqual(len(v), 3)
|
||||||
|
values = []
|
||||||
|
for var in v:
|
||||||
|
if type(var) == ItemVariation:
|
||||||
|
self.assertEqual(iv.pk, var.pk)
|
||||||
|
values.append(iv.values.all()[0].value)
|
||||||
|
elif type(var) == tuple:
|
||||||
|
self.assertIs(type(var[0]), PropertyValue)
|
||||||
|
values.append(var[0].value)
|
||||||
|
self.assertEqual(sorted(values), sorted(['S', 'M', 'L']))
|
||||||
|
|
||||||
|
# Two properties, one variation
|
||||||
|
p2 = Property.objects.get(event=e, name='Color')
|
||||||
|
i.properties.add(p2)
|
||||||
|
iv.values.add(PropertyValue.objects.get(prop=p2, value='black'))
|
||||||
|
v = i.get_all_variations()
|
||||||
|
self.assertIs(type(v), list)
|
||||||
|
self.assertEqual(len(v), 6)
|
||||||
|
values = []
|
||||||
|
num_variations = 0
|
||||||
|
for var in v:
|
||||||
|
if type(var) == ItemVariation:
|
||||||
|
self.assertEqual(iv.pk, var.pk)
|
||||||
|
values.append(sorted([ivv.value for ivv in iv.values.all()]))
|
||||||
|
self.assertEqual(sorted([ivv.value for ivv in iv.values.all()]), sorted(['S', 'black']))
|
||||||
|
num_variations += 1
|
||||||
|
elif type(var) == tuple:
|
||||||
|
values.append(sorted([pv.value for pv in var]))
|
||||||
|
self.assertEqual(sorted(values), sorted([
|
||||||
|
['S', 'black'],
|
||||||
|
['S', 'blue'],
|
||||||
|
['M', 'black'],
|
||||||
|
['M', 'blue'],
|
||||||
|
['L', 'black'],
|
||||||
|
['L', 'blue'],
|
||||||
|
]))
|
||||||
|
self.assertEqual(num_variations, 1)
|
||||||
|
|||||||
Reference in New Issue
Block a user