Moved account service management object-tools to cl filters
This commit is contained in:
parent
cc85956e7b
commit
fc44c8bfc0
2
TODO.md
2
TODO.md
|
@ -89,6 +89,4 @@ at + clock time, midnight, noon- At 3:30 p.m., At 4:01, At noon
|
||||||
|
|
||||||
* help_text on readonly_fields specialy Bill.state. (eg. A bill is in OPEN state when bla bla )
|
* help_text on readonly_fields specialy Bill.state. (eg. A bill is in OPEN state when bla bla )
|
||||||
|
|
||||||
* Account link and "show all" button on the filters secction instead of object-tools
|
|
||||||
|
|
||||||
* Create ProForma from orders orders.bill(proforma=True)
|
* Create ProForma from orders orders.bill(proforma=True)
|
||||||
|
|
|
@ -37,8 +37,8 @@ class AdminFormSet(BaseModelFormSet):
|
||||||
return template.render(Context({'inline_admin_formset': inline_admin_formset}))
|
return template.render(Context({'inline_admin_formset': inline_admin_formset}))
|
||||||
|
|
||||||
|
|
||||||
def adminmodelformset_factory(modeladmin, form):
|
def adminmodelformset_factory(modeladmin, form, formset=AdminFormSet, **kwargs):
|
||||||
formset = modelformset_factory(modeladmin.model, extra=0,
|
formset = modelformset_factory(modeladmin.model, form=form, formset=formset,
|
||||||
form=form, formset=AdminFormSet)
|
**kwargs)
|
||||||
formset.modeladmin = modeladmin
|
formset.modeladmin = modeladmin
|
||||||
return formset
|
return formset
|
||||||
|
|
|
@ -198,19 +198,25 @@ class AccountAdminMixin(object):
|
||||||
|
|
||||||
def changelist_view(self, request, extra_context=None):
|
def changelist_view(self, request, extra_context=None):
|
||||||
account_id = request.GET.get('account')
|
account_id = request.GET.get('account')
|
||||||
context = {
|
context = {}
|
||||||
'from_account': False
|
|
||||||
}
|
|
||||||
if account_id:
|
if account_id:
|
||||||
opts = self.model._meta
|
opts = self.model._meta
|
||||||
account = Account.objects.get(pk=account_id)
|
account = Account.objects.get(pk=account_id)
|
||||||
context = {
|
context = {
|
||||||
'from_account': True,
|
|
||||||
'title': _("Select %s to change for %s") % (
|
|
||||||
opts.verbose_name, account.name),
|
|
||||||
'account': not account_id or Account.objects.get(pk=account_id),
|
'account': not account_id or Account.objects.get(pk=account_id),
|
||||||
'account_opts': Account._meta,
|
'account_opts': Account._meta,
|
||||||
|
'all_selected': True,
|
||||||
}
|
}
|
||||||
|
if not request.GET.get('all'):
|
||||||
|
context.update({
|
||||||
|
'all_selected': False,
|
||||||
|
'title': _("Select %s to change for %s") % (
|
||||||
|
opts.verbose_name, account.name),
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
request_copy = request.GET.copy()
|
||||||
|
request_copy.pop('account')
|
||||||
|
request.GET = request_copy
|
||||||
context.update(extra_context or {})
|
context.update(extra_context or {})
|
||||||
return super(AccountAdminMixin, self).changelist_view(request,
|
return super(AccountAdminMixin, self).changelist_view(request,
|
||||||
extra_context=context)
|
extra_context=context)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from django.contrib.admin import SimpleListFilter
|
from django.contrib.admin import SimpleListFilter
|
||||||
|
from django.utils.encoding import force_text
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
{% extends "admin/change_list.html" %}
|
{% extends "admin/change_list.html" %}
|
||||||
{% load i18n admin_urls %}
|
{% load i18n admin_urls admin_list %}
|
||||||
|
|
||||||
|
|
||||||
{% block breadcrumbs %}
|
{% block breadcrumbs %}
|
||||||
<div class="breadcrumbs">
|
<div class="breadcrumbs">
|
||||||
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
|
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
|
||||||
{% if from_account %}
|
{% if account %}
|
||||||
› <a href="{% url 'admin:app_list' app_label=account_opts.app_label %}">{{ account_opts.app_config.verbose_name }}</a>
|
› <a href="{% url 'admin:app_list' app_label=account_opts.app_label %}">{{ account_opts.app_config.verbose_name }}</a>
|
||||||
› <a href="{% url account_opts|admin_urlname:'changelist' %}">{{ account_opts.verbose_name_plural|capfirst }}</a>
|
› <a href="{% url account_opts|admin_urlname:'changelist' %}">{{ account_opts.verbose_name_plural|capfirst }}</a>
|
||||||
› <a href="{% url account_opts|admin_urlname:'change' account.pk|admin_urlquote %}">{{ account|truncatewords:"18" }}</a>
|
› <a href="{% url account_opts|admin_urlname:'change' account.pk|admin_urlquote %}">{{ account|truncatewords:"18" }}</a>
|
||||||
|
@ -18,18 +18,32 @@
|
||||||
|
|
||||||
|
|
||||||
{% block object-tools-items %}
|
{% block object-tools-items %}
|
||||||
{% if from_account %}
|
|
||||||
<li>
|
|
||||||
<a href="{% url account_opts|admin_urlname:'change' account.pk|admin_urlquote %}" class="historylink">{{ account|truncatewords:"18" }}</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="./" class="historylink">{% trans 'Show all' %}</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
<li>
|
<li>
|
||||||
{% url cl.opts|admin_urlname:'add' as add_url %}
|
{% url cl.opts|admin_urlname:'add' as add_url %}
|
||||||
<a href="{% add_preserved_filters add_url is_popup to_field %}" class="addlink">
|
<a href="{% add_preserved_filters add_url is_popup to_field %}" class="addlink">
|
||||||
|
{% if all_selected %}
|
||||||
{% blocktrans with cl.opts.verbose_name as name %}Add {{ name }}{% endblocktrans %}
|
{% blocktrans with cl.opts.verbose_name as name %}Add {{ name }}{% endblocktrans %}
|
||||||
|
{% else %}
|
||||||
|
{% blocktrans with cl.opts.verbose_name as name and account|truncatewords:"18" as account %}Add {{ account }} {{ name }}{% endblocktrans %}
|
||||||
|
{% endif %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block filters %}
|
||||||
|
{% if cl.has_filters %}
|
||||||
|
<div id="changelist-filter">
|
||||||
|
<h2>{% trans 'Filter' %}</h2>
|
||||||
|
{% if account %}
|
||||||
|
<h3>{% trans 'By account' %}</h3>
|
||||||
|
<ul>
|
||||||
|
<li {% if not all_selected %}class="selected"{% endif %}><a href="?account={{ account.pk }}">{{ account|truncatewords:"18" }}</a></li>
|
||||||
|
<li {% if all_selected %}class="selected"{% endif %}><a href="?account={{ account.pk }}&all=True">All</a></li>
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
{% for spec in cl.filter_specs %}{% admin_list_filter cl spec %}{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,8 @@ def close_bills(modeladmin, request, queryset):
|
||||||
if not queryset:
|
if not queryset:
|
||||||
messages.warning(request, _("Selected bills should be in open state"))
|
messages.warning(request, _("Selected bills should be in open state"))
|
||||||
return
|
return
|
||||||
SelectSourceFormSet = adminmodelformset_factory(modeladmin, SelectSourceForm)
|
SelectSourceFormSet = adminmodelformset_factory(modeladmin, SelectSourceForm,
|
||||||
|
extra=0)
|
||||||
formset = SelectSourceFormSet(queryset=queryset)
|
formset = SelectSourceFormSet(queryset=queryset)
|
||||||
if request.POST.get('post') == 'yes':
|
if request.POST.get('post') == 'yes':
|
||||||
formset = SelectSourceFormSet(request.POST, request.FILES, queryset=queryset)
|
formset = SelectSourceFormSet(request.POST, request.FILES, queryset=queryset)
|
||||||
|
@ -66,6 +67,7 @@ def close_bills(modeladmin, request, queryset):
|
||||||
'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/bills/close_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'
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
|
|
||||||
{% block summary %}
|
{% block summary %}
|
||||||
<div id="bill-number">
|
<div id="bill-number">
|
||||||
{{ bill.get_type_display }}<br>
|
{{ bill.get_type_display.capitalize }}<br>
|
||||||
<span class="value">{{ bill.number }}</span><br>
|
<span class="value">{{ bill.number }}</span><br>
|
||||||
</div>
|
</div>
|
||||||
<div id="bill-summary">
|
<div id="bill-summary">
|
||||||
|
@ -125,14 +125,14 @@
|
||||||
{% if payment.message %}
|
{% if payment.message %}
|
||||||
{{ payment.message | safe }}
|
{{ payment.message | safe }}
|
||||||
{% else %}
|
{% else %}
|
||||||
You can pay our invoice by bank transfer. <br>
|
You can pay our {{ bill.get_type_display.lower }} by bank transfer. <br>
|
||||||
Please make sure to state your name and the invoice number.
|
Please make sure to state your name and the {{ bill.get_type_display.lower}} number.
|
||||||
Our bank account number is <br>
|
Our bank account number is <br>
|
||||||
<strong>{{ seller_info.bank_account }}</strong>
|
<strong>{{ seller_info.bank_account }}</strong>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div id="questions">
|
<div id="questions">
|
||||||
<span class="title">QUESTIONS</span> If you have any question about your bill, please
|
<span class="title">QUESTIONS</span> If you have any question about your {{ bill.get_type_display.lower}}, please
|
||||||
feel free to contact us at your convinience. We will reply as soon as we get
|
feel free to contact us at your convinience. We will reply as soon as we get
|
||||||
your message.
|
your message.
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -13,6 +13,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
from orchestra.core import caches, services, accounts
|
from orchestra.core import caches, services, accounts
|
||||||
from orchestra.models import queryset
|
from orchestra.models import queryset
|
||||||
from orchestra.utils.apps import autodiscover
|
from orchestra.utils.apps import autodiscover
|
||||||
|
from orchestra.utils.python import import_class
|
||||||
|
|
||||||
from . import settings, helpers
|
from . import settings, helpers
|
||||||
from .handlers import ServiceHandler
|
from .handlers import ServiceHandler
|
||||||
|
@ -315,9 +316,7 @@ class Order(models.Model):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_bill_backend(cls):
|
def get_bill_backend(cls):
|
||||||
# TODO
|
return import_class(settings.ORDERS_BILLING_BACKEND)()
|
||||||
from .backends import BillsBackend
|
|
||||||
return BillsBackend()
|
|
||||||
|
|
||||||
def cancel(self):
|
def cancel(self):
|
||||||
self.cancelled_on = timezone.now()
|
self.cancelled_on = timezone.now()
|
||||||
|
|
|
@ -12,3 +12,7 @@ ORDERS_SERVICE_DEFAUL_TAX = getattr(settings, 'ORDERS_SERVICE_DFAULT_TAX', 0)
|
||||||
|
|
||||||
|
|
||||||
ORDERS_SERVICE_ANUAL_BILLING_MONTH = getattr(settings, 'ORDERS_SERVICE_ANUAL_BILLING_MONTH', 4)
|
ORDERS_SERVICE_ANUAL_BILLING_MONTH = getattr(settings, 'ORDERS_SERVICE_ANUAL_BILLING_MONTH', 4)
|
||||||
|
|
||||||
|
|
||||||
|
ORDERS_BILLING_BACKEND = getattr(settings, 'ORDERS_BILLING_BACKEND',
|
||||||
|
'orchestra.apps.orders.billing.BillsBackend')
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
|
from .methods import PaymentMethod
|
||||||
def process_transactions(modeladmin, request, queryset):
|
def process_transactions(modeladmin, request, queryset):
|
||||||
for source, transactions in queryset.group_by('source'):
|
for method, transactions in queryset.group_by('source__method'):
|
||||||
if source:
|
if method is not None:
|
||||||
source.method_class().process(transactions)
|
PaymentMethod.get_plugin(method)().process(transactions)
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
from .utils import get_field_value
|
||||||
|
|
||||||
|
|
||||||
def group_by(qset, *fields, **kwargs):
|
def group_by(qset, *fields, **kwargs):
|
||||||
""" group_by iterator with support for multiple nested fields """
|
""" group_by iterator with support for multiple nested fields """
|
||||||
ix = kwargs.get('ix', 0)
|
ix = kwargs.get('ix', 0)
|
||||||
|
@ -6,7 +9,11 @@ def group_by(qset, *fields, **kwargs):
|
||||||
group = []
|
group = []
|
||||||
first = True
|
first = True
|
||||||
for obj in qset:
|
for obj in qset:
|
||||||
current = getattr(obj, fields[ix])
|
try:
|
||||||
|
current = get_field_value(obj, fields[ix])
|
||||||
|
except AttributeError:
|
||||||
|
# Intermediary relation does not exists
|
||||||
|
current = None
|
||||||
if first or current == previous:
|
if first or current == previous:
|
||||||
group.append(obj)
|
group.append(obj)
|
||||||
else:
|
else:
|
||||||
|
|
Loading…
Reference in New Issue