Implemented payments source selection

This commit is contained in:
Marc 2014-09-06 10:56:30 +00:00
parent 4c603bf584
commit cc85956e7b
8 changed files with 98 additions and 28 deletions

View File

@ -86,3 +86,9 @@ at + clock time, midnight, noon- At 3:30 p.m., At 4:01, At noon
from django.utils import translation from django.utils import translation
with translation.override('en'): with translation.override('en'):
* Plurals! * Plurals!
* 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)

View File

@ -1,5 +1,6 @@
from django.contrib.admin import helpers
from django.forms.models import modelformset_factory, BaseModelFormSet
from django.template import Template, Context from django.template import Template, Context
from django.contrib.admin.helpers import AdminForm
class AdminFormMixin(object): class AdminFormMixin(object):
@ -9,10 +10,35 @@ class AdminFormMixin(object):
fieldsets = [ fieldsets = [
(None, {'fields': self.fields.keys()}) (None, {'fields': self.fields.keys()})
] ]
adminform = AdminForm(self, fieldsets, prepopulated_fields) adminform = helpers.AdminForm(self, fieldsets, prepopulated_fields)
template = Template( template = Template(
'{% for fieldset in adminform %}' '{% for fieldset in adminform %}'
' {% include "admin/includes/fieldset.html" %}' ' {% include "admin/includes/fieldset.html" %}'
'{% endfor %}' '{% endfor %}'
) )
return template.render(Context({'adminform': adminform})) return template.render(Context({'adminform': adminform}))
class AdminFormSet(BaseModelFormSet):
def as_admin(self):
prepopulated = {}
fieldsets = [
(None, {'fields': self.form().fields.keys()})
]
readonly = getattr(self.form.Meta, 'readonly_fields', ())
if not hasattr(self.modeladmin, 'verbose_name_plural'):
opts = self.modeladmin.model._meta
self.modeladmin.verbose_name_plural = opts.verbose_name_plural
inline_admin_formset = helpers.InlineAdminFormSet(self.modeladmin, self,
fieldsets, prepopulated, readonly, model_admin=self.modeladmin)
template = Template(
'{% include "admin/edit_inline/tabular.html" %}'
)
return template.render(Context({'inline_admin_formset': inline_admin_formset}))
def adminmodelformset_factory(modeladmin, form):
formset = modelformset_factory(modeladmin.model, extra=0,
form=form, formset=AdminFormSet)
formset.modeladmin = modeladmin
return formset

View File

@ -2,11 +2,16 @@ import StringIO
import zipfile import zipfile
from django.contrib import messages from django.contrib import messages
from django.contrib.admin import helpers
from django.http import HttpResponse from django.http import HttpResponse
from django.shortcuts import render
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from orchestra.admin.forms import adminmodelformset_factory
from orchestra.utils.html import html_to_pdf from orchestra.utils.html import html_to_pdf
from .forms import SelectSourceForm
def download_bills(modeladmin, request, queryset): def download_bills(modeladmin, request, queryset):
if queryset.count() > 1: if queryset.count() > 1:
@ -35,29 +40,33 @@ view_bill.verbose_name = _("View")
view_bill.url_name = 'view' view_bill.url_name = 'view'
from django import forms
from django.forms.models import BaseModelFormSet
from django.forms.formsets import formset_factory
from django.forms.models import modelformset_factory
from django.shortcuts import render
from .forms import SelectPaymentSourceForm
def close_bills(modeladmin, request, queryset): def close_bills(modeladmin, request, queryset):
queryset = queryset.filter(status=queryset.model.OPEN) queryset = queryset.filter(status=queryset.model.OPEN)
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
SelectPaymentSourceFormSet = modelformset_factory(queryset.model, form=SelectPaymentSourceForm, extra=0) SelectSourceFormSet = adminmodelformset_factory(modeladmin, SelectSourceForm)
if request.POST.get('action') == 'close_selected_bills': formset = SelectSourceFormSet(queryset=queryset)
formset = SelectPaymentSourceFormSet(request.POST, queryset=queryset) if request.POST.get('post') == 'yes':
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:
form.save() source = form.cleaned_data['source']
form.instance.close(payment=source)
messages.success(request, _("Selected bills have been closed")) messages.success(request, _("Selected bills have been closed"))
return return
formset = SelectPaymentSourceFormSet(queryset=queryset) opts = modeladmin.model._meta
return render(request, 'admin/bills/close_confirmation.html', {'formset': formset}) context = {
'title': "Are you sure?",
'action_value': 'close_bills',
'deletable_objects': queryset,
'queryset': queryset,
'opts': opts,
'app_label': opts.app_label,
'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME,
'formset': formset,
}
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

