diff --git a/TODO.md b/TODO.md
index 9ba640e1..a5e52152 100644
--- a/TODO.md
+++ b/TODO.md
@@ -464,5 +464,3 @@ with open(file) as handler:
# Mark transaction process as executed should not override higher transaction states
# mailbox.addresses get_Queryset SQL contact @ with mailboxes and forwards
-
-# Remove membership fee when changing account.type
diff --git a/orchestra/contrib/accounts/admin.py b/orchestra/contrib/accounts/admin.py
index 6df66eab..3214ccd4 100644
--- a/orchestra/contrib/accounts/admin.py
+++ b/orchestra/contrib/accounts/admin.py
@@ -17,8 +17,10 @@ from django.utils.translation import ugettext_lazy as _
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
from orchestra.admin.actions import SendEmail
from orchestra.admin.utils import wrap_admin_view, admin_link, set_url_query
+from orchestra.contrib.services.settings import SERVICES_IGNORE_ACCOUNT_TYPE
from orchestra.core import services, accounts
from orchestra.forms import UserChangeForm
+from orchestra.utils.apps import isinstalled
from .actions import (list_contacts, service_report, delete_related_services, disable_selected,
enable_selected)
@@ -111,6 +113,26 @@ class AccountAdmin(ChangePasswordAdminMixin, auth.UserAdmin, ExtendedModelAdmin)
form.save_model(obj)
form.save_related(obj)
else:
+ if isinstalled('orchestra.contrib.orders') and isinstalled('orchestra.contrib.services'):
+ if 'type' in form.changed_data:
+ old_type = Account.objects.get(pk=obj.pk).type
+ new_type = form.cleaned_data['type']
+ context = {
+ 'from': old_type.lower(),
+ 'to': new_type.lower(),
+ 'url': reverse('admin:orders_order_changelist'),
+ }
+ msg = ''
+ if old_type in SERVICES_IGNORE_ACCOUNT_TYPE and new_type not in SERVICES_IGNORE_ACCOUNT_TYPE:
+ context['url'] += '?account=%i&ignore=1' % obj.pk
+ msg = _("Account type has been changed from %(from)s to %(to)s. "
+ "You may want to mark existing ignored orders as not ignored.")
+ elif old_type not in SERVICES_IGNORE_ACCOUNT_TYPE and new_type in SERVICES_IGNORE_ACCOUNT_TYPE:
+ context['url'] += '?account=%i&ignore=0' % obj.pk
+ msg = _("Account type has been changed from %(from)s to %(to)s. "
+ "You may want to ignore existing not ignored orders.")
+ if msg:
+ messages.warning(request, mark_safe(msg % context))
super(AccountAdmin, self).save_model(request, obj, form, change)
def get_change_view_actions(self, obj=None):
diff --git a/orchestra/contrib/mailboxes/admin.py b/orchestra/contrib/mailboxes/admin.py
index 7c45e3d8..d6965655 100644
--- a/orchestra/contrib/mailboxes/admin.py
+++ b/orchestra/contrib/mailboxes/admin.py
@@ -89,7 +89,6 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo
if cached_forwards is None:
cached_forwards = {}
qs = Address.objects.filter(forward__regex=r'(^|.*\s)[^@]+(\s.*|$)')
- qs = qs.select_related('domain')
qs = qs.annotate(email=Concat('name', V('@'), 'domain__name'))
qs = qs.values_list('id', 'email', 'forward')
for addr_id, email, mbox in qs:
diff --git a/orchestra/contrib/webapps/admin.py b/orchestra/contrib/webapps/admin.py
index 12e3aaee..0297ae8b 100644
--- a/orchestra/contrib/webapps/admin.py
+++ b/orchestra/contrib/webapps/admin.py
@@ -12,7 +12,7 @@ from orchestra.forms.widgets import DynamicHelpTextSelect
from orchestra.plugins.admin import SelectPluginAdminMixin, display_plugin_field
from orchestra.utils.html import get_on_site_link
-from .filters import HasWebsiteListFilter, PHPVersionListFilter
+from .filters import HasWebsiteListFilter, DetailListFilter
from .models import WebApp, WebAppOption
from .options import AppOption
from .types import AppType
@@ -53,7 +53,7 @@ class WebAppAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedModelAdmin)
list_display = (
'name', 'display_type', 'display_detail', 'display_websites', 'account_link'
)
- list_filter = ('type', HasWebsiteListFilter, PHPVersionListFilter)
+ list_filter = ('type', HasWebsiteListFilter, DetailListFilter)
inlines = [WebAppOptionInline]
readonly_fields = ('account_link',)
change_readonly_fields = ('name', 'type', 'display_websites')
diff --git a/orchestra/contrib/webapps/filters.py b/orchestra/contrib/webapps/filters.py
index fca86d6b..bbf1cce3 100644
--- a/orchestra/contrib/webapps/filters.py
+++ b/orchestra/contrib/webapps/filters.py
@@ -1,7 +1,7 @@
from django.contrib.admin import SimpleListFilter
from django.utils.translation import ugettext_lazy as _
-from . import settings
+from .types import AppType
class HasWebsiteListFilter(SimpleListFilter):
@@ -22,15 +22,28 @@ class HasWebsiteListFilter(SimpleListFilter):
return queryset
-class PHPVersionListFilter(SimpleListFilter):
- title = _("PHP version")
- parameter_name = 'php_version'
+class DetailListFilter(SimpleListFilter):
+ title = _("detail")
+ parameter_name = 'detail'
def lookups(self, request, model_admin):
- return settings.WEBAPPS_PHP_VERSIONS
+ ret = set()
+ lookup_map = {}
+ for apptype in AppType.get_plugins():
+ for field, values in apptype.get_detail_lookups().items():
+ for value in values:
+ lookup_map[value[0]] = field
+ ret.add(value)
+ self.lookup_map = lookup_map
+ return sorted(list(ret))
def queryset(self, request, queryset):
value = self.value()
if value:
- return queryset.filter(data__contains='"php_version":"%s"' % value)
+ try:
+ field = self.lookup_map[value]
+ except KeyError:
+ return queryset
+ else:
+ return queryset.filter(data__contains='"%s":"%s"' % (field, value))
return queryset
diff --git a/orchestra/contrib/webapps/types/__init__.py b/orchestra/contrib/webapps/types/__init__.py
index 4e07a2a9..33020d32 100644
--- a/orchestra/contrib/webapps/types/__init__.py
+++ b/orchestra/contrib/webapps/types/__init__.py
@@ -72,6 +72,11 @@ class AppType(plugins.Plugin, metaclass=plugins.PluginMount):
else:
yield (group, [(op.name, op.verbose_name) for op in options])
+ @classmethod
+ def get_detail_lookups(cls):
+ """ {'field_name': (('opt1', _("Option 1"),)} """
+ return {}
+
def get_detail(self):
return ''
diff --git a/orchestra/contrib/webapps/types/php.py b/orchestra/contrib/webapps/types/php.py
index 5764f276..8c1e6522 100644
--- a/orchestra/contrib/webapps/types/php.py
+++ b/orchestra/contrib/webapps/types/php.py
@@ -59,6 +59,12 @@ class PHPApp(AppType):
def get_detail(self):
return self.instance.data.get('php_version', '')
+ @classmethod
+ def get_detail_lookups(cls):
+ return {
+ 'php_version': settings.WEBAPPS_PHP_VERSIONS,
+ }
+
@cached
def get_options(self, merge=settings.WEBAPPS_MERGE_PHP_WEBAPPS):
""" adapter to webapp.get_options that performs merging of PHP options """
diff --git a/orchestra/contrib/webapps/types/python.py b/orchestra/contrib/webapps/types/python.py
index d515f777..ec9984e4 100644
--- a/orchestra/contrib/webapps/types/python.py
+++ b/orchestra/contrib/webapps/types/python.py
@@ -40,6 +40,12 @@ class PythonApp(AppType):
option_groups = (AppOption.FILESYSTEM, AppOption.PROCESS)
icon = 'orchestra/icons/apps/Python.png'
+ @classmethod
+ def get_detail_lookups(cls):
+ return {
+ 'python_version': settings.WEBAPPS_PYTHON_VERSIONS,
+ }
+
def get_directive(self):
context = self.get_directive_context()
return ('uwsgi', settings.WEBAPPS_UWSGI_SOCKET % context)