From 903ea9da30531d508bac20e42b8c2632698da7f2 Mon Sep 17 00:00:00 2001 From: Serghei Mihai Date: Wed, 30 Mar 2016 14:29:17 +0200 Subject: [PATCH 2/5] lingo: add generic invoice cell with "category" filter (#10483) Migrate data from existing items cell to the new one --- combo/apps/lingo/migrations/0018_invoicescell.py | 38 +++++++++++ ...9_manual_migrate_invoice_cells_20160330_2154.py | 76 ++++++++++++++++++++++ combo/apps/lingo/models.py | 62 ++++++++++++++++++ tests/test_lingo_cells.py | 16 ++++- 4 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 combo/apps/lingo/migrations/0018_invoicescell.py create mode 100644 combo/apps/lingo/migrations/0019_manual_migrate_invoice_cells_20160330_2154.py diff --git a/combo/apps/lingo/migrations/0018_invoicescell.py b/combo/apps/lingo/migrations/0018_invoicescell.py new file mode 100644 index 0000000..5e910f8 --- /dev/null +++ b/combo/apps/lingo/migrations/0018_invoicescell.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +import ckeditor.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0001_initial'), + ('data', '0016_feedcell_limit'), + ('lingo', '0017_auto_20160327_0831'), + ] + + operations = [ + migrations.CreateModel( + name='InvoicesCell', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('placeholder', models.CharField(max_length=20)), + ('order', models.PositiveIntegerField()), + ('slug', models.SlugField(verbose_name='Slug', blank=True)), + ('public', models.BooleanField(default=True, verbose_name='Public')), + ('restricted_to_unlogged', models.BooleanField(default=False, verbose_name='Restrict to unlogged users')), + ('regie', models.CharField(max_length=50, verbose_name='Regie', blank=True)), + ('title', models.CharField(max_length=200, verbose_name='Title', blank=True)), + ('text', ckeditor.fields.RichTextField(null=True, verbose_name='Text', blank=True)), + ('category', models.CharField(default=b'active', max_length=128, verbose_name='Category', choices=[(b'active', 'Active'), (b'past', 'Past')])), + ('groups', models.ManyToManyField(to='auth.Group', verbose_name='Groups', blank=True)), + ('page', models.ForeignKey(to='data.Page')), + ], + options={ + 'verbose_name': 'Invoices', + }, + bases=(models.Model,), + ), + ] diff --git a/combo/apps/lingo/migrations/0019_manual_migrate_invoice_cells_20160330_2154.py b/combo/apps/lingo/migrations/0019_manual_migrate_invoice_cells_20160330_2154.py new file mode 100644 index 0000000..06a3098 --- /dev/null +++ b/combo/apps/lingo/migrations/0019_manual_migrate_invoice_cells_20160330_2154.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + +def migrate_activeitems_cells(apps, schema_editor): + InvoicesCell = apps.get_model('lingo', 'InvoicesCell') + Page = apps.get_model('data', 'Page') + ActiveItems = apps.get_model('lingo', 'ActiveItems') + for cell in ActiveItems.objects.all(): + page = Page.objects.get(pk=cell.page_id) + InvoicesCell.objects.get_or_create(order=cell.order, + page=page, placeholder=cell.placeholder, + public=cell.public, regie=cell.regie, + restricted_to_unlogged=cell.restricted_to_unlogged, + slug=cell.slug, text=cell.text, title=cell.title, + category='active' + ) + cell.delete() + +def migrate_itemshistory_cells(apps, schema_editor): + InvoicesCell = apps.get_model('lingo', 'InvoicesCell') + Page = apps.get_model('data', 'Page') + ItemsHistory = apps.get_model('lingo', 'ItemsHistory') + for cell in ItemsHistory.objects.all(): + page = Page.objects.get(pk=cell.page_id) + InvoicesCell.objects.get_or_create(order=cell.order, + page=page, placeholder=cell.placeholder, + public=cell.public, regie=cell.regie, + restricted_to_unlogged=cell.restricted_to_unlogged, + slug=cell.slug, text=cell.text, title=cell.title, + category='past' + ) + cell.delete() + +def restore_activeitems_cells(apps, schema_editor): + InvoicesCell = apps.get_model('lingo', 'InvoicesCell') + Page = apps.get_model('data', 'Page') + ActiveItems = apps.get_model('lingo', 'ActiveItems') + for cell in InvoicesCell.objects.filter(category='active'): + page = Page.objects.get(pk=cell.page_id) + ActiveItems.objects.get_or_create(order=cell.order, + page=page, placeholder=cell.placeholder, + public=cell.public, regie=cell.regie, + restricted_to_unlogged=cell.restricted_to_unlogged, + slug=cell.slug, text=cell.text, title=cell.title + ) + cell.delete() + +def restore_itemshistory_cells(apps, schema_editor): + InvoicesCell = apps.get_model('lingo', 'InvoicesCell') + Page = apps.get_model('data', 'Page') + ItemsHistory = apps.get_model('lingo', 'HistoryItems') + for cell in InvoicesCell.objects.filter(category='past'): + page = Page.objects.get(pk=cell.page_id) + ItemsHistory.objects.get_or_create(order=cell.order, + page=page, placeholder=cell.placeholder, + public=cell.public, regie=cell.regie, + restricted_to_unlogged=cell.restricted_to_unlogged, + slug=cell.slug, text=cell.text, title=cell.title + ) + cell.delete() + + +class Migration(migrations.Migration): + + dependencies = [ + ('lingo', '0018_invoicescell'), + ] + + operations = [ + migrations.RunPython(migrate_activeitems_cells, + restore_activeitems_cells), + migrations.RunPython(migrate_itemshistory_cells, + restore_itemshistory_cells) + ] diff --git a/combo/apps/lingo/models.py b/combo/apps/lingo/models.py index 771ad13..c05879f 100644 --- a/combo/apps/lingo/models.py +++ b/combo/apps/lingo/models.py @@ -55,6 +55,11 @@ SERVICES = [ (eopayment.PAYZEN, _('PayZen')), ] +INVOICE_CATEGORIES = ( + ('active', _('Active')), + ('past', _('Past')) +) + def build_remote_item(data, regie): return RemoteItem(id=data.get('id'), regie=regie, creation_date=data['created'], @@ -358,6 +363,63 @@ class LingoBasketLinkCell(CellBase): return basket_template.render(context) +@register_cell_class +class InvoicesCell(CellBase): + regie = models.CharField(_('Regie'), max_length=50, blank=True) + title = models.CharField(_('Title'), max_length=200, blank=True) + text = RichTextField(_('Text'), blank=True, null=True) + category = models.CharField(_('Category'), max_length=128, + choices=INVOICE_CATEGORIES, default='active') + + user_dependant = True + template_name = 'lingo/combo/items.html' + + class Meta: + verbose_name = _('Invoices') + + class Media: + js = ('xstatic/jquery-ui.min.js', 'js/gadjo.js',) + css = {'all': ('xstatic/themes/smoothness/jquery-ui.min.css', )} + + @classmethod + def is_enabled(cls): + return Regie.objects.count() > 0 + + def get_default_form_class(self): + fields = ['title', 'category', 'text'] + widgets = {} + if Regie.objects.count() > 1: + regies = [('', _('All'))] + regies.extend([(r.slug, r.label) for r in Regie.objects.all()]) + widgets['regie'] = Select(choices=regies) + fields.insert(0, 'regie') + return model_forms.modelform_factory(self.__class__, fields=fields, widgets=widgets) + + def get_regies(self): + if self.regie: + return [Regie.objects.get(slug=self.regie)] + return Regie.objects.all() + + def get_cell_extra_context(self, context): + ctx = {'title': self.title, 'text': self.text} + invoices = [] + for r in self.get_regies(): + if self.category == 'active': + invoices.extend(r.get_items(self.context)) + elif self.category == 'past': + invoices.extend(r.get_past_items(self.context)) + # sort items by creation date + invoices.sort(key=lambda i: i.creation_date, reverse=True) + ctx.update({'items': invoices}) + return ctx + + def render(self, context): + self.context = context + if not context.get('synchronous'): + raise NothingInCacheException() + return super(InvoicesCell, self).render(context) + + class Items(CellBase): regie = models.CharField(_('Regie'), max_length=50, blank=True) title = models.CharField(_('Title'), max_length=200, blank=True) diff --git a/tests/test_lingo_cells.py b/tests/test_lingo_cells.py index 8c9d83d..369be8f 100644 --- a/tests/test_lingo_cells.py +++ b/tests/test_lingo_cells.py @@ -6,7 +6,8 @@ from django.template import Context from django.utils import timezone from combo.data.models import Page -from combo.apps.lingo.models import Regie, BasketItem, Transaction +from combo.utils import NothingInCacheException +from combo.apps.lingo.models import Regie, BasketItem, Transaction, InvoicesCell from combo.apps.lingo.models import LingoBasketCell, LingoRecentTransactionsCell pytestmark = pytest.mark.django_db @@ -68,3 +69,16 @@ def test_basket_cell(regie, user): content = cell.render(context) assert '12345' in content + +def test_invoices_cell(regie, user): + page = Page(title='invoices', slug='test_invoices_cell', template_name='standard') + page.save() + cell = InvoicesCell(page=page, placeholder='content', order=0, + regie=regie.slug, title='Active Invoices', category='active') + context = Context({'request': RequestFactory().get('/')}) + context['request'].user = user + assert cell.is_relevant(context) is True + with pytest.raises(NothingInCacheException): + cell.render(context) + context['synchronous'] = True + assert 'Active Invoices' in cell.render(context) -- 2.8.0.rc3