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
with translation.override('en'):
* 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.contrib.admin.helpers import AdminForm
class AdminFormMixin(object):
@ -9,10 +10,35 @@ class AdminFormMixin(object):
fieldsets = [
(None, {'fields': self.fields.keys()})
]
adminform = AdminForm(self, fieldsets, prepopulated_fields)
adminform = helpers.AdminForm(self, fieldsets, prepopulated_fields)
template = Template(
'{% for fieldset in adminform %}'
' {% include "admin/includes/fieldset.html" %}'
'{% endfor %}'
)
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
from django.contrib import messages
from django.contrib.admin import helpers
from django.http import HttpResponse
from django.shortcuts import render
from django.utils.translation import ugettext_lazy as _
from orchestra.admin.forms import adminmodelformset_factory
from orchestra.utils.html import html_to_pdf
from .forms import SelectSourceForm
def download_bills(modeladmin, request, queryset):
if queryset.count() > 1:
@ -35,29 +40,33 @@ view_bill.verbose_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):
queryset = queryset.filter(status=queryset.model.OPEN)
if not queryset:
messages.warning(request, _("Selected bills should be in open state"))
return
SelectPaymentSourceFormSet = modelformset_factory(queryset.model, form=SelectPaymentSourceForm, extra=0)
if request.POST.get('action') == 'close_selected_bills':
formset = SelectPaymentSourceFormSet(request.POST, queryset=queryset)
SelectSourceFormSet = adminmodelformset_factory(modeladmin, SelectSourceForm)
formset = SelectSourceFormSet(queryset=queryset)
if request.POST.get('post') == 'yes':
formset = SelectSourceFormSet(request.POST, request.FILES, queryset=queryset)
if formset.is_valid():
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"))
return
formset = SelectPaymentSourceFormSet(queryset=queryset)
return render(request, 'admin/bills/close_confirmation.html', {'formset': formset})
opts = modeladmin.model._meta
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.url_name = 'close'

View File

@ -1,15 +1,28 @@
from django import forms
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)
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):
super(SelectPaymentSourceForm, self).__init__(*args, **kwargs)
super(SelectSourceForm, self).__init__(*args, **kwargs)
bill = kwargs.get('instance')
if bill:
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:
choices.append((source.pk, str(source)))
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):
source_id = self.cleaned_data['source']
@ -27,8 +43,8 @@ class SelectPaymentSourceForm(forms.ModelForm):
source_model = self.instance.account.paymentsources.model
return source_model.objects.get(id=source_id)
def has_changed(self):
return False
def save(self, commit=True):
if commit:
source = self.cleaned_data['source']
self.instance.close(payment=source)
return self.instance
pass

View File

@ -180,7 +180,7 @@ class Bill(models.Model):
@cached
def get_subtotals(self):
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 += line.total
for subline in line.sublines.all():

View File

@ -4,6 +4,7 @@
{% 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 %}
@ -18,12 +19,16 @@
<form action="" method="post">{% csrf_token %}
<div>
<div style="margin:20px;">
{{ formset }}
{{ 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="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" %}" />
</div>
</form>

View File

@ -82,6 +82,7 @@ class PaymentSourceAdmin(AccountAdminMixin, admin.ModelAdmin):
opts = self.model._meta
info = opts.app_label, opts.model_name
select_urls = patterns("",
# TODO wrap for authentication
url("/select-method/$",
self.select_method_view,
name='%s_%s_select_method' % info),

View File

@ -54,12 +54,19 @@ class PaymentSource(models.Model):
class TransactionQuerySet(models.QuerySet):
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
class Transaction(models.Model):
WAITTING_PROCESSING = 'WAITTING_PROCESSING'
WAITTING_CONFIRMATION = 'WAITTING_CONFIRMATION'
WAITTING_PROCESSING = 'WAITTING_PROCESSING' # CREATED
WAITTING_CONFIRMATION = 'WAITTING_CONFIRMATION' # PROCESSED
CONFIRMED = 'CONFIRMED'
REJECTED = 'REJECTED'
DISCARTED = 'DISCARTED'