implement adding options to hosting packages

- fix unique constraints on CustomerDiskSpaceOption and
  CustomerUserDatabaseOption to allow multiple options from the same template
  for hosting packages
- fix disk space calculation in CustomerHostingPackage
- implement hostingpackages forms AddDiskspaceOptionForm, AddMailboxOptionForm,
  AddUserDatabaseOptionForm
- implement hostingpackages.views.AddHostingOption
- add new URL pattern add_hosting_option to hostingpackages.urls
- add template hostingpackages/add_hosting_option.html
- link items on hostingpackages/customerhostingpackage_option_choices.html to
  add_hosting_option
This commit is contained in:
Jan Dittberner 2015-01-25 15:15:39 +01:00
parent 9815bd1f5b
commit 0fc823a305
8 changed files with 229 additions and 14 deletions

View file

@ -14,7 +14,12 @@ from crispy_forms.layout import (
Submit, Submit,
) )
from .models import CustomerHostingPackage from .models import (
CustomerDiskSpaceOption,
CustomerHostingPackage,
CustomerMailboxOption,
CustomerUserDatabaseOption,
)
class CreateCustomerHostingPackageForm(forms.ModelForm): class CreateCustomerHostingPackageForm(forms.ModelForm):
@ -68,3 +73,79 @@ class CreateHostingPackageForm(forms.ModelForm):
'description', 'description',
Submit('submit', _('Add Hosting Package')), Submit('submit', _('Add Hosting Package')),
) )
class AddDiskspaceOptionForm(forms.ModelForm):
class Meta:
model = CustomerDiskSpaceOption
fields = ['diskspace', 'diskspace_unit']
def __init__(self, *args, **kwargs):
self.hostingpackage = kwargs.pop('hostingpackage')
self.option_template = kwargs.pop('option_template')
super(AddDiskspaceOptionForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_action = reverse(
'add_hosting_option',
kwargs={
'package': self.hostingpackage.id,
'type': 'diskspace',
'optionid': self.option_template.id,
})
self.helper.add_input(Submit('submit', _('Add disk space option')))
def save(self, commit=True):
self.instance.hosting_package = self.hostingpackage
self.instance.template = self.option_template
return super(AddDiskspaceOptionForm, self).save(commit=True)
class AddMailboxOptionForm(forms.ModelForm):
class Meta:
model = CustomerMailboxOption
fields = ['number']
def __init__(self, *args, **kwargs):
self.hostingpackage = kwargs.pop('hostingpackage')
self.option_template = kwargs.pop('option_template')
super(AddMailboxOptionForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_action = reverse(
'add_hosting_option',
kwargs={
'package': self.hostingpackage.id,
'type': 'mailboxes',
'optionid': self.option_template.id,
})
self.helper.add_input(Submit('submit', _('Add mailbox option')))
def save(self, commit=True):
self.instance.hosting_package = self.hostingpackage
self.instance.template = self.option_template
return super(AddMailboxOptionForm, self).save(commit=True)
class AddUserDatabaseOptionForm(forms.ModelForm):
class Meta:
model = CustomerUserDatabaseOption
fields = ['number']
def __init__(self, *args, **kwargs):
self.hostingpackage = kwargs.pop('hostingpackage')
self.option_template = kwargs.pop('option_template')
super(AddUserDatabaseOptionForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_action = reverse(
'add_hosting_option',
kwargs={
'package': self.hostingpackage.id,
'type': 'databases',
'optionid': self.option_template.id,
})
self.helper.add_input(Submit('submit', _('Add database option')))
def save(self, commit=True):
self.instance.hosting_package = self.hostingpackage
self.instance.template = self.option_template
self.instance.db_type = self.option_template.db_type
return super(AddUserDatabaseOptionForm, self).save(commit=True)

View file

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('hostingpackages', '0004_customerhostingpackagedomain'),
]
operations = [
migrations.AlterModelOptions(
name='diskspaceoption',
options={},
),
migrations.AlterUniqueTogether(
name='customerdiskspaceoption',
unique_together=set([]),
),
]

View file

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('hostingpackages', '0005_auto_20150125_1508'),
]
operations = [
migrations.AlterModelOptions(
name='userdatabaseoption',
options={},
),
migrations.AlterUniqueTogether(
name='customeruserdatabaseoption',
unique_together=set([]),
),
]

View file

@ -80,7 +80,6 @@ class DiskSpaceOptionBase(models.Model):
class Meta: class Meta:
abstract = True abstract = True
ordering = ['diskspace_unit', 'diskspace'] ordering = ['diskspace_unit', 'diskspace']
unique_together = ['diskspace', 'diskspace_unit']
verbose_name = _('Disk space option') verbose_name = _('Disk space option')
verbose_name_plural = _('Disk space options') verbose_name_plural = _('Disk space options')
@ -95,6 +94,8 @@ class DiskSpaceOption(DiskSpaceOptionBase, HostingOption):
existing hosting packages. existing hosting packages.
""" """
class Meta:
unique_together = ['diskspace', 'diskspace_unit']
@python_2_unicode_compatible @python_2_unicode_compatible
@ -107,7 +108,6 @@ class UserDatabaseOptionBase(models.Model):
class Meta: class Meta:
abstract = True abstract = True
ordering = ['db_type', 'number'] ordering = ['db_type', 'number']
unique_together = ['number', 'db_type']
verbose_name = _('Database option') verbose_name = _('Database option')
verbose_name_plural = _('Database options') verbose_name_plural = _('Database options')
@ -127,6 +127,8 @@ class UserDatabaseOption(UserDatabaseOptionBase, HostingOption):
hosting packages. hosting packages.
""" """
class Meta:
unique_together = ['number', 'db_type']
@python_2_unicode_compatible @python_2_unicode_compatible
@ -267,7 +269,7 @@ class CustomerHostingPackage(HostingPackageBase):
options = CustomerDiskSpaceOption.objects.filter(hosting_package=self) options = CustomerDiskSpaceOption.objects.filter(hosting_package=self)
for option in options: for option in options:
if option.diskspace_unit == min_unit: if option.diskspace_unit == min_unit:
diskspace += option.disk_space diskspace += option.diskspace
elif option.diskspace_unit > min_unit: elif option.diskspace_unit > min_unit:
diskspace += ( diskspace += (
DISK_SPACE_FACTORS[option.diskspace_unit][min_unit] * DISK_SPACE_FACTORS[option.diskspace_unit][min_unit] *

View file

@ -7,6 +7,7 @@ from __future__ import absolute_import, unicode_literals
from django.conf.urls import patterns, url from django.conf.urls import patterns, url
from .views import ( from .views import (
AddHostingOption,
AllCustomerHostingPackageList, AllCustomerHostingPackageList,
CreateCustomerHostingPackage, CreateCustomerHostingPackage,
CreateHostingPackage, CreateHostingPackage,
@ -26,9 +27,9 @@ urlpatterns = patterns(
CustomerHostingPackageDetails.as_view(), CustomerHostingPackageDetails.as_view(),
name='hosting_package_details'), name='hosting_package_details'),
url(r'^allpackages/', url(r'^allpackages/',
AllCustomerHostingPackageList.as_view(), AllCustomerHostingPackageList.as_view(), name='all_hosting_packages'),
name='all_hosting_packages'),
url(r'^(?P<pk>\d+)/option-choices$', url(r'^(?P<pk>\d+)/option-choices$',
HostingOptionChoices.as_view(), HostingOptionChoices.as_view(), name='hosting_option_choices'),
name='hosting_option_choices'), url(r'^(?P<package>\d+)/add-option/(?P<type>\w+)/(?P<optionid>\d+)$',
AddHostingOption.as_view(), name='add_hosting_option'),
) )

View file

@ -5,13 +5,17 @@ This module defines views related to hosting packages.
from __future__ import absolute_import, unicode_literals from __future__ import absolute_import, unicode_literals
from django.conf import settings from django.conf import settings
from django.http import Http404
from django.shortcuts import redirect, get_object_or_404 from django.shortcuts import redirect, get_object_or_404
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.views.generic import ( from django.views.generic import (
DetailView, DetailView,
ListView, ListView,
) )
from django.views.generic.edit import CreateView from django.views.generic.edit import (
CreateView,
FormView,
)
from django.contrib import messages from django.contrib import messages
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
@ -23,6 +27,9 @@ from braces.views import (
from gvacommon.viewmixins import StaffOrSelfLoginRequiredMixin from gvacommon.viewmixins import StaffOrSelfLoginRequiredMixin
from .forms import ( from .forms import (
AddDiskspaceOptionForm,
AddMailboxOptionForm,
AddUserDatabaseOptionForm,
CreateCustomerHostingPackageForm, CreateCustomerHostingPackageForm,
CreateHostingPackageForm, CreateHostingPackageForm,
) )
@ -137,11 +144,83 @@ class HostingOptionChoices(
'customer': self.get_object().customer, 'customer': self.get_object().customer,
'hosting_options': ( 'hosting_options': (
(_('Disk space'), (_('Disk space'),
DiskSpaceOption.objects.all()), [(option, 'diskspace') for option in
DiskSpaceOption.objects.all()]),
(_('Mailboxes'), (_('Mailboxes'),
MailboxOption.objects.all()), [(option, 'mailboxes') for option in
MailboxOption.objects.all()]),
(_('Databases'), (_('Databases'),
UserDatabaseOption.objects.all()) [(option, 'databases') for option in
UserDatabaseOption.objects.all()]),
), ),
}) })
return context return context
class AddHostingOption(
LoginRequiredMixin, StaffuserRequiredMixin, FormView
):
template_name = 'hostingpackages/add_hosting_option.html'
def get_form_class(self):
optiontype = self.kwargs['type']
if optiontype == 'diskspace':
return AddDiskspaceOptionForm
elif optiontype == 'mailboxes':
return AddMailboxOptionForm
elif optiontype == 'databases':
return AddUserDatabaseOptionForm
raise Http404()
def get_hosting_package(self):
return get_object_or_404(
CustomerHostingPackage, pk=int(self.kwargs['package']))
def get_option_template(self):
optiontype = self.kwargs['type']
optionid = int(self.kwargs['optionid'])
if optiontype == 'diskspace':
return get_object_or_404(DiskSpaceOption, pk=optionid)
elif optiontype == 'mailboxes':
return get_object_or_404(MailboxOption, pk=optionid)
elif optiontype == 'databases':
return get_object_or_404(UserDatabaseOption, pk=optionid)
raise Http404()
def get_form_kwargs(self):
kwargs = super(AddHostingOption, self).get_form_kwargs()
kwargs['hostingpackage'] = self.get_hosting_package()
kwargs['option_template'] = self.get_option_template()
return kwargs
def get_initial(self):
initial = super(AddHostingOption, self).get_initial()
template = self.get_option_template()
if type(template) == DiskSpaceOption:
initial.update({
'diskspace': template.diskspace,
'diskspace_unit': template.diskspace_unit,
})
elif type(template) == MailboxOption:
initial['number'] = template.number
elif type(template) == UserDatabaseOption:
initial['number'] = template.number
else:
raise Http404()
return initial
def get_context_data(self, **kwargs):
context = super(AddHostingOption, self).get_context_data(**kwargs)
context['option_template'] = self.get_option_template()
return context
def form_valid(self, form):
option = form.save()
hosting_package = self.get_hosting_package()
messages.success(
self.request,
_("Successfully added option {option} to hosting package "
"{package}.").format(
option=option, package=hosting_package.name)
)
return redirect(hosting_package)

View file

@ -0,0 +1,8 @@
{% extends "hostingpackages/base.html" %}
{% load i18n crispy_forms_tags %}
{% block title %}{{ block.super }} - {% blocktrans with package=hostingpackage.name full_name=customer.get_full_name %}Add Option to Hosting Package {{ package }} of Customer {{ full_name }}{% endblocktrans %}{% endblock title %}
{% block page_title %}{% blocktrans with package=hostingpackage.name full_name=customer.get_full_name %}Add Option to Hosting Package {{ package }} of Customer {{ full_name }}{% endblocktrans %}{% endblock page_title %}
{% block content %}
{% crispy form %}
{% endblock content %}

View file

@ -12,8 +12,8 @@
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading">{{ label }}</div> <div class="panel-heading">{{ label }}</div>
<ul class="list-group"> <ul class="list-group">
{% for item in items %} {% for item, option_type in items %}
<li class="list-group-item"><a href="#"><i class="glyphicon glyphicon-plus-sign"></i> {{ item }}</a></li> <li class="list-group-item"><a href="{% url 'add_hosting_option' package=hostingpackage.id type=option_type optionid=item.id %}"><i class="glyphicon glyphicon-plus-sign"></i> {{ item }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
</div> </div>