Add Item.get_all_variations and a test for it

This commit is contained in:
Raphael Michel
2014-09-27 13:58:26 +02:00
parent 675688d5df
commit d59e203299
2 changed files with 125 additions and 1 deletions

View File

@@ -1,3 +1,5 @@
from itertools import product
from django.db import models
from django.conf import settings
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
@@ -462,6 +464,39 @@ class Item(models.Model):
self.active = False
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:
verbose_name = _("Item")
verbose_name_plural = _("Items")

View File

@@ -1,3 +1,92 @@
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)