diff --git a/TODO.md b/TODO.md
index d3210342..64a38af9 100644
--- a/TODO.md
+++ b/TODO.md
@@ -90,7 +90,7 @@ Remember that, as always with QuerySets, any subsequent chained methods which im
* mail backend related_models = ('resources__content_type') ??
-* ignore orders (mark orders as ignored)
+* ignore orders (mark orders as ignored), ignore orchestra related orders by default (or do not generate them on the first place) ignore superuser orders?
* Domain backend PowerDNS Bind validation support?
@@ -115,8 +115,6 @@ Remember that, as always with QuerySets, any subsequent chained methods which im
* Separate panel from server passwords? Store passwords on panel? set_password special backend operation?
-* be more explicit about which backends are resources and which are service handling
-
* What fields we really need on contacts? name email phone and what more?
* Redirect junk emails and delete every 30 days?
diff --git a/orchestra/admin/options.py b/orchestra/admin/options.py
index e6a375a5..c90065a4 100644
--- a/orchestra/admin/options.py
+++ b/orchestra/admin/options.py
@@ -86,8 +86,11 @@ class ChangeViewActionsMixin(object):
action = getattr(self, action)
view = action_to_view(action, self)
view.url_name = getattr(action, 'url_name', action.__name__)
- view.verbose_name = getattr(action, 'verbose_name',
+ verbose_name = getattr(action, 'verbose_name',
view.url_name.capitalize().replace('_', ' '))
+ if hasattr(verbose_name, '__call__'):
+ verbose_name = verbose_name(obj)
+ view.verbose_name = verbose_name
view.css_class = getattr(action, 'css_class', 'historylink')
view.description = getattr(action, 'description', '')
views.append(view)
@@ -186,7 +189,7 @@ class SelectPluginAdminMixin(object):
def add_view(self, request, form_url='', extra_context=None):
""" Redirects to select account view if required """
if request.user.is_superuser:
- plugin_value = request.GET.get(self.plugin_field)
+ plugin_value = request.GET.get(self.plugin_field) or request.POST.get(self.plugin_field)
if plugin_value or self.plugin.get_plugins() == 1:
self.plugin_value = plugin_value
if not plugin_value:
diff --git a/orchestra/apps/bills/actions.py b/orchestra/apps/bills/actions.py
index 0bdbc8ed..0c1bebeb 100644
--- a/orchestra/apps/bills/actions.py
+++ b/orchestra/apps/bills/actions.py
@@ -4,37 +4,17 @@ import zipfile
from django.contrib import messages
from django.contrib.admin import helpers
from django.core.urlresolvers import reverse
-from django.http import HttpResponse, HttpResponseServerError
+from django.http import HttpResponse
from django.shortcuts import render
-from django.utils.encoding import force_text
from django.utils.safestring import mark_safe
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import ungettext, ugettext_lazy as _
from orchestra.admin.forms import adminmodelformset_factory
-from orchestra.admin.utils import get_object_from_url
+from orchestra.admin.utils import get_object_from_url, change_url
from orchestra.utils.html import html_to_pdf
from .forms import SelectSourceForm
-
-def validate_contact(bill):
- """ checks if all the preconditions for bill generation are met """
- msg = ''
- if not hasattr(bill.account, 'invoicecontact'):
- account = force_text(bill.account)
- link = reverse('admin:accounts_account_change', args=(bill.account_id,))
- link += '#invoicecontact-group'
- msg += _('Related account "%s" doesn\'t have a declared invoice contact\n') % account
- msg += _('You should provide one') % link
- main = type(bill).account.field.rel.to.get_main()
- if not hasattr(main, 'invoicecontact'):
- account = force_text(main)
- link = reverse('admin:accounts_account_change', args=(main.id,))
- link += '#invoicecontact-group'
- msg += _('Main account "%s" doesn\'t have a declared invoice contact\n') % account
- msg += _('You should provide one') % link
- if msg:
- # TODO custom template
- return HttpResponseServerError(mark_safe(msg))
+from .helpers import validate_contact
def download_bills(modeladmin, request, queryset):
@@ -42,15 +22,14 @@ def download_bills(modeladmin, request, queryset):
stringio = StringIO.StringIO()
archive = zipfile.ZipFile(stringio, 'w')
for bill in queryset:
- html = bill.html or bill.render()
- pdf = html_to_pdf(html)
+ pdf = html_to_pdf(bill.html or bill.render())
archive.writestr('%s.pdf' % bill.number, pdf)
archive.close()
response = HttpResponse(stringio.getvalue(), content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="orchestra-bills.zip"'
return response
bill = queryset.get()
- pdf = html_to_pdf(bill.html)
+ pdf = html_to_pdf(bill.html or bill.render())
return HttpResponse(pdf, content_type='application/pdf')
download_bills.verbose_name = _("Download")
download_bills.url_name = 'download'
@@ -58,9 +37,8 @@ download_bills.url_name = 'download'
def view_bill(modeladmin, request, queryset):
bill = queryset.get()
- error = validate_contact(bill)
- if error:
- return error
+ if not validate_contact(request, bill):
+ return
html = bill.html or bill.render()
return HttpResponse(html)
view_bill.verbose_name = _("View")
@@ -73,20 +51,34 @@ def close_bills(modeladmin, request, queryset):
messages.warning(request, _("Selected bills should be in open state"))
return
for bill in queryset:
- error = validate_contact(bill)
- if error:
- return error
+ if not validate_contact(request, bill):
+ return
SelectSourceFormSet = adminmodelformset_factory(modeladmin, SelectSourceForm, extra=0)
formset = SelectSourceFormSet(queryset=queryset)
if request.POST.get('post') == 'generic_confirmation':
formset = SelectSourceFormSet(request.POST, request.FILES, queryset=queryset)
if formset.is_valid():
+ transactions = []
for form in formset.forms:
source = form.cleaned_data['source']
- form.instance.close(payment=source)
+ transaction = form.instance.close(payment=source)
+ if transaction:
+ transactions.append(transaction)
for bill in queryset:
modeladmin.log_change(request, bill, 'Closed')
messages.success(request, _("Selected bills have been closed"))
+ if transactions:
+ num = len(transactions)
+ if num == 1:
+ url = change_url(transactions[0])
+ else:
+ url = reverse('admin:transactions_transaction_changelist')
+ url += 'id__in=%s' % ','.join([str(t.id) for t in transactions])
+ message = ungettext(
+ _('One related transaction has been created') % url,
+ _('%i related transactions have been created') % (url, num),
+ num)
+ messages.success(request, mark_safe(message))
return
opts = modeladmin.model._meta
context = {
@@ -110,11 +102,10 @@ close_bills.url_name = 'close'
def send_bills(modeladmin, request, queryset):
for bill in queryset:
- error = validate_contact(bill)
- if error:
- return error
+ if not validate_contact(request, bill):
+ return
for bill in queryset:
bill.send()
modeladmin.log_change(request, bill, 'Sent')
-send_bills.verbose_name = _("Send")
+send_bills.verbose_name = lambda bill: _("Resend" if getattr(bill, 'is_sent', False) else "Send")
send_bills.url_name = 'send'
diff --git a/orchestra/apps/bills/admin.py b/orchestra/apps/bills/admin.py
index 5c59bf80..88d5ddad 100644
--- a/orchestra/apps/bills/admin.py
+++ b/orchestra/apps/bills/admin.py
@@ -1,5 +1,5 @@
from django import forms
-from django.contrib import admin, messages
+from django.contrib import admin
from django.contrib.admin.utils import unquote
from django.core.urlresolvers import reverse
from django.db import models
@@ -11,7 +11,7 @@ from orchestra.admin.utils import admin_date
from orchestra.apps.accounts.admin import AccountAdminMixin
from . import settings
-from .actions import download_bills, view_bill, close_bills, send_bills
+from .actions import download_bills, view_bill, close_bills, send_bills, validate_contact
from .filters import BillTypeListFilter
from .models import Bill, Invoice, AmendmentInvoice, Fee, AmendmentFee, ProForma, BillLine
@@ -55,9 +55,9 @@ class BillLineInline(admin.TabularInline):
class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
list_display = (
'number', 'type_link', 'account_link', 'created_on_display',
- 'num_lines', 'display_total', 'display_payment_state', 'is_open'
+ 'num_lines', 'display_total', 'display_payment_state', 'is_open', 'is_sent'
)
- list_filter = (BillTypeListFilter, 'is_open',)
+ list_filter = (BillTypeListFilter, 'is_open', 'is_sent')
add_fields = ('account', 'type', 'is_open', 'due_on', 'comments')
fieldsets = (
(None, {
@@ -97,9 +97,14 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
type_link.admin_order_field = 'type'
def display_payment_state(self, bill):
- topts = bill.transactions.model._meta
- url = reverse('admin:%s_%s_changelist' % (topts.app_label, topts.module_name))
- url += '?bill=%i' % bill.pk
+ t_opts = bill.transactions.model._meta
+ transactions = bill.transactions.all()
+ if len(transactions) == 1:
+ args = (transactions[0].pk,)
+ url = reverse('admin:%s_%s_change' % (t_opts.app_label, t_opts.module_name), args=args)
+ else:
+ url = reverse('admin:%s_%s_changelist' % (t_opts.app_label, t_opts.module_name))
+ url += '?bill=%i' % bill.pk
state = bill.get_payment_state_display().upper()
color = PAYMENT_STATE_COLORS.get(bill.payment_state, 'grey')
return '{name}'.format(
@@ -120,7 +125,7 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
return fieldsets
def get_change_view_actions(self, obj=None):
- actions = super(BillAdmin, self).get_change_view_actions()
+ actions = super(BillAdmin, self).get_change_view_actions(obj=obj)
exclude = []
if obj:
if not obj.is_open:
@@ -143,19 +148,13 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
def get_queryset(self, request):
qs = super(BillAdmin, self).get_queryset(request)
qs = qs.annotate(models.Count('lines'))
- qs = qs.prefetch_related('lines', 'lines__sublines')
+ qs = qs.prefetch_related('lines', 'lines__sublines', 'transactions')
return qs
def change_view(self, request, object_id, **kwargs):
- bill = self.get_object(request, unquote(object_id))
# TODO raise404, here and everywhere
- if not hasattr(bill.account, 'invoicecontact'):
- create_link = reverse('admin:accounts_account_change', args=(bill.account_id,))
- create_link += '#invoicecontact-group'
- messages.warning(request, mark_safe(_(
- 'Be aware, related contact doesn\'t have a billing contact defined, '
- 'bill can not be generated until one is provided' % create_link
- )))
+ bill = self.get_object(request, unquote(object_id))
+ validate_contact(request, bill, error=False)
return super(BillAdmin, self).change_view(request, object_id, **kwargs)
diff --git a/orchestra/apps/bills/helpers.py b/orchestra/apps/bills/helpers.py
new file mode 100644
index 00000000..cc0619fb
--- /dev/null
+++ b/orchestra/apps/bills/helpers.py
@@ -0,0 +1,28 @@
+from django.contrib import messages
+from django.core.urlresolvers import reverse
+from django.utils.encoding import force_text
+from django.utils.safestring import mark_safe
+from django.utils.translation import ugettext_lazy as _
+
+
+def validate_contact(request, bill, error=True):
+ """ checks if all the preconditions for bill generation are met """
+ msg = _('{relation} account "{account}" does not have a declared invoice contact. '
+ 'You should provide one')
+ valid = True
+ send = messages.error if error else messages.warning
+ if not hasattr(bill.account, 'invoicecontact'):
+ account = force_text(bill.account)
+ url = reverse('admin:accounts_account_change', args=(bill.account_id,))
+ message = msg.format(relation=_("Related"), account=account, url=url)
+ send(request, mark_safe(message))
+ valid = False
+ main = type(bill).account.field.rel.to.get_main()
+ if not hasattr(main, 'invoicecontact'):
+ account = force_text(main)
+ url = reverse('admin:accounts_account_change', args=(main.id,))
+ message = msg.format(relation=_("Main"), account=account, url=url)
+ send(request, mark_safe(message))
+ valid = False
+ return valid
+
diff --git a/orchestra/apps/bills/models.py b/orchestra/apps/bills/models.py
index 769d14cd..09c489ee 100644
--- a/orchestra/apps/bills/models.py
+++ b/orchestra/apps/bills/models.py
@@ -81,7 +81,7 @@ class Bill(models.Model):
@cached_property
def payment_state(self):
- if self.is_open:
+ if self.is_open or self.get_type() == self.PROFORMA:
return self.OPEN
secured = self.transactions.secured().amount()
if secured >= self.total:
@@ -136,12 +136,14 @@ class Bill(models.Model):
self.due_on = self.get_due_date(payment=payment)
self.total = self.get_total()
self.html = self.render(payment=payment)
+ transaction = None
if self.get_type() != self.PROFORMA:
- self.transactions.create(bill=self, source=payment, amount=self.total)
+ transaction = self.transactions.create(bill=self, source=payment, amount=self.total)
self.closed_on = timezone.now()
self.is_open = False
self.is_sent = False
self.save()
+ return transaction
def send(self):
html = self.html or self.render()
diff --git a/orchestra/apps/bills/templates/bills/bill-notification.email b/orchestra/apps/bills/templates/bills/bill-notification.email
index 52535d6e..425fc490 100644
--- a/orchestra/apps/bills/templates/bills/bill-notification.email
+++ b/orchestra/apps/bills/templates/bills/bill-notification.email
@@ -1,2 +1,6 @@
{% if subject %}Bill {{ bill.number }}{% endif %}
-{% if message %}Find attached your invoice{% endif %}
+{% if message %}Dear {{ bill.account.username }},
+Find your {{ bill.get_type.lower }} attached.
+
+If you have any question, please write us at support@orchestra.lan
+{% endif %}
diff --git a/orchestra/apps/orchestration/backends.py b/orchestra/apps/orchestration/backends.py
index a5a092ef..911abda7 100644
--- a/orchestra/apps/orchestration/backends.py
+++ b/orchestra/apps/orchestration/backends.py
@@ -1,6 +1,7 @@
from functools import partial
from django.utils import timezone
+from django.utils.translation import ugettext_lazy as _
from orchestra.utils import plugins
@@ -111,6 +112,11 @@ class ServiceBackend(plugins.Plugin):
class ServiceController(ServiceBackend):
actions = ('save', 'delete')
+ abstract = True
+
+ @classmethod
+ def get_verbose_name(cls):
+ return _("[S] %s") % super(ServiceController, cls).get_verbose_name()
@classmethod
def get_backends(cls):
diff --git a/orchestra/apps/orders/actions.py b/orchestra/apps/orders/actions.py
index 4f8fe13b..f9797efa 100644
--- a/orchestra/apps/orders/actions.py
+++ b/orchestra/apps/orders/actions.py
@@ -2,10 +2,11 @@ from django.contrib import admin, messages
from django.core.urlresolvers import reverse
from django.db import transaction
from django.utils.safestring import mark_safe
-from django.utils.translation import ugettext_lazy as _
-from django.utils.translation import ungettext
+from django.utils.translation import ungettext, ugettext_lazy as _
from django.shortcuts import render
+from orchestra.admin.utils import change_url
+
from .forms import (BillSelectedOptionsForm, BillSelectConfirmationForm,
BillSelectRelatedForm)
@@ -38,7 +39,7 @@ class BillSelectedOrders(object):
self.options = dict(
billing_point=form.cleaned_data['billing_point'],
fixed_point=form.cleaned_data['fixed_point'],
- is_proforma=form.cleaned_data['is_proforma'],
+ proforma=form.cleaned_data['proforma'],
new_open=form.cleaned_data['new_open'],
)
if int(request.POST.get('step')) != 3:
@@ -78,14 +79,18 @@ class BillSelectedOrders(object):
if int(request.POST.get('step')) >= 3:
bills = self.queryset.bill(commit=True, **self.options)
for order in self.queryset:
- self.modeladmin.log_change(request, order, 'Billed')
+ self.modeladmin.log_change(request, order, _("Billed"))
if not bills:
msg = _("Selected orders do not have pending billing")
self.modeladmin.message_user(request, msg, messages.WARNING)
else:
- ids = ','.join([str(bill.id) for bill in bills])
- url = reverse('admin:bills_bill_changelist')
- url += '?id__in=%s' % ids
+ num = len(bills)
+ if num == 1:
+ url = change_url(bills[0])
+ else:
+ url = reverse('admin:bills_bill_changelist')
+ ids = ','.join([str(bill.id) for bill in bills])
+ url += '?id__in=%s' % ids
num = len(bills)
msg = ungettext(
'One bill has been created.',
diff --git a/orchestra/apps/orders/forms.py b/orchestra/apps/orders/forms.py
index 31cce901..c96da35a 100644
--- a/orchestra/apps/orders/forms.py
+++ b/orchestra/apps/orders/forms.py
@@ -18,7 +18,7 @@ class BillSelectedOptionsForm(AdminFormMixin, forms.Form):
label=_("Fixed point"),
help_text=_("Deisgnates whether you want the billing point to be an "
"exact date, or adapt it to the billing period."))
- is_proforma = forms.BooleanField(initial=False, required=False,
+ proforma = forms.BooleanField(initial=False, required=False,
label=_("Pro-forma (billing simulation)"),
help_text=_("Creates a Pro Forma instead of billing the orders."))
new_open = forms.BooleanField(initial=False, required=False,
@@ -49,7 +49,7 @@ class BillSelectRelatedForm(AdminFormMixin, forms.Form):
required=False)
billing_point = forms.DateField(widget=forms.HiddenInput())
fixed_point = forms.BooleanField(widget=forms.HiddenInput(), required=False)
- is_proforma = forms.BooleanField(widget=forms.HiddenInput(), required=False)
+ proforma = forms.BooleanField(widget=forms.HiddenInput(), required=False)
create_new_open = forms.BooleanField(widget=forms.HiddenInput(), required=False)
def __init__(self, *args, **kwargs):
@@ -63,5 +63,5 @@ class BillSelectRelatedForm(AdminFormMixin, forms.Form):
class BillSelectConfirmationForm(AdminFormMixin, forms.Form):
billing_point = forms.DateField(widget=forms.HiddenInput())
fixed_point = forms.BooleanField(widget=forms.HiddenInput(), required=False)
- is_proforma = forms.BooleanField(widget=forms.HiddenInput(), required=False)
+ proforma = forms.BooleanField(widget=forms.HiddenInput(), required=False)
create_new_open = forms.BooleanField(widget=forms.HiddenInput(), required=False)
diff --git a/orchestra/apps/payments/admin.py b/orchestra/apps/payments/admin.py
index f58818d5..843f248f 100644
--- a/orchestra/apps/payments/admin.py
+++ b/orchestra/apps/payments/admin.py
@@ -92,7 +92,7 @@ class TransactionAdmin(ChangeViewActionsMixin, AccountAdminMixin, admin.ModelAdm
class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
list_display = ('id', 'file_url', 'display_transactions', 'created_at')
- fields = ('data', 'file_url', 'display_transactions', 'created_at')
+ fields = ('data', 'file_url', 'created_at')
readonly_fields = ('file_url', 'display_transactions', 'created_at')
inlines = [TransactionInline]
actions = (actions.mark_process_as_executed, actions.abort, actions.commit)
@@ -111,16 +111,17 @@ class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
# Because of values_list this query doesn't benefit from prefetch_related
tx_ids = process.transactions.values_list('id', flat=True)
for tx_id in tx_ids:
- ids.append(str(tx_id))
+ ids.append('#%i' % tx_id)
counter += 1
if counter > 10:
counter = 0
lines.append(','.join(ids))
ids = []
lines.append(','.join(ids))
+ transactions = '
%s' % (url, '
'.join(lines))
+ return '%s' % (url, transactions)
display_transactions.short_description = _("Transactions")
display_transactions.allow_tags = True
diff --git a/orchestra/apps/payments/methods/sepadirectdebit.py b/orchestra/apps/payments/methods/sepadirectdebit.py
index 9ca73693..f364b0df 100644
--- a/orchestra/apps/payments/methods/sepadirectdebit.py
+++ b/orchestra/apps/payments/methods/sepadirectdebit.py
@@ -175,10 +175,10 @@ class SEPADirectDebit(PaymentMethod):
def get_debt_transactions(cls, transactions, process):
for transaction in transactions:
transaction.process = process
+ transaction.state = transaction.WAITTING_EXECUTION
+ transaction.save(update_fields=['state', 'process'])
account = transaction.account
data = transaction.source.data
- transaction.state = transaction.WAITTING_CONFIRMATION
- transaction.save(update_fields=['state'])
yield E.DrctDbtTxInf( # Direct Debit Transaction Info
E.PmtId( # Payment Id
E.EndToEndId(str(transaction.id)) # Payment Id/End to End
@@ -191,7 +191,7 @@ class SEPADirectDebit(PaymentMethod):
E.MndtRltdInf( # Mandate Related Info
E.MndtId(str(account.id)), # Mandate Id
E.DtOfSgntr( # Date of Signature
- account.register_date.strftime("%Y-%m-%d")
+ account.date_joined.strftime("%Y-%m-%d")
)
)
),
@@ -216,10 +216,10 @@ class SEPADirectDebit(PaymentMethod):
def get_credit_transactions(transactions, process):
for transaction in transactions:
transaction.process = process
+ transaction.state = transaction.WAITTING_EXECUTION
+ transaction.save(update_fields=['state', 'process'])
account = transaction.account
data = transaction.source.data
- transaction.state = transaction.WAITTING_CONFIRMATION
- transaction.save(update_fields=['state'])
yield E.CdtTrfTxInf( # Credit Transfer Transaction Info
E.PmtId( # Payment Id
E.EndToEndId(str(transaction.id)) # Payment Id/End to End
diff --git a/orchestra/apps/payments/models.py b/orchestra/apps/payments/models.py
index b3684122..3ad2f259 100644
--- a/orchestra/apps/payments/models.py
+++ b/orchestra/apps/payments/models.py
@@ -104,7 +104,7 @@ class Transaction(models.Model):
objects = TransactionQuerySet.as_manager()
def __unicode__(self):
- return "Transaction {}".format(self.id)
+ return "Transaction #{}".format(self.id)
@property
def account(self):
@@ -162,7 +162,7 @@ class TransactionProcess(models.Model):
verbose_name_plural = _("Transaction processes")
def __unicode__(self):
- return str(self.id)
+ return '#%i' % self.id
def mark_as_executed(self):
assert self.state == self.CREATED
diff --git a/orchestra/apps/resources/backends.py b/orchestra/apps/resources/backends.py
index fae87831..754ccebf 100644
--- a/orchestra/apps/resources/backends.py
+++ b/orchestra/apps/resources/backends.py
@@ -3,6 +3,7 @@ import datetime
from django.contrib.contenttypes.models import ContentType
from django.utils import timezone
from django.utils.functional import cached_property
+from django.utils.translation import ugettext_lazy as _
from orchestra.apps.orchestration import ServiceBackend
@@ -13,15 +14,19 @@ class ServiceMonitor(ServiceBackend):
MEMORY = 'memory'
CPU = 'cpu'
# TODO UNITS
-
actions = ('monitor', 'exceeded', 'recovery')
+ abstract = True
@classmethod
def get_backends(cls):
- """ filter monitor classes """
- for backend in cls.plugins:
- if backend != ServiceMonitor and ServiceMonitor in backend.__mro__:
- yield backend
+ """ filter controller classes """
+ return [
+ plugin for plugin in cls.plugins if ServiceMonitor in plugin.__mro__
+ ]
+
+ @classmethod
+ def get_verbose_name(cls):
+ return _("[M] %s") % super(ServiceMonitor, cls).get_verbose_name()
@cached_property
def current_date(self):
diff --git a/orchestra/apps/saas/services/wordpress.py b/orchestra/apps/saas/services/wordpress.py
index fd5bbde5..4f4f66c8 100644
--- a/orchestra/apps/saas/services/wordpress.py
+++ b/orchestra/apps/saas/services/wordpress.py
@@ -1,4 +1,5 @@
from django import forms
+from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from orchestra.forms import PluginDataForm
@@ -6,16 +7,24 @@ from orchestra.forms import PluginDataForm
from .options import SoftwareService
-class WordpressForm(PluginDataForm):
+class WordPressForm(PluginDataForm):
username = forms.CharField(label=_("Username"), max_length=64)
password = forms.CharField(label=_("Password"), max_length=64)
site_name = forms.CharField(label=_("Site name"), max_length=64,
help_text=_("URL will be <site_name>.blogs.orchestra.lan"))
email = forms.EmailField(label=_("Email"))
+
+ def __init__(self, *args, **kwargs):
+ super(WordPressForm, self).__init__(*args, **kwargs)
+ instance = kwargs.get('instance')
+ if instance:
+ url = 'http://%s.%s' % (instance.data['site_name'], 'blogs.orchestra.lan')
+ url = '%s' % (url, url)
+ self.fields['site_name'].help_text = mark_safe(url)
class WordpressService(SoftwareService):
verbose_name = "WordPress"
- form = WordpressForm
+ form = WordPressForm
description_field = 'site_name'
icon = 'saas/icons/WordPress.png'
diff --git a/orchestra/templates/admin/orchestra/select_plugin.html b/orchestra/templates/admin/orchestra/select_plugin.html
index dbe419b6..b5421f5e 100644
--- a/orchestra/templates/admin/orchestra/select_plugin.html
+++ b/orchestra/templates/admin/orchestra/select_plugin.html
@@ -28,7 +28,7 @@
{% else %}