From 9f63fbbb5dd7ed0e422d1abc0f18c1a325cd48e2 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 18 Jan 2015 13:22:06 +0100 Subject: [PATCH 01/10] Add new hostingpackages app - implement models for hosting packages, hosting options and customer specific variants - implement admin interface - add documentation --- gnuviechadmin/hostingpackages/__init__.py | 5 + gnuviechadmin/hostingpackages/admin.py | 121 +++++++++ gnuviechadmin/hostingpackages/apps.py | 18 ++ .../locale/de/LC_MESSAGES/django.po | 192 ++++++++++++++ .../migrations/0001_initial.py | 214 +++++++++++++++ .../0001_squashed_0005_auto_20150118_1303.py | 245 ++++++++++++++++++ .../migrations/0002_auto_20150118_1149.py | 38 +++ .../migrations/0002_auto_20150118_1319.py | 18 ++ .../migrations/0003_auto_20150118_1221.py | 24 ++ .../0004_customerhostingpackage_osuser.py | 21 ++ .../migrations/0005_auto_20150118_1303.py | 20 ++ .../hostingpackages/migrations/__init__.py | 0 gnuviechadmin/hostingpackages/models.py | 242 +++++++++++++++++ 13 files changed, 1158 insertions(+) create mode 100644 gnuviechadmin/hostingpackages/__init__.py create mode 100644 gnuviechadmin/hostingpackages/admin.py create mode 100644 gnuviechadmin/hostingpackages/apps.py create mode 100644 gnuviechadmin/hostingpackages/locale/de/LC_MESSAGES/django.po create mode 100644 gnuviechadmin/hostingpackages/migrations/0001_initial.py create mode 100644 gnuviechadmin/hostingpackages/migrations/0001_squashed_0005_auto_20150118_1303.py create mode 100644 gnuviechadmin/hostingpackages/migrations/0002_auto_20150118_1149.py create mode 100644 gnuviechadmin/hostingpackages/migrations/0002_auto_20150118_1319.py create mode 100644 gnuviechadmin/hostingpackages/migrations/0003_auto_20150118_1221.py create mode 100644 gnuviechadmin/hostingpackages/migrations/0004_customerhostingpackage_osuser.py create mode 100644 gnuviechadmin/hostingpackages/migrations/0005_auto_20150118_1303.py create mode 100644 gnuviechadmin/hostingpackages/migrations/__init__.py create mode 100644 gnuviechadmin/hostingpackages/models.py diff --git a/gnuviechadmin/hostingpackages/__init__.py b/gnuviechadmin/hostingpackages/__init__.py new file mode 100644 index 0000000..e32bbf1 --- /dev/null +++ b/gnuviechadmin/hostingpackages/__init__.py @@ -0,0 +1,5 @@ +""" +This app takes care of hosting packages. + +""" +default_app_config = 'hostingpackages.apps.HostingPackagesAppConfig' diff --git a/gnuviechadmin/hostingpackages/admin.py b/gnuviechadmin/hostingpackages/admin.py new file mode 100644 index 0000000..a399bdb --- /dev/null +++ b/gnuviechadmin/hostingpackages/admin.py @@ -0,0 +1,121 @@ +""" +This module contains the admin site interface for hosting packages. + +""" +from __future__ import absolute_import, unicode_literals + +from django import forms +from django.contrib import admin + +from .models import ( + CustomerHostingPackage, + CustomerDiskSpaceOption, + CustomerUserDatabaseOption, + CustomerMailboxOption, + DiskSpaceOption, + HostingPackageTemplate, + MailboxOption, + UserDatabaseOption, +) + + +class CustomerHostingPackageCreateForm(forms.ModelForm): + class Meta: + model = CustomerHostingPackage + fields = ['customer', 'template', 'name'] + + def save(self, **kwargs): + """ + Save the customer hosting package. + + :param kwargs: keyword arguments passed to create method + :return: customer hosting package instance + :rtype: :py:class:`hostingpackages.models.CustomerHostingPackage` + + """ + hostinpackages = CustomerHostingPackage.objects.create_from_template( + customer=self.cleaned_data['customer'], + template=self.cleaned_data['template'], + name=self.cleaned_data['name'], + **kwargs) + return hostinpackages + + def save_m2m(self): + pass + + +class CustomerDiskSpaceOptionInline(admin.TabularInline): + model = CustomerDiskSpaceOption + extra = 0 + + +class CustomerMailboxOptionInline(admin.TabularInline): + model = CustomerMailboxOption + extra = 0 + + +class CustomerUserDatabaseOptionInline(admin.TabularInline): + model = CustomerUserDatabaseOption + extra = 0 + + +class CustomerHostingPackageAdmin(admin.ModelAdmin): + add_form = CustomerHostingPackageCreateForm + add_fieldsets = ( + (None, { + 'fields': ('customer', 'template', 'name') + }), + ) + + inlines = [ + CustomerDiskSpaceOptionInline, + CustomerMailboxOptionInline, + CustomerUserDatabaseOptionInline, + ] + + def get_form(self, request, obj=None, **kwargs): + """ + Use special form for customer hosting package creation. + + :param request: the current HTTP request + :param obj: either a :py:class:`CustomerHostingPackage + ` instance or None + for a new customer hosting package + :param kwargs: keyword arguments to be passed to + :py:meth:`django.contrib.admin.ModelAdmin.get_form` + :return: form instance + + """ + defaults = {} + if obj is None: + defaults.update({ + 'form': self.add_form, + 'fields': admin.options.flatten_fieldsets(self.add_fieldsets), + }) + defaults.update(kwargs) + return super(CustomerHostingPackageAdmin, self).get_form( + request, obj, **defaults) + + def get_readonly_fields(self, request, obj=None): + """ + Make sure that customer and template are not editable for existing + customer hosting packages. + + :param request: the current HTTP request + :param obj: either a :py:class:`CustomerHostingPackage + ` instance or None + for a new customer hosting package + :return: a list of fields + :rtype: list + + """ + if obj: + return ['customer', 'template'] + return [] + + +admin.site.register(CustomerHostingPackage, CustomerHostingPackageAdmin) +admin.site.register(DiskSpaceOption) +admin.site.register(HostingPackageTemplate) +admin.site.register(MailboxOption) +admin.site.register(UserDatabaseOption) diff --git a/gnuviechadmin/hostingpackages/apps.py b/gnuviechadmin/hostingpackages/apps.py new file mode 100644 index 0000000..bda74ce --- /dev/null +++ b/gnuviechadmin/hostingpackages/apps.py @@ -0,0 +1,18 @@ +""" +This module contains the :py:class:`django.apps.AppConfig` instance for the +:py:mod:`hostingpackages` app. + +""" +from __future__ import unicode_literals +from django.apps import AppConfig +from django.utils.translation import ugettext_lazy as _ + + +class HostingPackagesAppConfig(AppConfig): + """ + AppConfig for the :py:mod:`osusers` app. + + """ + name = 'hostingpackages' + verbose_name = _('Hosting Packages and Options') + diff --git a/gnuviechadmin/hostingpackages/locale/de/LC_MESSAGES/django.po b/gnuviechadmin/hostingpackages/locale/de/LC_MESSAGES/django.po new file mode 100644 index 0000000..8037f05 --- /dev/null +++ b/gnuviechadmin/hostingpackages/locale/de/LC_MESSAGES/django.po @@ -0,0 +1,192 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: gnuviechadmin hostingpackages\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-18 13:16+0100\n" +"PO-Revision-Date: 2015-01-18 13:17+0100\n" +"Last-Translator: Jan Dittberner \n" +"Language-Team: Jan Dittberner \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.6.10\n" +"X-Poedit-SourceCharset: UTF-8\n" + +#: apps.py:17 +msgid "Hosting Packages and Options" +msgstr "Hostingpakete und -Optionen" + +#: models.py:20 +msgid "MiB" +msgstr "MiB" + +#: models.py:21 +msgid "GiB" +msgstr "GiB" + +#: models.py:22 +msgid "TiB" +msgstr "TiB" + +#: models.py:28 +msgid "description" +msgstr "Beschreibung" + +#: models.py:29 +msgid "mailbox count" +msgstr "Anzahl Postfächer" + +#: models.py:31 models.py:58 +msgid "disk space" +msgstr "Speicherplatz" + +#: models.py:31 +msgid "disk space for the hosting package" +msgstr "Speicherplatz für das Hostingpaket" + +#: models.py:33 models.py:60 +msgid "unit of disk space" +msgstr "Maßeinheit für den Speicherplatz" + +#: models.py:43 models.py:172 +msgid "name" +msgstr "Name" + +#: models.py:46 +msgid "Hosting package" +msgstr "Hostingpaket" + +#: models.py:47 +msgid "Hosting packages" +msgstr "Hostingpakete" + +#: models.py:66 +msgid "Disk space option" +msgstr "Speicherplatzoption" + +#: models.py:67 +msgid "Disk space options" +msgstr "Speicherplatzoptionen" + +#: models.py:70 +#, python-brace-format +msgid "Additional disk space {space} {unit}" +msgstr "Zusätzlicher Speicherplatz {space} {unit}" + +#: models.py:84 +msgid "number of databases" +msgstr "Anzahl von Datenbanken" + +#: models.py:86 +msgid "database type" +msgstr "Datenbanktyp" + +#: models.py:92 +msgid "Database option" +msgstr "Datenbankoption" + +#: models.py:93 +msgid "Database options" +msgstr "Datenbankoptionen" + +#: models.py:97 +#, python-brace-format +msgid "{type} database" +msgid_plural "{count} {type} databases" +msgstr[0] "{type}-Datenbank" +msgstr[1] "{count} {type}-Datenbanken" + +#: models.py:120 +msgid "number of mailboxes" +msgstr "Anzahl von Postfächern" + +#: models.py:125 +msgid "Mailbox option" +msgstr "Postfachoption" + +#: models.py:126 +msgid "Mailbox options" +msgstr "Postfachoptionen" + +#: models.py:130 +#, python-brace-format +msgid "{count} additional mailbox" +msgid_plural "{count} additional mailboxes" +msgstr[0] "{count} zusätzliches Postfach" +msgstr[1] "{count} zusätzliche Postfächer" + +#: models.py:165 +msgid "customer" +msgstr "Kunde" + +#: models.py:167 +msgid "hosting package template" +msgstr "Hostingpaketvorlage" + +#: models.py:169 +msgid "The hosting package template that this hosting package is based on" +msgstr "Die Hostingpaketvorlage, auf der dieses Hostingpaket aufgebaut ist" + +#: models.py:174 +msgid "Operating system user" +msgstr "Betriebssystemnutzer" + +#: models.py:181 +msgid "customer hosting package" +msgstr "Kundenhostingpaket" + +#: models.py:182 +msgid "customer hosting packages" +msgstr "Kundenhostingpakete" + +#: models.py:191 +msgid "hosting package" +msgstr "Hostingpaket" + +#: models.py:194 +msgid "customer hosting option" +msgstr "kundenspezifische Hostingoption" + +#: models.py:195 +msgid "customer hosting options" +msgstr "kundenspezifische Hostingoptionen" + +#: models.py:207 +msgid "disk space option template" +msgstr "Speicherplatzoptionsvorlage" + +#: models.py:209 +msgid "The disk space option template that this disk space option is based on" +msgstr "" +"Die Speicherplatzoptionsvorlage auf der diese Speicherplatzoption aufgebaut " +"ist" + +#: models.py:223 +msgid "user database option template" +msgstr "Nutzerdatenbankoptionsvorlage" + +#: models.py:225 +msgid "The user database option template that this database option is based on" +msgstr "" +"Die Nutzerdatenbankoptionsvorlage auf der diese Datenbankoption aufgebaut ist" + +#: models.py:239 +msgid "mailbox option template" +msgstr "Postfachoptionsvorlage" + +#: models.py:241 +msgid "The mailbox option template that this mailbox option is based on" +msgstr "Die Postfachoptionsvorlage auf der diese Postfachoption aufgebaut ist" + +#~ msgid "Hosting option" +#~ msgstr "Hostingoption" + +#~ msgid "Hosting options" +#~ msgstr "Hostingoptionen" diff --git a/gnuviechadmin/hostingpackages/migrations/0001_initial.py b/gnuviechadmin/hostingpackages/migrations/0001_initial.py new file mode 100644 index 0000000..b70934d --- /dev/null +++ b/gnuviechadmin/hostingpackages/migrations/0001_initial.py @@ -0,0 +1,214 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +import django.utils.timezone +from django.conf import settings +import model_utils.fields + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='CustomerHostingPackage', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ('name', models.CharField(unique=True, max_length=128, verbose_name='name')), + ('description', models.TextField(verbose_name='description', blank=True)), + ('mailboxcount', models.PositiveIntegerField(verbose_name='mailbox count')), + ('diskspace', models.PositiveIntegerField(help_text='disk space for the hosting package', verbose_name='disk space')), + ('diskspace_unit', models.PositiveSmallIntegerField(verbose_name='unit of disk space', choices=[(0, 'MiB'), (1, 'GiB'), (2, 'TiB')])), + ('customer', models.ForeignKey(verbose_name='customer', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'customer hosting package', + 'verbose_name_plural': 'customer hosting packages', + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='CustomerHostingPackageOption', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ], + options={ + 'verbose_name': 'customer hosting option', + 'verbose_name_plural': 'customer hosting options', + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='CustomerDiskSpaceOption', + fields=[ + ('customerhostingpackageoption_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='hostingpackages.CustomerHostingPackageOption')), + ('diskspace', models.PositiveIntegerField(verbose_name='disk space')), + ('diskspace_unit', models.PositiveSmallIntegerField(verbose_name='unit of disk space', choices=[(0, 'MiB'), (1, 'GiB'), (2, 'TiB')])), + ], + options={ + 'ordering': ['diskspace_unit', 'diskspace'], + 'abstract': False, + 'verbose_name': 'Disk space option', + 'verbose_name_plural': 'Disk space options', + }, + bases=('hostingpackages.customerhostingpackageoption', models.Model), + ), + migrations.CreateModel( + name='CustomerMailboxOption', + fields=[ + ('customerhostingpackageoption_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='hostingpackages.CustomerHostingPackageOption')), + ('number', models.PositiveIntegerField(unique=True, verbose_name='number of mailboxes')), + ], + options={ + 'ordering': ['number'], + 'abstract': False, + 'verbose_name': 'Mailbox option', + 'verbose_name_plural': 'Mailbox options', + }, + bases=('hostingpackages.customerhostingpackageoption', models.Model), + ), + migrations.CreateModel( + name='CustomerUserDatabaseOption', + fields=[ + ('customerhostingpackageoption_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='hostingpackages.CustomerHostingPackageOption')), + ('number', models.PositiveIntegerField(default=1, verbose_name='number of databases')), + ('db_type', models.PositiveSmallIntegerField(verbose_name='database type', choices=[(0, 'PostgreSQL'), (1, 'MySQL')])), + ], + options={ + 'ordering': ['db_type', 'number'], + 'abstract': False, + 'verbose_name': 'Database option', + 'verbose_name_plural': 'Database options', + }, + bases=('hostingpackages.customerhostingpackageoption', models.Model), + ), + migrations.CreateModel( + name='HostingOption', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ], + options={ + 'verbose_name': 'Hosting option', + 'verbose_name_plural': 'Hosting options', + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='DiskSpaceOption', + fields=[ + ('hostingoption_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='hostingpackages.HostingOption')), + ('diskspace', models.PositiveIntegerField(verbose_name='disk space')), + ('diskspace_unit', models.PositiveSmallIntegerField(verbose_name='unit of disk space', choices=[(0, 'MiB'), (1, 'GiB'), (2, 'TiB')])), + ], + options={ + 'ordering': ['diskspace_unit', 'diskspace'], + 'abstract': False, + 'verbose_name': 'Disk space option', + 'verbose_name_plural': 'Disk space options', + }, + bases=('hostingpackages.hostingoption', models.Model), + ), + migrations.CreateModel( + name='HostingPackageTemplate', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ('name', models.CharField(unique=True, max_length=128, verbose_name='name')), + ('description', models.TextField(verbose_name='description', blank=True)), + ('mailboxcount', models.PositiveIntegerField(verbose_name='mailbox count')), + ('diskspace', models.PositiveIntegerField(help_text='disk space for the hosting package', verbose_name='disk space')), + ('diskspace_unit', models.PositiveSmallIntegerField(verbose_name='unit of disk space', choices=[(0, 'MiB'), (1, 'GiB'), (2, 'TiB')])), + ], + options={ + 'verbose_name': 'Hosting package', + 'verbose_name_plural': 'Hosting packages', + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='MailboxOption', + fields=[ + ('hostingoption_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='hostingpackages.HostingOption')), + ('number', models.PositiveIntegerField(unique=True, verbose_name='number of mailboxes')), + ], + options={ + 'ordering': ['number'], + 'abstract': False, + 'verbose_name': 'Mailbox option', + 'verbose_name_plural': 'Mailbox options', + }, + bases=('hostingpackages.hostingoption', models.Model), + ), + migrations.CreateModel( + name='UserDatabaseOption', + fields=[ + ('hostingoption_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='hostingpackages.HostingOption')), + ('number', models.PositiveIntegerField(default=1, verbose_name='number of databases')), + ('db_type', models.PositiveSmallIntegerField(verbose_name='database type', choices=[(0, 'PostgreSQL'), (1, 'MySQL')])), + ], + options={ + 'ordering': ['db_type', 'number'], + 'abstract': False, + 'verbose_name': 'Database option', + 'verbose_name_plural': 'Database options', + }, + bases=('hostingpackages.hostingoption', models.Model), + ), + migrations.AlterUniqueTogether( + name='userdatabaseoption', + unique_together=set([('number', 'db_type')]), + ), + migrations.AlterUniqueTogether( + name='diskspaceoption', + unique_together=set([('diskspace', 'diskspace_unit')]), + ), + migrations.AddField( + model_name='customeruserdatabaseoption', + name='template', + field=models.ForeignKey(verbose_name='user database option template', to='hostingpackages.UserDatabaseOption', help_text='The user database option template that this hosting option is based on'), + preserve_default=True, + ), + migrations.AlterUniqueTogether( + name='customeruserdatabaseoption', + unique_together=set([('number', 'db_type')]), + ), + migrations.AddField( + model_name='customermailboxoption', + name='template', + field=models.ForeignKey(verbose_name='mailbox option template', to='hostingpackages.UserDatabaseOption', help_text='The mailbox option template that this hosting option is based on'), + preserve_default=True, + ), + migrations.AddField( + model_name='customerhostingpackageoption', + name='hosting_package', + field=models.ForeignKey(verbose_name='hosting package', to='hostingpackages.CustomerHostingPackage'), + preserve_default=True, + ), + migrations.AddField( + model_name='customerhostingpackage', + name='template', + field=models.ForeignKey(verbose_name='hosting package template', to='hostingpackages.HostingPackageTemplate', help_text='The hosting package template that this hosting package is based on.'), + preserve_default=True, + ), + migrations.AddField( + model_name='customerdiskspaceoption', + name='template', + field=models.ForeignKey(verbose_name='disk space option template', to='hostingpackages.DiskSpaceOption', help_text='The disk space option template that this hosting option is based on'), + preserve_default=True, + ), + migrations.AlterUniqueTogether( + name='customerdiskspaceoption', + unique_together=set([('diskspace', 'diskspace_unit')]), + ), + ] diff --git a/gnuviechadmin/hostingpackages/migrations/0001_squashed_0005_auto_20150118_1303.py b/gnuviechadmin/hostingpackages/migrations/0001_squashed_0005_auto_20150118_1303.py new file mode 100644 index 0000000..09ca357 --- /dev/null +++ b/gnuviechadmin/hostingpackages/migrations/0001_squashed_0005_auto_20150118_1303.py @@ -0,0 +1,245 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +import django.utils.timezone +from django.conf import settings +import model_utils.fields + + +class Migration(migrations.Migration): + + replaces = [('hostingpackages', '0001_initial'), ('hostingpackages', '0002_auto_20150118_1149'), ('hostingpackages', '0003_auto_20150118_1221'), ('hostingpackages', '0004_customerhostingpackage_osuser'), ('hostingpackages', '0005_auto_20150118_1303')] + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('osusers', '0004_auto_20150104_1751'), + ] + + operations = [ + migrations.CreateModel( + name='CustomerHostingPackage', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ('name', models.CharField(unique=True, max_length=128, verbose_name='name')), + ('description', models.TextField(verbose_name='description', blank=True)), + ('mailboxcount', models.PositiveIntegerField(verbose_name='mailbox count')), + ('diskspace', models.PositiveIntegerField(help_text='disk space for the hosting package', verbose_name='disk space')), + ('diskspace_unit', models.PositiveSmallIntegerField(verbose_name='unit of disk space', choices=[(0, 'MiB'), (1, 'GiB'), (2, 'TiB')])), + ('customer', models.ForeignKey(verbose_name='customer', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'customer hosting package', + 'verbose_name_plural': 'customer hosting packages', + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='CustomerHostingPackageOption', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ], + options={ + 'verbose_name': 'customer hosting option', + 'verbose_name_plural': 'customer hosting options', + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='CustomerDiskSpaceOption', + fields=[ + ('customerhostingpackageoption_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='hostingpackages.CustomerHostingPackageOption')), + ('diskspace', models.PositiveIntegerField(verbose_name='disk space')), + ('diskspace_unit', models.PositiveSmallIntegerField(verbose_name='unit of disk space', choices=[(0, 'MiB'), (1, 'GiB'), (2, 'TiB')])), + ], + options={ + 'ordering': ['diskspace_unit', 'diskspace'], + 'abstract': False, + 'verbose_name': 'Disk space option', + 'verbose_name_plural': 'Disk space options', + }, + bases=('hostingpackages.customerhostingpackageoption', models.Model), + ), + migrations.CreateModel( + name='CustomerMailboxOption', + fields=[ + ('customerhostingpackageoption_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='hostingpackages.CustomerHostingPackageOption')), + ('number', models.PositiveIntegerField(unique=True, verbose_name='number of mailboxes')), + ], + options={ + 'ordering': ['number'], + 'abstract': False, + 'verbose_name': 'Mailbox option', + 'verbose_name_plural': 'Mailbox options', + }, + bases=('hostingpackages.customerhostingpackageoption', models.Model), + ), + migrations.CreateModel( + name='CustomerUserDatabaseOption', + fields=[ + ('customerhostingpackageoption_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='hostingpackages.CustomerHostingPackageOption')), + ('number', models.PositiveIntegerField(default=1, verbose_name='number of databases')), + ('db_type', models.PositiveSmallIntegerField(verbose_name='database type', choices=[(0, 'PostgreSQL'), (1, 'MySQL')])), + ], + options={ + 'ordering': ['db_type', 'number'], + 'abstract': False, + 'verbose_name': 'Database option', + 'verbose_name_plural': 'Database options', + }, + bases=('hostingpackages.customerhostingpackageoption', models.Model), + ), + migrations.CreateModel( + name='HostingOption', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ], + options={ + 'verbose_name': 'Hosting option', + 'verbose_name_plural': 'Hosting options', + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='DiskSpaceOption', + fields=[ + ('hostingoption_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='hostingpackages.HostingOption')), + ('diskspace', models.PositiveIntegerField(verbose_name='disk space')), + ('diskspace_unit', models.PositiveSmallIntegerField(verbose_name='unit of disk space', choices=[(0, 'MiB'), (1, 'GiB'), (2, 'TiB')])), + ], + options={ + 'ordering': ['diskspace_unit', 'diskspace'], + 'abstract': False, + 'verbose_name': 'Disk space option', + 'verbose_name_plural': 'Disk space options', + }, + bases=('hostingpackages.hostingoption', models.Model), + ), + migrations.CreateModel( + name='HostingPackageTemplate', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ('name', models.CharField(unique=True, max_length=128, verbose_name='name')), + ('description', models.TextField(verbose_name='description', blank=True)), + ('mailboxcount', models.PositiveIntegerField(verbose_name='mailbox count')), + ('diskspace', models.PositiveIntegerField(help_text='disk space for the hosting package', verbose_name='disk space')), + ('diskspace_unit', models.PositiveSmallIntegerField(verbose_name='unit of disk space', choices=[(0, 'MiB'), (1, 'GiB'), (2, 'TiB')])), + ], + options={ + 'verbose_name': 'Hosting package', + 'verbose_name_plural': 'Hosting packages', + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='MailboxOption', + fields=[ + ('hostingoption_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='hostingpackages.HostingOption')), + ('number', models.PositiveIntegerField(unique=True, verbose_name='number of mailboxes')), + ], + options={ + 'ordering': ['number'], + 'abstract': False, + 'verbose_name': 'Mailbox option', + 'verbose_name_plural': 'Mailbox options', + }, + bases=('hostingpackages.hostingoption', models.Model), + ), + migrations.CreateModel( + name='UserDatabaseOption', + fields=[ + ('hostingoption_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='hostingpackages.HostingOption')), + ('number', models.PositiveIntegerField(default=1, verbose_name='number of databases')), + ('db_type', models.PositiveSmallIntegerField(verbose_name='database type', choices=[(0, 'PostgreSQL'), (1, 'MySQL')])), + ], + options={ + 'ordering': ['db_type', 'number'], + 'abstract': False, + 'verbose_name': 'Database option', + 'verbose_name_plural': 'Database options', + }, + bases=('hostingpackages.hostingoption', models.Model), + ), + migrations.AlterUniqueTogether( + name='userdatabaseoption', + unique_together=set([('number', 'db_type')]), + ), + migrations.AlterUniqueTogether( + name='diskspaceoption', + unique_together=set([('diskspace', 'diskspace_unit')]), + ), + migrations.AddField( + model_name='customeruserdatabaseoption', + name='template', + field=models.ForeignKey(verbose_name='user database option template', to='hostingpackages.UserDatabaseOption', help_text='The user database option template that this hosting option is based on'), + preserve_default=True, + ), + migrations.AlterUniqueTogether( + name='customeruserdatabaseoption', + unique_together=set([('number', 'db_type')]), + ), + migrations.AddField( + model_name='customermailboxoption', + name='template', + field=models.ForeignKey(verbose_name='mailbox option template', to='hostingpackages.UserDatabaseOption', help_text='The mailbox option template that this mailbox option is based on'), + preserve_default=True, + ), + migrations.AddField( + model_name='customerhostingpackageoption', + name='hosting_package', + field=models.ForeignKey(verbose_name='hosting package', to='hostingpackages.CustomerHostingPackage'), + preserve_default=True, + ), + migrations.AddField( + model_name='customerhostingpackage', + name='template', + field=models.ForeignKey(verbose_name='hosting package template', to='hostingpackages.HostingPackageTemplate', help_text='The hosting package template that this hosting package is based on'), + preserve_default=True, + ), + migrations.AddField( + model_name='customerdiskspaceoption', + name='template', + field=models.ForeignKey(verbose_name='disk space option template', to='hostingpackages.DiskSpaceOption', help_text='The disk space option template that this hosting option is based on'), + preserve_default=True, + ), + migrations.AlterUniqueTogether( + name='customerdiskspaceoption', + unique_together=set([('diskspace', 'diskspace_unit')]), + ), + migrations.AlterField( + model_name='customerdiskspaceoption', + name='template', + field=models.ForeignKey(verbose_name='disk space option template', to='hostingpackages.DiskSpaceOption', help_text='The disk space option template that this disk space option is based on'), + preserve_default=True, + ), + migrations.AlterField( + model_name='customeruserdatabaseoption', + name='template', + field=models.ForeignKey(verbose_name='user database option template', to='hostingpackages.UserDatabaseOption', help_text='The user database option template that this database option is based on'), + preserve_default=True, + ), + migrations.AlterField( + model_name='customerhostingpackage', + name='name', + field=models.CharField(max_length=128, verbose_name='name'), + preserve_default=True, + ), + migrations.AlterUniqueTogether( + name='customerhostingpackage', + unique_together=set([('customer', 'name')]), + ), + migrations.AddField( + model_name='customerhostingpackage', + name='osuser', + field=models.OneToOneField(null=True, blank=True, to='osusers.User', verbose_name='Operating system user'), + preserve_default=True, + ), + ] diff --git a/gnuviechadmin/hostingpackages/migrations/0002_auto_20150118_1149.py b/gnuviechadmin/hostingpackages/migrations/0002_auto_20150118_1149.py new file mode 100644 index 0000000..61103ed --- /dev/null +++ b/gnuviechadmin/hostingpackages/migrations/0002_auto_20150118_1149.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('hostingpackages', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='customerdiskspaceoption', + name='template', + field=models.ForeignKey(verbose_name='disk space option template', to='hostingpackages.DiskSpaceOption', help_text='The disk space option template that this disk space option is based on'), + preserve_default=True, + ), + migrations.AlterField( + model_name='customerhostingpackage', + name='template', + field=models.ForeignKey(verbose_name='hosting package template', to='hostingpackages.HostingPackageTemplate', help_text='The hosting package template that this hosting package is based on'), + preserve_default=True, + ), + migrations.AlterField( + model_name='customermailboxoption', + name='template', + field=models.ForeignKey(verbose_name='mailbox option template', to='hostingpackages.UserDatabaseOption', help_text='The mailbox option template that this mailbox option is based on'), + preserve_default=True, + ), + migrations.AlterField( + model_name='customeruserdatabaseoption', + name='template', + field=models.ForeignKey(verbose_name='user database option template', to='hostingpackages.UserDatabaseOption', help_text='The user database option template that this database option is based on'), + preserve_default=True, + ), + ] diff --git a/gnuviechadmin/hostingpackages/migrations/0002_auto_20150118_1319.py b/gnuviechadmin/hostingpackages/migrations/0002_auto_20150118_1319.py new file mode 100644 index 0000000..80bf125 --- /dev/null +++ b/gnuviechadmin/hostingpackages/migrations/0002_auto_20150118_1319.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('hostingpackages', '0001_squashed_0005_auto_20150118_1303'), + ] + + operations = [ + migrations.AlterModelOptions( + name='hostingoption', + options={}, + ), + ] diff --git a/gnuviechadmin/hostingpackages/migrations/0003_auto_20150118_1221.py b/gnuviechadmin/hostingpackages/migrations/0003_auto_20150118_1221.py new file mode 100644 index 0000000..c77662e --- /dev/null +++ b/gnuviechadmin/hostingpackages/migrations/0003_auto_20150118_1221.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('hostingpackages', '0002_auto_20150118_1149'), + ] + + operations = [ + migrations.AlterField( + model_name='customerhostingpackage', + name='name', + field=models.CharField(max_length=128, verbose_name='name'), + preserve_default=True, + ), + migrations.AlterUniqueTogether( + name='customerhostingpackage', + unique_together=set([('customer', 'name')]), + ), + ] diff --git a/gnuviechadmin/hostingpackages/migrations/0004_customerhostingpackage_osuser.py b/gnuviechadmin/hostingpackages/migrations/0004_customerhostingpackage_osuser.py new file mode 100644 index 0000000..c5b47e3 --- /dev/null +++ b/gnuviechadmin/hostingpackages/migrations/0004_customerhostingpackage_osuser.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('osusers', '0004_auto_20150104_1751'), + ('hostingpackages', '0003_auto_20150118_1221'), + ] + + operations = [ + migrations.AddField( + model_name='customerhostingpackage', + name='osuser', + field=models.ForeignKey(verbose_name='Operating system user', blank=True, to='osusers.User', null=True), + preserve_default=True, + ), + ] diff --git a/gnuviechadmin/hostingpackages/migrations/0005_auto_20150118_1303.py b/gnuviechadmin/hostingpackages/migrations/0005_auto_20150118_1303.py new file mode 100644 index 0000000..b66739e --- /dev/null +++ b/gnuviechadmin/hostingpackages/migrations/0005_auto_20150118_1303.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('hostingpackages', '0004_customerhostingpackage_osuser'), + ] + + operations = [ + migrations.AlterField( + model_name='customerhostingpackage', + name='osuser', + field=models.OneToOneField(null=True, blank=True, to='osusers.User', verbose_name='Operating system user'), + preserve_default=True, + ), + ] diff --git a/gnuviechadmin/hostingpackages/migrations/__init__.py b/gnuviechadmin/hostingpackages/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/gnuviechadmin/hostingpackages/models.py b/gnuviechadmin/hostingpackages/models.py new file mode 100644 index 0000000..ad9f2e5 --- /dev/null +++ b/gnuviechadmin/hostingpackages/models.py @@ -0,0 +1,242 @@ +""" +This module contains the hosting package models. + +""" +from __future__ import absolute_import, unicode_literals + +from django.conf import settings +from django.db import models +from django.utils.encoding import python_2_unicode_compatible +from django.utils.translation import ugettext_lazy as _, ungettext + +from model_utils import Choices +from model_utils.models import TimeStampedModel + +from userdbs.models import DB_TYPES +from osusers.models import User as OsUser + + +DISK_SPACE_UNITS = Choices( + (0, 'M', _('MiB')), + (1, 'G', _('GiB')), + (2, 'T', _('TiB')), +) + + +@python_2_unicode_compatible +class HostingPackageBase(TimeStampedModel): + description = models.TextField(_('description'), blank=True) + mailboxcount = models.PositiveIntegerField(_('mailbox count')) + diskspace = models.PositiveIntegerField( + _('disk space'), help_text=_('disk space for the hosting package')) + diskspace_unit = models.PositiveSmallIntegerField( + _('unit of disk space'), choices=DISK_SPACE_UNITS) + + class Meta: + abstract = True + + def __str__(self): + return self.name + + +class HostingPackageTemplate(HostingPackageBase): + name = models.CharField(_('name'), max_length=128, unique=True) + + class Meta: + verbose_name = _('Hosting package') + verbose_name_plural = _('Hosting packages') + + +class HostingOption(TimeStampedModel): + """ + This is the base class for several types of hosting options. + + """ + +@python_2_unicode_compatible +class DiskSpaceOptionBase(models.Model): + diskspace = models.PositiveIntegerField(_('disk space')) + diskspace_unit = models.PositiveSmallIntegerField( + _('unit of disk space'), choices=DISK_SPACE_UNITS) + + class Meta: + abstract = True + ordering = ['diskspace_unit', 'diskspace'] + unique_together = ['diskspace', 'diskspace_unit'] + verbose_name = _('Disk space option') + verbose_name_plural = _('Disk space options') + + def __str__(self): + return _("Additional disk space {space} {unit}").format( + space=self.diskspace, unit=self.get_diskspace_unit_display()) + +class DiskSpaceOption(DiskSpaceOptionBase, HostingOption): + """ + This is a class for hosting options adding additional disk space to + existing hosting packages. + + """ + + +@python_2_unicode_compatible +class UserDatabaseOptionBase(models.Model): + number = models.PositiveIntegerField( + _('number of databases'), default=1) + db_type = models.PositiveSmallIntegerField( + _('database type'), choices=DB_TYPES) + + class Meta: + abstract = True + ordering = ['db_type', 'number'] + unique_together = ['number', 'db_type'] + verbose_name = _('Database option') + verbose_name_plural = _('Database options') + + def __str__(self): + return ungettext( + '{type} database', + '{count} {type} databases', + self.number + ).format( + type=self.get_db_type_display(), count=self.number + ) + + +class UserDatabaseOption(UserDatabaseOptionBase, HostingOption): + """ + This is a class for hosting options adding user databases to existing + hosting packages. + + """ + + +@python_2_unicode_compatible +class MailboxOptionBase(models.Model): + """ + Base class for mailbox options. + + """ + number = models.PositiveIntegerField( + _('number of mailboxes'), unique=True) + + class Meta: + abstract = True + ordering = ['number'] + verbose_name = _('Mailbox option') + verbose_name_plural = _('Mailbox options') + + def __str__(self): + return ungettext( + '{count} additional mailbox', + '{count} additional mailboxes', + self.number + ).format( + count=self.number + ) + + +class MailboxOption(MailboxOptionBase, HostingOption): + """ + This is a class for hosting options adding more mailboxes to existing + hosting packages. + + """ + + +class CustomerHostingPackageManager(models.Manager): + + def create_from_template(self, customer, template, name, **kwargs): + package = CustomerHostingPackage( + customer=customer, template=template, name=name) + for attrname in ('description', 'diskspace', 'diskspace_unit', + 'mailboxcount'): + setattr(package, attrname, getattr(template, attrname)) + if 'commit' in kwargs and kwargs['commit'] is True: + package.save(**kwargs) + return package + + +class CustomerHostingPackage(HostingPackageBase): + """ + This class defines customer specific hosting packages. + + """ + customer = models.ForeignKey( + settings.AUTH_USER_MODEL, verbose_name=_('customer')) + template = models.ForeignKey( + HostingPackageTemplate, verbose_name=_('hosting package template'), + help_text=_( + 'The hosting package template that this hosting package is based' + ' on' + )) + name = models.CharField(_('name'), max_length=128) + osuser = models.OneToOneField( + OsUser, verbose_name=_('Operating system user'), + blank=True, null=True) + + objects = CustomerHostingPackageManager() + + class Meta: + unique_together = ['customer', 'name'] + verbose_name = _('customer hosting package') + verbose_name_plural = _('customer hosting packages') + + +class CustomerHostingPackageOption(TimeStampedModel): + """ + This class defines options for customer hosting packages. + + """ + hosting_package = models.ForeignKey( + CustomerHostingPackage, verbose_name=_('hosting package')) + + class Meta: + verbose_name = _('customer hosting option') + verbose_name_plural = _('customer hosting options') + + +class CustomerDiskSpaceOption(DiskSpaceOptionBase, + CustomerHostingPackageOption): + """ + This is a class for customer hosting package options adding additional disk + space to existing customer hosting package. + + """ + template = models.ForeignKey( + DiskSpaceOption, + verbose_name=_('disk space option template'), + help_text=_( + 'The disk space option template that this disk space option is' + ' based on' + )) + + +class CustomerUserDatabaseOption(UserDatabaseOptionBase, + CustomerHostingPackageOption): + """ + This is a class for customer hosting package options adding user databases + to existing customer hosting packages. + + """ + template = models.ForeignKey( + UserDatabaseOption, + verbose_name=_('user database option template'), + help_text=_( + 'The user database option template that this database option is' + ' based on' + )) + + +class CustomerMailboxOption(MailboxOptionBase, + CustomerHostingPackageOption): + """ + This is a class for customer hosting package options adding additional + mailboxes to existing customer hosting packages. + + """ + template = models.ForeignKey( + UserDatabaseOption, + verbose_name=_('mailbox option template'), + help_text=_( + 'The mailbox option template that this mailbox option is based on' + )) From 12455e2d99c4886652b74cc974c53ae9970351f2 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 18 Jan 2015 13:22:31 +0100 Subject: [PATCH 02/10] add hostingpackages app to INSTALLED_APPS --- gnuviechadmin/gnuviechadmin/settings/base.py | 1 + 1 file changed, 1 insertion(+) diff --git a/gnuviechadmin/gnuviechadmin/settings/base.py b/gnuviechadmin/gnuviechadmin/settings/base.py index 8c6a359..09b75ad 100644 --- a/gnuviechadmin/gnuviechadmin/settings/base.py +++ b/gnuviechadmin/gnuviechadmin/settings/base.py @@ -262,6 +262,7 @@ LOCAL_APPS = ( 'osusers', 'managemails', 'userdbs', + 'hostingpackages', ) # See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps From 4f2ebbae63d07335daae057bd3da1170497bc259 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 18 Jan 2015 13:37:21 +0100 Subject: [PATCH 03/10] add hostingpackages api doc - add to docs/code.rst toctree - add new docs/code/hostingpackages.rst containing the autodoc directives - document undocumented code in hostingpackages app - update translation templates --- docs/code.rst | 1 + docs/code/hostingpackages.rst | 24 +++++++++++++ gnuviechadmin/hostingpackages/admin.py | 24 +++++++++++++ gnuviechadmin/hostingpackages/apps.py | 2 +- .../locale/de/LC_MESSAGES/django.po | 34 +++++++++---------- gnuviechadmin/hostingpackages/models.py | 20 +++++++++++ 6 files changed, 87 insertions(+), 18 deletions(-) create mode 100644 docs/code/hostingpackages.rst diff --git a/docs/code.rst b/docs/code.rst index 22944fe..d5f720c 100644 --- a/docs/code.rst +++ b/docs/code.rst @@ -16,6 +16,7 @@ administrators and customers. code/gvacommon code/dashboard code/domains + code/hostingpackages code/managemails code/mysqltasks code/osusers diff --git a/docs/code/hostingpackages.rst b/docs/code/hostingpackages.rst new file mode 100644 index 0000000..2d5d077 --- /dev/null +++ b/docs/code/hostingpackages.rst @@ -0,0 +1,24 @@ +:py:mod:`hostingpackages` app +============================= + +.. automodule:: hostingpackages + +:py:mod:`admin ` +--------------------------------------- + +.. automodule:: hostingpackages.admin + :members: + + +:py:mod:`apps ` +------------------------------------- + +.. automodule:: hostingpackages.apps + :members: + + +:py:mod:`models ` +----------------------------------------- + +.. automodule:: hostingpackages.models + :members: diff --git a/gnuviechadmin/hostingpackages/admin.py b/gnuviechadmin/hostingpackages/admin.py index a399bdb..a5fd3a7 100644 --- a/gnuviechadmin/hostingpackages/admin.py +++ b/gnuviechadmin/hostingpackages/admin.py @@ -20,6 +20,10 @@ from .models import ( class CustomerHostingPackageCreateForm(forms.ModelForm): + """ + This is the form class for creating new customer hosting packages. + + """ class Meta: model = CustomerHostingPackage fields = ['customer', 'template', 'name'] @@ -45,21 +49,41 @@ class CustomerHostingPackageCreateForm(forms.ModelForm): class CustomerDiskSpaceOptionInline(admin.TabularInline): + """ + This class implements the inline editor for customer hosting package disk + space options. + + """ model = CustomerDiskSpaceOption extra = 0 class CustomerMailboxOptionInline(admin.TabularInline): + """ + This class implements the inline editor for customer hosting package + mailbox options. + + """ model = CustomerMailboxOption extra = 0 class CustomerUserDatabaseOptionInline(admin.TabularInline): + """ + This class implements the inline editor for customer hosting package user + database options. + + """ model = CustomerUserDatabaseOption extra = 0 class CustomerHostingPackageAdmin(admin.ModelAdmin): + """ + This class implements the admin interface for + :py:class:`CustomerHostingPackage`. + + """ add_form = CustomerHostingPackageCreateForm add_fieldsets = ( (None, { diff --git a/gnuviechadmin/hostingpackages/apps.py b/gnuviechadmin/hostingpackages/apps.py index bda74ce..2bb6e3e 100644 --- a/gnuviechadmin/hostingpackages/apps.py +++ b/gnuviechadmin/hostingpackages/apps.py @@ -10,7 +10,7 @@ from django.utils.translation import ugettext_lazy as _ class HostingPackagesAppConfig(AppConfig): """ - AppConfig for the :py:mod:`osusers` app. + AppConfig for the :py:mod:`hostingpackages` app. """ name = 'hostingpackages' diff --git a/gnuviechadmin/hostingpackages/locale/de/LC_MESSAGES/django.po b/gnuviechadmin/hostingpackages/locale/de/LC_MESSAGES/django.po index 8037f05..caf6f78 100644 --- a/gnuviechadmin/hostingpackages/locale/de/LC_MESSAGES/django.po +++ b/gnuviechadmin/hostingpackages/locale/de/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: gnuviechadmin hostingpackages\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-01-18 13:16+0100\n" +"POT-Creation-Date: 2015-01-18 13:36+0100\n" "PO-Revision-Date: 2015-01-18 13:17+0100\n" "Last-Translator: Jan Dittberner \n" "Language-Team: Jan Dittberner \n" @@ -55,7 +55,7 @@ msgstr "Speicherplatz für das Hostingpaket" msgid "unit of disk space" msgstr "Maßeinheit für den Speicherplatz" -#: models.py:43 models.py:172 +#: models.py:43 models.py:192 msgid "name" msgstr "Name" @@ -122,66 +122,66 @@ msgid_plural "{count} additional mailboxes" msgstr[0] "{count} zusätzliches Postfach" msgstr[1] "{count} zusätzliche Postfächer" -#: models.py:165 +#: models.py:185 msgid "customer" msgstr "Kunde" -#: models.py:167 +#: models.py:187 msgid "hosting package template" msgstr "Hostingpaketvorlage" -#: models.py:169 +#: models.py:189 msgid "The hosting package template that this hosting package is based on" msgstr "Die Hostingpaketvorlage, auf der dieses Hostingpaket aufgebaut ist" -#: models.py:174 +#: models.py:194 msgid "Operating system user" msgstr "Betriebssystemnutzer" -#: models.py:181 +#: models.py:201 msgid "customer hosting package" msgstr "Kundenhostingpaket" -#: models.py:182 +#: models.py:202 msgid "customer hosting packages" msgstr "Kundenhostingpakete" -#: models.py:191 +#: models.py:211 msgid "hosting package" msgstr "Hostingpaket" -#: models.py:194 +#: models.py:214 msgid "customer hosting option" msgstr "kundenspezifische Hostingoption" -#: models.py:195 +#: models.py:215 msgid "customer hosting options" msgstr "kundenspezifische Hostingoptionen" -#: models.py:207 +#: models.py:227 msgid "disk space option template" msgstr "Speicherplatzoptionsvorlage" -#: models.py:209 +#: models.py:229 msgid "The disk space option template that this disk space option is based on" msgstr "" "Die Speicherplatzoptionsvorlage auf der diese Speicherplatzoption aufgebaut " "ist" -#: models.py:223 +#: models.py:243 msgid "user database option template" msgstr "Nutzerdatenbankoptionsvorlage" -#: models.py:225 +#: models.py:245 msgid "The user database option template that this database option is based on" msgstr "" "Die Nutzerdatenbankoptionsvorlage auf der diese Datenbankoption aufgebaut ist" -#: models.py:239 +#: models.py:259 msgid "mailbox option template" msgstr "Postfachoptionsvorlage" -#: models.py:241 +#: models.py:261 msgid "The mailbox option template that this mailbox option is based on" msgstr "Die Postfachoptionsvorlage auf der diese Postfachoption aufgebaut ist" diff --git a/gnuviechadmin/hostingpackages/models.py b/gnuviechadmin/hostingpackages/models.py index ad9f2e5..f84a9c1 100644 --- a/gnuviechadmin/hostingpackages/models.py +++ b/gnuviechadmin/hostingpackages/models.py @@ -144,8 +144,28 @@ class MailboxOption(MailboxOptionBase, HostingOption): class CustomerHostingPackageManager(models.Manager): + """ + This is the default manager implementation for + :py:class:`CustomerHostingPackage`. + + """ def create_from_template(self, customer, template, name, **kwargs): + """ + Use this method to create a new :py:class:`CustomerHostingPackage` from + a :py:class:`HostingPackageTemplate`. + + The method copies data from the template to the new + :py:class:`CustomerHostingPackage` instance. + + :param customer: a Django user representing a customer + :param template: a :py:class:`HostingPackageTemplate` + :param str name: the name of the hosting package there must only be + one hosting package of this name for each customer + :return: customer hosting package + :rtype: :py:class:`CustomerHostingPackage` + + """ package = CustomerHostingPackage( customer=customer, template=template, name=name) for attrname in ('description', 'diskspace', 'diskspace_unit', From 7457754dc6463214ff2934cf8f75f1ac670a76ca Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 18 Jan 2015 13:40:16 +0100 Subject: [PATCH 04/10] mention hostingpackages app in changelog --- docs/changelog.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index 1cfa8bd..0aac1fb 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,10 @@ Changelog ========= +* :feature:`-` implement new hostingpackages app to provide hosting package + templates, hosting options and customer hosting packages as well as customer + specific hosting package options + * :release:`0.5.2 <2015-01-18>` * :bug:`-` define proper allauth production settings with https and mandatory email verification From 95e15806c6d029257c74f1dd908b18e3d4c8d9be Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 18 Jan 2015 15:58:58 +0100 Subject: [PATCH 05/10] fix foreign key for CustomerMailboxOption --- .../migrations/0003_auto_20150118_1407.py | 20 +++++++++++++++++++ gnuviechadmin/hostingpackages/models.py | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 gnuviechadmin/hostingpackages/migrations/0003_auto_20150118_1407.py diff --git a/gnuviechadmin/hostingpackages/migrations/0003_auto_20150118_1407.py b/gnuviechadmin/hostingpackages/migrations/0003_auto_20150118_1407.py new file mode 100644 index 0000000..8d7e82d --- /dev/null +++ b/gnuviechadmin/hostingpackages/migrations/0003_auto_20150118_1407.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('hostingpackages', '0002_auto_20150118_1319'), + ] + + operations = [ + migrations.AlterField( + model_name='customermailboxoption', + name='template', + field=models.ForeignKey(verbose_name='mailbox option template', to='hostingpackages.MailboxOption', help_text='The mailbox option template that this mailbox option is based on'), + preserve_default=True, + ), + ] diff --git a/gnuviechadmin/hostingpackages/models.py b/gnuviechadmin/hostingpackages/models.py index f84a9c1..15e98b9 100644 --- a/gnuviechadmin/hostingpackages/models.py +++ b/gnuviechadmin/hostingpackages/models.py @@ -255,7 +255,7 @@ class CustomerMailboxOption(MailboxOptionBase, """ template = models.ForeignKey( - UserDatabaseOption, + MailboxOption, verbose_name=_('mailbox option template'), help_text=_( 'The mailbox option template that this mailbox option is based on' From 0e32aff544191fa1d407d629981a6866fba5dcb1 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 18 Jan 2015 16:14:47 +0100 Subject: [PATCH 06/10] add CustomerHostingPackage information aggration methods - add get_disk_space, get_used_mailboxes, get_mailboxes and get_database methods for hostingpackages.models.CustomerHostingPackage --- gnuviechadmin/hostingpackages/models.py | 70 ++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/gnuviechadmin/hostingpackages/models.py b/gnuviechadmin/hostingpackages/models.py index 15e98b9..89b7e37 100644 --- a/gnuviechadmin/hostingpackages/models.py +++ b/gnuviechadmin/hostingpackages/models.py @@ -12,8 +12,9 @@ from django.utils.translation import ugettext_lazy as _, ungettext from model_utils import Choices from model_utils.models import TimeStampedModel -from userdbs.models import DB_TYPES +from managemails.models import Mailbox from osusers.models import User as OsUser +from userdbs.models import DB_TYPES DISK_SPACE_UNITS = Choices( @@ -22,6 +23,12 @@ DISK_SPACE_UNITS = Choices( (2, 'T', _('TiB')), ) +DISK_SPACE_FACTORS = ( + (1, None, None), + (1024, 1, None), + (1024 * 1024, 1024, 1), +) + @python_2_unicode_compatible class HostingPackageBase(TimeStampedModel): @@ -201,6 +208,67 @@ class CustomerHostingPackage(HostingPackageBase): verbose_name = _('customer hosting package') verbose_name_plural = _('customer hosting packages') + def get_disk_space(self): + """ + Get the total disk space reserved for this hosting package and all its + additional disk space options. + + :return: disk space + :rtype: int + + """ + diskspace = self.diskspace + min_unit = self.diskspace_unit + + options = CustomerDiskSpaceOption.objects.filter(hosting_package=self) + for option in options: + if option.diskspace_unit == min_unit: + diskspace += option.disk_space + elif option.diskspace_unit > min_unit: + diskspace += ( + DISK_SPACE_FACTORS[option.diskspace_unit][min_unit] * + option.diskspace) + else: + diskspace = ( + DISK_SPACE_FACTORS[min_unit][option.diskspace_unit] * + diskspace) + option.diskspace + min_unit = option.diskspace_unit + return DISK_SPACE_FACTORS[min_unit][0] * diskspace * 1024**2 + + def get_used_mailboxes(self): + """ + Get the number of used mailboxes for this hosting package. + + """ + if self.osuser: + return Mailbox.objects.filter(osuser=self.osuser).count() + return 0 + + def get_mailboxes(self): + """ + Get the number of mailboxes provided by this hosting package and all + of its mailbox options. + + """ + result = CustomerMailboxOption.objects.filter( + hosting_package=self + ).aggregate( + mailbox_sum=models.Sum('number') + ) + return self.mailboxcount + result['mailbox_sum'] + + def get_databases(self): + """ + Get the number of user databases provided by user database hosting + options for this hosting package. + + """ + return CustomerUserDatabaseOption.objects.values( + 'db_type' + ).filter(hosting_package=self).annotate( + number=models.Sum('number') + ).all() + class CustomerHostingPackageOption(TimeStampedModel): """ From d34f3596aee8d77d6435066794e9183c46a2ed50 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 18 Jan 2015 16:19:28 +0100 Subject: [PATCH 07/10] implement get_context_data for UserDashboardView - expose user's hosting packages in UserDashboardView.get_context_data --- gnuviechadmin/dashboard/views.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/gnuviechadmin/dashboard/views.py b/gnuviechadmin/dashboard/views.py index eec7df6..549c059 100644 --- a/gnuviechadmin/dashboard/views.py +++ b/gnuviechadmin/dashboard/views.py @@ -15,6 +15,8 @@ from django.contrib.auth import get_user_model, logout from braces.views import LoginRequiredMixin +from hostingpackages.models import CustomerHostingPackage + class IndexView(TemplateView): """ @@ -43,6 +45,14 @@ class UserDashboardView(LoginRequiredMixin, DetailView): _('You are not allowed to view this page.') ) + def get_context_data(self, **kwargs): + context = super(UserDashboardView, self).get_context_data(**kwargs) + context['hosting_packages'] = CustomerHostingPackage.objects.filter( + customer=self.object + ) + return context + + class LogoutView(RedirectView): pattern_name = 'dashboard' From d7d41d2fd9a69019063915a922592747bdd78556 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 18 Jan 2015 16:20:47 +0100 Subject: [PATCH 08/10] render hosting package table on user dashboard --- .../templates/dashboard/user_dashboard.html | 48 ++++++++++++++++--- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/gnuviechadmin/templates/dashboard/user_dashboard.html b/gnuviechadmin/templates/dashboard/user_dashboard.html index baff5f7..c12627a 100644 --- a/gnuviechadmin/templates/dashboard/user_dashboard.html +++ b/gnuviechadmin/templates/dashboard/user_dashboard.html @@ -3,10 +3,46 @@ {% block title %}{{ block.super }} - {% blocktrans with full_name=dashboard_user.get_full_name %}Dashboard for {{ full_name }}{% endblocktrans %}{% endblock title %} {% block page_title %}{% blocktrans with full_name=dashboard_user.get_full_name %}Dashboard for {{ full_name }}{% endblocktrans %}{% endblock page_title %} {% block content %} -

Contract details

-
    -
  • Domains
  • -
  • Email mailboxes
  • -
  • Email addresses
  • -
+
+
+
+
{% trans "Hosting packages" %}
+
+ {% if hosting_packages %} + + + + + + + + + + + + {% for package in hosting_packages %} + + + + + + + + {% endfor %} + +
{% trans "Name" %}{% trans "Disk space" %}{% trans "Mailboxes" %}{% trans "Databases" %}{% trans "Actions" %}
{{ package.name }} + {% with diskspace=package.get_disk_space %} + {{ diskspace|filesizeformat }} + {% endwith %} + {% blocktrans with num=package.get_used_mailboxes total=package.get_mailboxes %}used {{ num }} of {{ total }}{% endblocktrans %}{% for dbtype in package.get_databases %} + {{ dbtype.number }} {% include "userdbs/snippets/db_type.html" with db_type=dbtype.db_type %} + {% if not forloop.last %} / {% endif %} + {% endfor %}
+ {% else %} +

{% trans "You have no hosting packages yet." %}

+ {% endif %} +
+
+
+
{% endblock content %} From 8ffa22cc078b0a51dce385b7db41debe0d192d0b Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 18 Jan 2015 16:22:00 +0100 Subject: [PATCH 09/10] add changelog entry for hosting package information on user dashboard --- docs/changelog.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index 0aac1fb..f22636b 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,7 @@ Changelog ========= +* :feature:`-` show hosting package information on user dashboard * :feature:`-` implement new hostingpackages app to provide hosting package templates, hosting options and customer hosting packages as well as customer specific hosting package options From 7ab58575eb3fd89c126f56c934d62d2145f2102a Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 18 Jan 2015 16:25:41 +0100 Subject: [PATCH 10/10] remove newline at EOF --- gnuviechadmin/hostingpackages/apps.py | 1 - 1 file changed, 1 deletion(-) diff --git a/gnuviechadmin/hostingpackages/apps.py b/gnuviechadmin/hostingpackages/apps.py index 2bb6e3e..e1fb021 100644 --- a/gnuviechadmin/hostingpackages/apps.py +++ b/gnuviechadmin/hostingpackages/apps.py @@ -15,4 +15,3 @@ class HostingPackagesAppConfig(AppConfig): """ name = 'hostingpackages' verbose_name = _('Hosting Packages and Options') -