Merge pull request #1896 from normanjaeckel/AgendaNumbering
Fixed agenda numbering. Fixed #1892.
This commit is contained in:
commit
741cae028c
@ -21,13 +21,10 @@ class ItemManager(models.Manager):
|
|||||||
Customized model manager with special methods for agenda tree and
|
Customized model manager with special methods for agenda tree and
|
||||||
numbering.
|
numbering.
|
||||||
"""
|
"""
|
||||||
def get_only_agenda_items(self, queryset=None):
|
def get_only_agenda_items(self):
|
||||||
"""
|
"""
|
||||||
Generator, which yields only agenda items. Skips hidden items.
|
Generator, which yields only agenda items. Skips hidden items.
|
||||||
"""
|
"""
|
||||||
if queryset is None:
|
|
||||||
queryset = self.all()
|
|
||||||
|
|
||||||
# Do not execute item.is_hidden() because this would create a lot of db queries
|
# Do not execute item.is_hidden() because this would create a lot of db queries
|
||||||
root_items, item_children = self.get_root_and_children(only_agenda_items=True)
|
root_items, item_children = self.get_root_and_children(only_agenda_items=True)
|
||||||
|
|
||||||
@ -38,6 +35,29 @@ class ItemManager(models.Manager):
|
|||||||
for item in items:
|
for item in items:
|
||||||
yield item
|
yield item
|
||||||
yield from yield_items(item_children[item.pk])
|
yield from yield_items(item_children[item.pk])
|
||||||
|
|
||||||
|
yield from yield_items(root_items)
|
||||||
|
|
||||||
|
def get_only_hidden_items(self):
|
||||||
|
"""
|
||||||
|
Generator, which yields only hidden items, that means only items
|
||||||
|
which type is HIDDEN_ITEM or which are children of hidden items.
|
||||||
|
"""
|
||||||
|
# Do not execute item.is_hidden() because this would create a lot of db queries
|
||||||
|
root_items, item_children = self.get_root_and_children(only_agenda_items=False)
|
||||||
|
|
||||||
|
def yield_items(items, parent_is_hidden=False):
|
||||||
|
"""
|
||||||
|
Generator that yields a list of items and their children.
|
||||||
|
"""
|
||||||
|
for item in items:
|
||||||
|
if parent_is_hidden or item.type == item.HIDDEN_ITEM:
|
||||||
|
item_is_hidden = True
|
||||||
|
yield item
|
||||||
|
else:
|
||||||
|
item_is_hidden = False
|
||||||
|
yield from yield_items(item_children[item.pk], parent_is_hidden=item_is_hidden)
|
||||||
|
|
||||||
yield from yield_items(root_items)
|
yield from yield_items(root_items)
|
||||||
|
|
||||||
def get_root_and_children(self, only_agenda_items=False):
|
def get_root_and_children(self, only_agenda_items=False):
|
||||||
@ -45,7 +65,8 @@ class ItemManager(models.Manager):
|
|||||||
Returns a list with all root items and a dictonary where the key is an
|
Returns a list with all root items and a dictonary where the key is an
|
||||||
item pk and the value is a list with all children of the item.
|
item pk and the value is a list with all children of the item.
|
||||||
|
|
||||||
If only_agenda_items is True, the tree hides HIDDEN_ITEM.
|
If only_agenda_items is True, the tree hides items with type
|
||||||
|
HIDDEN_ITEM and all of their children.
|
||||||
"""
|
"""
|
||||||
queryset = self.order_by('weight')
|
queryset = self.order_by('weight')
|
||||||
item_children = defaultdict(list)
|
item_children = defaultdict(list)
|
||||||
@ -57,7 +78,6 @@ class ItemManager(models.Manager):
|
|||||||
item_children[item.parent_id].append(item)
|
item_children[item.parent_id].append(item)
|
||||||
else:
|
else:
|
||||||
root_items.append(item)
|
root_items.append(item)
|
||||||
|
|
||||||
return root_items, item_children
|
return root_items, item_children
|
||||||
|
|
||||||
def get_tree(self, only_agenda_items=False, include_content=False):
|
def get_tree(self, only_agenda_items=False, include_content=False):
|
||||||
@ -66,7 +86,8 @@ class ItemManager(models.Manager):
|
|||||||
and children, where id is the id of one agenda item and children is a
|
and children, where id is the id of one agenda item and children is a
|
||||||
generator that yields dictonaries like the one discribed.
|
generator that yields dictonaries like the one discribed.
|
||||||
|
|
||||||
If only_agenda_items is True, the tree hides HIDDEN_ITEM.
|
If only_agenda_items is True, the tree hides items with type
|
||||||
|
HIDDEN_ITEM and all of their children.
|
||||||
|
|
||||||
If include_content is True, the yielded dictonaries have no key 'id'
|
If include_content is True, the yielded dictonaries have no key 'id'
|
||||||
but a key 'item' with the entire object.
|
but a key 'item' with the entire object.
|
||||||
@ -133,22 +154,31 @@ class ItemManager(models.Manager):
|
|||||||
"""
|
"""
|
||||||
def walk_tree(tree, number=None):
|
def walk_tree(tree, number=None):
|
||||||
for index, tree_element in enumerate(tree):
|
for index, tree_element in enumerate(tree):
|
||||||
|
# Calculate number of visable agenda items.
|
||||||
if numeral_system == 'roman' and number is None:
|
if numeral_system == 'roman' and number is None:
|
||||||
item_number = to_roman(index + 1)
|
item_number = to_roman(index + 1)
|
||||||
else:
|
else:
|
||||||
item_number = str(index + 1)
|
item_number = str(index + 1)
|
||||||
if number is not None:
|
if number is not None:
|
||||||
item_number = '.'.join((number, item_number))
|
item_number = '.'.join((number, item_number))
|
||||||
|
# Add prefix.
|
||||||
if config['agenda_number_prefix']:
|
if config['agenda_number_prefix']:
|
||||||
item_number_tmp = "%s %s" % (config['agenda_number_prefix'], item_number)
|
item_number_tmp = "%s %s" % (config['agenda_number_prefix'], item_number)
|
||||||
else:
|
else:
|
||||||
item_number_tmp = item_number
|
item_number_tmp = item_number
|
||||||
|
# Save the new value and go down the tree.
|
||||||
tree_element['item'].item_number = item_number_tmp
|
tree_element['item'].item_number = item_number_tmp
|
||||||
tree_element['item'].save()
|
tree_element['item'].save()
|
||||||
walk_tree(tree_element['children'], item_number)
|
walk_tree(tree_element['children'], item_number)
|
||||||
|
|
||||||
|
# Start numbering visable agenda items.
|
||||||
walk_tree(self.get_tree(only_agenda_items=True, include_content=True))
|
walk_tree(self.get_tree(only_agenda_items=True, include_content=True))
|
||||||
|
|
||||||
|
# Reset number of hidden items.
|
||||||
|
for item in self.get_only_hidden_items():
|
||||||
|
item.item_number = ''
|
||||||
|
item.save()
|
||||||
|
|
||||||
|
|
||||||
class Item(RESTModelMixin, models.Model):
|
class Item(RESTModelMixin, models.Model):
|
||||||
"""
|
"""
|
||||||
|
@ -288,3 +288,18 @@ class Numbering(TestCase):
|
|||||||
self.assertEqual(Item.objects.get(pk=self.item_2.pk).item_number, '')
|
self.assertEqual(Item.objects.get(pk=self.item_2.pk).item_number, '')
|
||||||
self.assertEqual(Item.objects.get(pk=self.item_2_1.pk).item_number, '')
|
self.assertEqual(Item.objects.get(pk=self.item_2_1.pk).item_number, '')
|
||||||
self.assertEqual(Item.objects.get(pk=self.item_3.pk).item_number, '2')
|
self.assertEqual(Item.objects.get(pk=self.item_3.pk).item_number, '2')
|
||||||
|
|
||||||
|
def test_reset_numbering_with_hidden_item(self):
|
||||||
|
self.item_2.item_number = 'test_number_Cieghae6ied5ool4hiem'
|
||||||
|
self.item_2.type = Item.HIDDEN_ITEM
|
||||||
|
self.item_2.save()
|
||||||
|
self.item_2_1.item_number = 'test_number_roQueTohg7fe1Is7aemu'
|
||||||
|
self.item_2_1.save()
|
||||||
|
|
||||||
|
response = self.client.post(reverse('item-numbering'))
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertEqual(Item.objects.get(pk=self.item_1.pk).item_number, '1')
|
||||||
|
self.assertEqual(Item.objects.get(pk=self.item_2.pk).item_number, '')
|
||||||
|
self.assertEqual(Item.objects.get(pk=self.item_2_1.pk).item_number, '')
|
||||||
|
self.assertEqual(Item.objects.get(pk=self.item_3.pk).item_number, '2')
|
||||||
|
Loading…
Reference in New Issue
Block a user