diff --git a/combo/apps/lingo/migrations/0018_invoicescell.py b/combo/apps/lingo/migrations/0018_invoicescell.py deleted file mode 100644 index e5e71e99..00000000 --- a/combo/apps/lingo/migrations/0018_invoicescell.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations -import multiselectfield.db.fields -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)), - ('categories', multiselectfield.db.fields.MultiSelectField(max_length=11, verbose_name='Categories', 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_20160404_1356.py b/combo/apps/lingo/migrations/0019_manual_migrate_invoice_cells_20160404_1356.py deleted file mode 100644 index 266f8e4c..00000000 --- a/combo/apps/lingo/migrations/0019_manual_migrate_invoice_cells_20160404_1356.py +++ /dev/null @@ -1,76 +0,0 @@ -# -*- 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, - categories='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, - categories='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(categories__contains='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', 'ItemsHistory') - for cell in InvoicesCell.objects.filter(categories__contains='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 a1e8c129..771ad13a 100644 --- a/combo/apps/lingo/models.py +++ b/combo/apps/lingo/models.py @@ -36,15 +36,12 @@ from django.core.exceptions import PermissionDenied from django.utils.http import urlencode from ckeditor.fields import RichTextField -from multiselectfield import MultiSelectField from combo.data.models import CellBase from combo.data.library import register_cell_class from combo.utils import NothingInCacheException, sign_url EXPIRED = 9999 -ACTIVE_ITEMS = 'active' -PAST_ITEMS = 'past' SERVICES = [ @@ -58,11 +55,6 @@ SERVICES = [ (eopayment.PAYZEN, _('PayZen')), ] -INVOICE_CATEGORIES = ( - (ACTIVE_ITEMS, _('Active')), - (PAST_ITEMS, _('Past')) -) - def build_remote_item(data, regie): return RemoteItem(id=data.get('id'), regie=regie, creation_date=data['created'], @@ -366,62 +358,6 @@ 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) - categories = MultiSelectField(_('Categories'), choices=INVOICE_CATEGORIES) - - 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', 'categories', '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 ACTIVE_ITEMS in self.categories: - invoices.extend(r.get_items(self.context)) - if PAST_ITEMS in self.categories: - 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/combo/fields.py b/combo/fields.py deleted file mode 100644 index e0d3fa3d..00000000 --- a/combo/fields.py +++ /dev/null @@ -1,143 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This is a modified copy of https://github.com/goinnn/django-multiselectfield -# -# Copyright (c) 2012 by Pablo Martín -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this programe. If not, see . - -import sys - -import django - -from django.db import models -from django.core import validators -from django import forms -from django.utils.text import capfirst -from django.core import exceptions - -if sys.version_info[0] == 2: - string_type = unicode -else: - string_type = str - -# Code from six egg https://bitbucket.org/gutworth/six/src/a3641cb211cc360848f1e2dd92e9ae6cd1de55dd/six.py?at=default - -def get_max_length(choices, max_length, default=200): - if max_length is None: - if choices: - return len(','.join([string_type(key) for key, label in choices])) - else: - return default - return max_length - - -class MaxValueMultiFieldValidator(validators.MaxLengthValidator): - clean = lambda self, x: len(','.join(x)) - code = 'max_multifield_value' - - -class MultiSelectFormField(forms.MultipleChoiceField): - widget = forms.CheckboxSelectMultiple - - def __init__(self, *args, **kwargs): - self.max_choices = kwargs.pop('max_choices', None) - self.max_length = kwargs.pop('max_length', None) - super(MultiSelectFormField, self).__init__(*args, **kwargs) - self.max_length = get_max_length(self.choices, self.max_length) - self.validators.append(MaxValueMultiFieldValidator(self.max_length)) - - -class MultiSelectField(models.CharField): - """ Choice values can not contain commas. """ - - __metaclass__ = models.SubfieldBase - - def __init__(self, *args, **kwargs): - self.max_choices = kwargs.pop('max_choices', None) - super(MultiSelectField, self).__init__(*args, **kwargs) - self.max_length = get_max_length(self.choices, self.max_length) - self.validators[0] = MaxValueMultiFieldValidator(self.max_length) - - @property - def flatchoices(self): - return None - - def get_choices_default(self): - return self.get_choices(include_blank=False) - - def get_choices_selected(self, arr_choices): - choices_selected = [] - for choice_selected in arr_choices: - choices_selected.append(string_type(choice_selected[0])) - return choices_selected - - def value_to_string(self, obj): - value = self._get_val_from_obj(obj) - return self.get_prep_value(value) - - def validate(self, value, model_instance): - arr_choices = self.get_choices_selected(self.get_choices_default()) - for opt_select in value: - if (opt_select not in arr_choices): - raise exceptions.ValidationError(self.error_messages['invalid_choice'] % value) - - def get_default(self): - default = super(MultiSelectField, self).get_default() - if isinstance(default, int): - default = string_type(default) - return default - - def formfield(self, **kwargs): - defaults = {'required': not self.blank, - 'label': capfirst(self.verbose_name), - 'help_text': self.help_text, - 'choices': self.choices, - 'max_length': self.max_length, - 'max_choices': self.max_choices} - if self.has_default(): - defaults['initial'] = self.get_default() - defaults.update(kwargs) - return MultiSelectFormField(**defaults) - - def get_prep_value(self, value): - return '' if value is None else ",".join(value) - - def to_python(self, value): - if value: - return value if isinstance(value, list) else value.split(',') - - def contribute_to_class(self, cls, name): - super(MultiSelectField, self).contribute_to_class(cls, name) - if self.choices: - def get_list(obj): - fieldname = name - choicedict = dict(self.choices) - display = [] - if getattr(obj, fieldname): - for value in getattr(obj, fieldname): - item_display = choicedict.get(value, None) - if item_display is None: - try: - item_display = choicedict.get(int(value), value) - except (ValueError, TypeError): - item_display = value - display.append(string_type(item_display)) - return display - - def get_display(obj): - return ", ".join(get_list(obj)) - - setattr(cls, 'get_%s_list' % self.name, get_list) - setattr(cls, 'get_%s_display' % self.name, get_display) diff --git a/combo/settings.py b/combo/settings.py index e04dae40..54163a74 100644 --- a/combo/settings.py +++ b/combo/settings.py @@ -70,7 +70,6 @@ INSTALLED_APPS = ( 'combo.apps.fargo', 'combo.apps.usersearch', 'xstatic.pkg.chartnew_js', - 'multiselectfield' ) INSTALLED_APPS = plugins.register_plugins_apps(INSTALLED_APPS) diff --git a/debian/control b/debian/control index 4ae584e4..81e19ab4 100644 --- a/debian/control +++ b/debian/control @@ -15,7 +15,6 @@ Depends: ${misc:Depends}, ${python:Depends}, python-feedparser, python-django-cmsplugin-blurp, python-xstatic-chartnew-js - python-django-multiselectfield Recommends: python-django-mellon Conflicts: python-lingo Description: Portal Management System (Python module) diff --git a/setup.py b/setup.py index e6aada61..e7ae6b5a 100644 --- a/setup.py +++ b/setup.py @@ -113,7 +113,6 @@ setup( 'XStatic-ChartNew.js', 'eopayment>=1.3', 'python-dateutil', - 'django-multiselectfield', ], zip_safe=False, cmdclass={ diff --git a/tests/test_lingo_cells.py b/tests/test_lingo_cells.py index 0848df41..8c9d83df 100644 --- a/tests/test_lingo_cells.py +++ b/tests/test_lingo_cells.py @@ -6,9 +6,7 @@ from django.template import Context from django.utils import timezone from combo.data.models import Page -from combo.utils import NothingInCacheException from combo.apps.lingo.models import Regie, BasketItem, Transaction -from combo.apps.lingo.models import ACTIVE_ITEMS, InvoicesCell from combo.apps.lingo.models import LingoBasketCell, LingoRecentTransactionsCell pytestmark = pytest.mark.django_db @@ -70,16 +68,3 @@ 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', categories=ACTIVE_ITEMS) - 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)