Random stuff

This commit is contained in:
Marc 2014-09-08 15:10:16 +00:00
parent 157fd54ce5
commit 4e3105194c
12 changed files with 61 additions and 111 deletions

View File

@ -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,

View File

@ -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"),

View File

@ -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'

View File

@ -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 = []

View File

@ -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:

View 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,
),
]

View File

@ -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

View File

@ -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 %}

View File

@ -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)

View File

@ -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

View File

@ -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 %}

View File

@ -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):