Random stuff
This commit is contained in:
parent
157fd54ce5
commit
4e3105194c
|
@ -55,7 +55,7 @@ def action_with_confirmation(action_name, extra_context={},
|
||||||
(action_name, objects_name),
|
(action_name, objects_name),
|
||||||
"action_name": action_name.capitalize(),
|
"action_name": action_name.capitalize(),
|
||||||
"action_value": action_value,
|
"action_value": action_value,
|
||||||
"deletable_objects": queryset,
|
"display_objects": queryset,
|
||||||
'queryset': queryset,
|
'queryset': queryset,
|
||||||
"opts": opts,
|
"opts": opts,
|
||||||
"app_label": app_label,
|
"app_label": app_label,
|
||||||
|
|
|
@ -3,7 +3,7 @@ from django.core.urlresolvers import reverse
|
||||||
from django.utils.text import capfirst
|
from django.utils.text import capfirst
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.core import services
|
from orchestra.core import services, accounts
|
||||||
from orchestra.utils.apps import isinstalled
|
from orchestra.utils.apps import isinstalled
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,47 +28,39 @@ def api_link(context):
|
||||||
|
|
||||||
|
|
||||||
def get_services():
|
def get_services():
|
||||||
result = []
|
childrens = []
|
||||||
for model, options in services.get().iteritems():
|
for model, options in services.get().iteritems():
|
||||||
if options.get('menu', True):
|
if options.get('menu', True):
|
||||||
opts = model._meta
|
opts = model._meta
|
||||||
url = reverse('admin:{}_{}_changelist'.format(
|
url = reverse('admin:{}_{}_changelist'.format(
|
||||||
opts.app_label, opts.model_name))
|
opts.app_label, opts.model_name))
|
||||||
name = capfirst(options.get('verbose_name_plural'))
|
name = capfirst(options.get('verbose_name_plural'))
|
||||||
result.append(items.MenuItem(name, url))
|
childrens.append(items.MenuItem(name, url))
|
||||||
return sorted(result, key=lambda i: i.title)
|
return sorted(childrens, key=lambda i: i.title)
|
||||||
|
|
||||||
|
|
||||||
def get_account_items():
|
def get_accounts():
|
||||||
childrens = [
|
childrens = [
|
||||||
items.MenuItem(_("Accounts"),
|
items.MenuItem(_("Accounts"),
|
||||||
reverse('admin:accounts_account_changelist'))
|
reverse('admin:accounts_account_changelist'))
|
||||||
]
|
]
|
||||||
if isinstalled('orchestra.apps.contacts'):
|
|
||||||
url = reverse('admin:contacts_contact_changelist')
|
|
||||||
childrens.append(items.MenuItem(_("Contacts"), url))
|
|
||||||
if isinstalled('orchestra.apps.users'):
|
if isinstalled('orchestra.apps.users'):
|
||||||
url = reverse('admin:users_user_changelist')
|
url = reverse('admin:users_user_changelist')
|
||||||
childrens.append(items.MenuItem(_("Users"), url))
|
childrens.append(items.MenuItem(_("Users"), url))
|
||||||
if isinstalled('orchestra.apps.orders'):
|
|
||||||
url = reverse('admin:orders_plan_changelist')
|
|
||||||
childrens.append(items.MenuItem(_("Plans"), url))
|
|
||||||
url = reverse('admin:orders_order_changelist')
|
|
||||||
childrens.append(items.MenuItem(_("Orders"), url))
|
|
||||||
if isinstalled('orchestra.apps.bills'):
|
|
||||||
url = reverse('admin:bills_bill_changelist')
|
|
||||||
childrens.append(items.MenuItem(_("Bills"), url))
|
|
||||||
if isinstalled('orchestra.apps.payments'):
|
if isinstalled('orchestra.apps.payments'):
|
||||||
url = reverse('admin:payments_transaction_changelist')
|
|
||||||
childrens.append(items.MenuItem(_("Transactions"), url))
|
|
||||||
url = reverse('admin:payments_transactionprocess_changelist')
|
url = reverse('admin:payments_transactionprocess_changelist')
|
||||||
childrens.append(items.MenuItem(_("Transaction processes"), url))
|
childrens.append(items.MenuItem(_("Transaction processes"), url))
|
||||||
url = reverse('admin:payments_paymentsource_changelist')
|
|
||||||
childrens.append(items.MenuItem(_("Payment sources"), url))
|
|
||||||
if isinstalled('orchestra.apps.issues'):
|
if isinstalled('orchestra.apps.issues'):
|
||||||
url = reverse('admin:issues_ticket_changelist')
|
url = reverse('admin:issues_ticket_changelist')
|
||||||
childrens.append(items.MenuItem(_("Tickets"), url))
|
childrens.append(items.MenuItem(_("Tickets"), url))
|
||||||
return childrens
|
for model, options in accounts.get().iteritems():
|
||||||
|
if options.get('menu', True):
|
||||||
|
opts = model._meta
|
||||||
|
url = reverse('admin:{}_{}_changelist'.format(
|
||||||
|
opts.app_label, opts.model_name))
|
||||||
|
name = capfirst(options.get('verbose_name_plural'))
|
||||||
|
childrens.append(items.MenuItem(name, url))
|
||||||
|
return sorted(childrens, key=lambda i: i.title)
|
||||||
|
|
||||||
|
|
||||||
def get_administration_items():
|
def get_administration_items():
|
||||||
|
@ -128,7 +120,7 @@ class OrchestraMenu(Menu):
|
||||||
items.MenuItem(
|
items.MenuItem(
|
||||||
_("Accounts"),
|
_("Accounts"),
|
||||||
reverse('admin:accounts_account_changelist'),
|
reverse('admin:accounts_account_changelist'),
|
||||||
children=get_account_items()
|
children=get_accounts()
|
||||||
),
|
),
|
||||||
items.MenuItem(
|
items.MenuItem(
|
||||||
_("Administration"),
|
_("Administration"),
|
||||||
|
|
|
@ -48,7 +48,7 @@ def close_bills(modeladmin, request, queryset):
|
||||||
SelectSourceFormSet = adminmodelformset_factory(modeladmin, SelectSourceForm,
|
SelectSourceFormSet = adminmodelformset_factory(modeladmin, SelectSourceForm,
|
||||||
extra=0)
|
extra=0)
|
||||||
formset = SelectSourceFormSet(queryset=queryset)
|
formset = SelectSourceFormSet(queryset=queryset)
|
||||||
if request.POST.get('post') == 'yes':
|
if request.POST.get('post') == 'generic_confirmation':
|
||||||
formset = SelectSourceFormSet(request.POST, request.FILES, queryset=queryset)
|
formset = SelectSourceFormSet(request.POST, request.FILES, queryset=queryset)
|
||||||
if formset.is_valid():
|
if formset.is_valid():
|
||||||
for form in formset.forms:
|
for form in formset.forms:
|
||||||
|
@ -58,17 +58,19 @@ def close_bills(modeladmin, request, queryset):
|
||||||
return
|
return
|
||||||
opts = modeladmin.model._meta
|
opts = modeladmin.model._meta
|
||||||
context = {
|
context = {
|
||||||
'title': "Are you sure?",
|
'title': _("Are you sure about closing the following bills?"),
|
||||||
|
'content_message': _("Once a bill is closed it can not be further modified.</p>"
|
||||||
|
"<p>Please select a payment source for the selected bills"),
|
||||||
|
'action_name': 'Close bills',
|
||||||
'action_value': 'close_bills',
|
'action_value': 'close_bills',
|
||||||
'deletable_objects': queryset,
|
'display_objects': [],
|
||||||
'queryset': queryset,
|
'queryset': queryset,
|
||||||
'opts': opts,
|
'opts': opts,
|
||||||
'app_label': opts.app_label,
|
'app_label': opts.app_label,
|
||||||
'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME,
|
'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME,
|
||||||
'formset': formset,
|
'formset': formset,
|
||||||
}
|
}
|
||||||
# TODO use generic confirmation template
|
return render(request, 'admin/orchestra/generic_confirmation.html', context)
|
||||||
return render(request, 'admin/bills/close_confirmation.html', context)
|
|
||||||
close_bills.verbose_name = _("Close")
|
close_bills.verbose_name = _("Close")
|
||||||
close_bills.url_name = 'close'
|
close_bills.url_name = 'close'
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,6 @@ class BudgetLineInline(admin.TabularInline):
|
||||||
fields = ('description', 'rate', 'amount', 'tax', 'total')
|
fields = ('description', 'rate', 'amount', 'tax', 'total')
|
||||||
|
|
||||||
|
|
||||||
# TODO hide raw when status = oPen
|
|
||||||
class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
list_display = (
|
list_display = (
|
||||||
'number', 'status', 'type_link', 'account_link', 'created_on_display',
|
'number', 'status', 'type_link', 'account_link', 'created_on_display',
|
||||||
|
@ -83,9 +82,10 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
num_lines.short_description = _("lines")
|
num_lines.short_description = _("lines")
|
||||||
|
|
||||||
def display_total(self, bill):
|
def display_total(self, bill):
|
||||||
return "%s &%s;" % (bill.get_total(), settings.BILLS_CURRENCY.lower())
|
return "%s &%s;" % (bill.total, settings.BILLS_CURRENCY.lower())
|
||||||
display_total.allow_tags = True
|
display_total.allow_tags = True
|
||||||
display_total.short_description = _("total")
|
display_total.short_description = _("total")
|
||||||
|
display_total.admin_order_field = 'total'
|
||||||
|
|
||||||
def type_link(self, bill):
|
def type_link(self, bill):
|
||||||
bill_type = bill.type.lower()
|
bill_type = bill.type.lower()
|
||||||
|
@ -101,6 +101,12 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
fields += self.add_fields
|
fields += self.add_fields
|
||||||
return fields
|
return fields
|
||||||
|
|
||||||
|
def get_fieldsets(self, request, obj=None):
|
||||||
|
fieldsets = super(BillAdmin, self).get_fieldsets(request, obj=obj)
|
||||||
|
if obj and obj.status == obj.OPEN:
|
||||||
|
fieldsets = (fieldsets[0],)
|
||||||
|
return fieldsets
|
||||||
|
|
||||||
def get_change_view_actions(self, obj=None):
|
def get_change_view_actions(self, obj=None):
|
||||||
actions = super(BillAdmin, self).get_change_view_actions(obj)
|
actions = super(BillAdmin, self).get_change_view_actions(obj)
|
||||||
discard = []
|
discard = []
|
||||||
|
|
|
@ -26,7 +26,7 @@ class SelectSourceForm(forms.ModelForm):
|
||||||
bill = kwargs.get('instance')
|
bill = kwargs.get('instance')
|
||||||
if bill:
|
if bill:
|
||||||
sources = bill.account.paymentsources.filter(is_active=True)
|
sources = bill.account.paymentsources.filter(is_active=True)
|
||||||
recharge = bool(bill.get_total() < 0)
|
recharge = bool(bill.total < 0)
|
||||||
choices = [(None, '-----------')]
|
choices = [(None, '-----------')]
|
||||||
for source in sources:
|
for source in sources:
|
||||||
if not recharge or source.method_class().allow_recharge:
|
if not recharge or source.method_class().allow_recharge:
|
||||||
|
|
20
orchestra/apps/bills/migrations/0003_bill_total.py
Normal file
20
orchestra/apps/bills/migrations/0003_bill_total.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import models, migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('bills', '0002_bill_closed_on'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='bill',
|
||||||
|
name='total',
|
||||||
|
field=models.DecimalField(default=10, max_digits=12, decimal_places=2),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
|
@ -57,10 +57,8 @@ class Bill(models.Model):
|
||||||
closed_on = models.DateTimeField(_("closed on"), blank=True, null=True)
|
closed_on = models.DateTimeField(_("closed on"), blank=True, null=True)
|
||||||
due_on = models.DateField(_("due on"), null=True, blank=True)
|
due_on = models.DateField(_("due on"), null=True, blank=True)
|
||||||
last_modified_on = models.DateTimeField(_("last modified on"), auto_now=True)
|
last_modified_on = models.DateTimeField(_("last modified on"), auto_now=True)
|
||||||
#base = models.DecimalField(max_digits=12, decimal_places=2)
|
total = models.DecimalField(max_digits=12, decimal_places=2)
|
||||||
#tax = models.DecimalField(max_digits=12, decimal_places=2)
|
|
||||||
comments = models.TextField(_("comments"), blank=True)
|
comments = models.TextField(_("comments"), blank=True)
|
||||||
# TODO rename to HTML-agnostic term like.. RAW ?
|
|
||||||
html = models.TextField(_("HTML"), blank=True)
|
html = models.TextField(_("HTML"), blank=True)
|
||||||
|
|
||||||
objects = BillManager()
|
objects = BillManager()
|
||||||
|
@ -121,10 +119,9 @@ class Bill(models.Model):
|
||||||
payment = self.account.paymentsources.get_default()
|
payment = self.account.paymentsources.get_default()
|
||||||
if not self.due_on:
|
if not self.due_on:
|
||||||
self.due_on = self.get_due_date(payment=payment)
|
self.due_on = self.get_due_date(payment=payment)
|
||||||
|
self.total = self.get_total()
|
||||||
self.html = self.render(payment=payment)
|
self.html = self.render(payment=payment)
|
||||||
self.transactions.create(
|
self.transactions.create(bill=self, source=payment, amount=self.total)
|
||||||
bill=self, source=payment, amount=self.get_total()
|
|
||||||
)
|
|
||||||
self.closed_on = timezone.now()
|
self.closed_on = timezone.now()
|
||||||
self.status = self.CLOSED
|
self.status = self.CLOSED
|
||||||
self.save()
|
self.save()
|
||||||
|
@ -173,6 +170,8 @@ class Bill(models.Model):
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
if not self.type:
|
if not self.type:
|
||||||
self.type = self.get_type()
|
self.type = self.get_type()
|
||||||
|
if self.status == self.OPEN:
|
||||||
|
self.total = self.get_total()
|
||||||
if not self.number or (self.number.startswith('O') and self.status != self.OPEN):
|
if not self.number or (self.number.startswith('O') and self.status != self.OPEN):
|
||||||
self.set_number()
|
self.set_number()
|
||||||
super(Bill, self).save(*args, **kwargs)
|
super(Bill, self).save(*args, **kwargs)
|
||||||
|
@ -190,7 +189,6 @@ class Bill(models.Model):
|
||||||
|
|
||||||
@cached
|
@cached
|
||||||
def get_total(self):
|
def get_total(self):
|
||||||
# TODO self.total = self.get_total on self.save()
|
|
||||||
total = 0
|
total = 0
|
||||||
for tax, subtotal in self.get_subtotals().iteritems():
|
for tax, subtotal in self.get_subtotals().iteritems():
|
||||||
subtotal, taxes = subtotal
|
subtotal, taxes = subtotal
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
{% extends "admin/base_site.html" %}
|
|
||||||
{% load i18n l10n staticfiles admin_urls %}
|
|
||||||
|
|
||||||
{% block extrastyle %}
|
|
||||||
{{ block.super }}
|
|
||||||
<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="{% static "orchestra/css/hide-inline-id.css" %}" />
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
|
|
||||||
{% block breadcrumbs %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<h1>Are you sure you want to close selected bills</h1>
|
|
||||||
<p>Once a bill is closed it can not be further modified.</p>
|
|
||||||
<p>Please select a payment source for the selected bills </p>
|
|
||||||
<form action="" method="post">{% csrf_token %}
|
|
||||||
<div>
|
|
||||||
<div style="margin:20px;">
|
|
||||||
|
|
||||||
{{ formset.as_admin }}
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
{% for obj in queryset %}
|
|
||||||
<input type="hidden" name="{{ action_checkbox_name }}" value="{{ obj.pk|unlocalize }}" />
|
|
||||||
{% endfor %}
|
|
||||||
<input type="hidden" name="action" value="{{ action_value }}"/>
|
|
||||||
<input type="hidden" name="post" value="yes"/>
|
|
||||||
<input type="submit" value="{% trans "Yes, close bills" %}" />
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,7 @@ class DomainAdmin(ChangeListDefaultFilter, AccountAdminMixin, ExtendedModelAdmin
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
""" Order by structured name and imporve performance """
|
""" Order by structured name and imporve performance """
|
||||||
qs = super(DomainAdmin, self).get_queryset(request)
|
qs = super(DomainAdmin, self).get_queryset(request)
|
||||||
qs = qs.select_related('top', 'account__user')
|
qs = qs.select_related('top')
|
||||||
# qs = qs.select_related('top')
|
# qs = qs.select_related('top')
|
||||||
# For some reason if we do this we know for sure that join table will be called T4
|
# For some reason if we do this we know for sure that join table will be called T4
|
||||||
__ = str(qs.query)
|
__ = str(qs.query)
|
||||||
|
|
|
@ -5,7 +5,7 @@ from django.core.urlresolvers import reverse
|
||||||
from django.shortcuts import render, redirect
|
from django.shortcuts import render, redirect
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.admin.utils import admin_colored, admin_link
|
from orchestra.admin.utils import admin_colored, admin_link, wrap_admin_view
|
||||||
from orchestra.apps.accounts.admin import AccountAdminMixin
|
from orchestra.apps.accounts.admin import AccountAdminMixin
|
||||||
|
|
||||||
from .actions import process_transactions
|
from .actions import process_transactions
|
||||||
|
@ -82,9 +82,8 @@ class PaymentSourceAdmin(AccountAdminMixin, admin.ModelAdmin):
|
||||||
opts = self.model._meta
|
opts = self.model._meta
|
||||||
info = opts.app_label, opts.model_name
|
info = opts.app_label, opts.model_name
|
||||||
select_urls = patterns("",
|
select_urls = patterns("",
|
||||||
# TODO wrap for authentication
|
|
||||||
url("/select-method/$",
|
url("/select-method/$",
|
||||||
self.select_method_view,
|
wrap_admin_view(self, self.select_method_view),
|
||||||
name='%s_%s_select_method' % info),
|
name='%s_%s_select_method' % info),
|
||||||
)
|
)
|
||||||
return select_urls + urls
|
return select_urls + urls
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
{% extends "admin/base_site.html" %}
|
|
||||||
{% load i18n l10n staticfiles admin_urls %}
|
|
||||||
|
|
||||||
{% block extrastyle %}
|
|
||||||
{{ block.super }}
|
|
||||||
<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}" />
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
|
|
||||||
{% block breadcrumbs %}
|
|
||||||
TODO
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<h1>Select a method for the new payment source</h1>
|
|
||||||
<form action="" method="post">{% csrf_token %}
|
|
||||||
<div>
|
|
||||||
<div style="margin:20px;">
|
|
||||||
<ul>
|
|
||||||
{% for name, verbose in methods %}
|
|
||||||
<li><a href="../?method={{ name }}&{{ request.META.QUERY_STRING }}">{{ verbose }}</<a></li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
|
|
|
@ -64,8 +64,7 @@ class AutoresponseInline(admin.StackedInline):
|
||||||
# def queryset(self, request):
|
# def queryset(self, request):
|
||||||
# """ Select related for performance """
|
# """ Select related for performance """
|
||||||
# qs = super(AddressAdmin, self).queryset(request)
|
# qs = super(AddressAdmin, self).queryset(request)
|
||||||
# # TODO django 1.7 account__user is not needed
|
# return qs.select_related('domain')
|
||||||
# return qs.select_related('domain', 'account__user')
|
|
||||||
|
|
||||||
|
|
||||||
class AddressAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
class AddressAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
|
@ -114,8 +113,7 @@ class AddressAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
""" Select related for performance """
|
""" Select related for performance """
|
||||||
qs = super(AddressAdmin, self).get_queryset(request)
|
qs = super(AddressAdmin, self).get_queryset(request)
|
||||||
# TODO django 1.7 account__user is not needed
|
return qs.select_related('domain')
|
||||||
return qs.select_related('domain', 'account__user')
|
|
||||||
|
|
||||||
|
|
||||||
class MailRoleAdmin(RoleAdmin):
|
class MailRoleAdmin(RoleAdmin):
|
||||||
|
|
Loading…
Reference in a new issue