@ -1,15 +1,28 @@
from django import forms from django import forms
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from orchestra.admin.utils import admin_link
from orchestra.forms.widgets import ShowTextWidget
class SelectPaymentSourceForm(forms.ModelForm):
class SelectSourceForm(forms.ModelForm):
bill_link = forms.CharField(label=_("Number"), required=False,
widget=ShowTextWidget())
account_link = forms.CharField(label=_("Account"), required=False)
display_total = forms.CharField(label=_("Total"), required=False)
display_type = forms.CharField(label=_("Type"), required=False,
widget=ShowTextWidget())
source = forms.ChoiceField(label=_("Source"), required=False) source = forms.ChoiceField(label=_("Source"), required=False)
class Meta: class Meta:
fields = ('number', 'source') fields = (
'bill_link', 'display_type', 'account_link', 'display_total',
'source'
)
readonly_fields = ('account_link', 'display_total')
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(SelectPaymentSourceForm, self).__init__(*args, **kwargs) super(SelectSourceForm, self).__init__(*args, **kwargs)
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)
@ -19,6 +32,9 @@ class SelectPaymentSourceForm(forms.ModelForm):
if not recharge or source.method_class().allow_recharge: if not recharge or source.method_class().allow_recharge:
choices.append((source.pk, str(source))) choices.append((source.pk, str(source)))
self.fields['source'].choices = choices self.fields['source'].choices = choices
self.fields['source'].initial = choices[-1][0]
self.fields['bill_link'].initial = admin_link('__unicode__')(bill)
self.fields['display_type'].initial = bill.get_type_display()
def clean_source(self): def clean_source(self):
source_id = self.cleaned_data['source'] source_id = self.cleaned_data['source']
@ -27,8 +43,8 @@ class SelectPaymentSourceForm(forms.ModelForm):
source_model = self.instance.account.paymentsources.model source_model = self.instance.account.paymentsources.model
return source_model.objects.get(id=source_id) return source_model.objects.get(id=source_id)
def has_changed(self):
return False
def save(self, commit=True): def save(self, commit=True):
if commit: pass
source = self.cleaned_data['source']
self.instance.close(payment=source)
return self.instance

View File

@ -180,7 +180,7 @@ class Bill(models.Model):
@cached @cached
def get_subtotals(self): def get_subtotals(self):
subtotals = {} subtotals = {}
for line in self.lines.all().prefetch_related('sublines'): for line in self.lines.all():
subtotal, taxes = subtotals.get(line.tax, (0, 0)) subtotal, taxes = subtotals.get(line.tax, (0, 0))
subtotal += line.total subtotal += line.total
for subline in line.sublines.all(): for subline in line.sublines.all():

View File

@ -4,6 +4,7 @@
{% block extrastyle %} {% block extrastyle %}
{{ block.super }} {{ block.super }}
<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}" /> <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 %} {% endblock %}
@ -18,12 +19,16 @@
<form action="" method="post">{% csrf_token %} <form action="" method="post">{% csrf_token %}
<div> <div>
<div style="margin:20px;"> <div style="margin:20px;">
{{ formset }}
{{ formset.as_admin }}
</div> </div>
{% for obj in queryset %} {% for obj in queryset %}
<input type="hidden" name="{{ action_checkbox_name }}" value="{{ obj.pk|unlocalize }}" /> <input type="hidden" name="{{ action_checkbox_name }}" value="{{ obj.pk|unlocalize }}" />
{% endfor %} {% endfor %}
<input type="hidden" name="action" value="close_selected_bills"/> <input type="hidden" name="action" value="{{ action_value }}"/>
<input type="hidden" name="post" value="yes"/>
<input type="submit" value="{% trans "Yes, close bills" %}" /> <input type="submit" value="{% trans "Yes, close bills" %}" />
</div> </div>
</form> </form>

View File

@ -82,6 +82,7 @@ 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, self.select_method_view,
name='%s_%s_select_method' % info), name='%s_%s_select_method' % info),

View File

@ -54,12 +54,19 @@ class PaymentSource(models.Model):
class TransactionQuerySet(models.QuerySet): class TransactionQuerySet(models.QuerySet):
group_by = group_by group_by = group_by
def create(self, **kwargs):
source = kwargs.get('source')
if source is None or not hasattr(source.method_class, 'process'):
# Manual payments don't need processing
kwargs['state']=self.model.WAITTING_CONFIRMATION
return super(TransactionQuerySet, self).create(**kwargs)
# TODO lock transaction in waiting confirmation # TODO lock transaction in waiting confirmation
class Transaction(models.Model): class Transaction(models.Model):
WAITTING_PROCESSING = 'WAITTING_PROCESSING' WAITTING_PROCESSING = 'WAITTING_PROCESSING' # CREATED
WAITTING_CONFIRMATION = 'WAITTING_CONFIRMATION' WAITTING_CONFIRMATION = 'WAITTING_CONFIRMATION' # PROCESSED
CONFIRMED = 'CONFIRMED' CONFIRMED = 'CONFIRMED'
REJECTED = 'REJECTED' REJECTED = 'REJECTED'
DISCARTED = 'DISCARTED' DISCARTED = 'DISCARTED'