Improvements on transactions
This commit is contained in:
parent
2b91495657
commit
821463eb33
|
@ -24,16 +24,16 @@ def admin_field(method):
|
||||||
return admin_field_wrapper
|
return admin_field_wrapper
|
||||||
|
|
||||||
|
|
||||||
def action_with_confirmation(action_name, extra_context={},
|
def action_with_confirmation(action_name=None, extra_context={},
|
||||||
template='admin/orchestra/generic_confirmation.html'):
|
template='admin/orchestra/generic_confirmation.html'):
|
||||||
"""
|
"""
|
||||||
Generic pattern for actions that needs confirmation step
|
Generic pattern for actions that needs confirmation step
|
||||||
If custom template is provided the form must contain:
|
If custom template is provided the form must contain:
|
||||||
<input type="hidden" name="post" value="generic_confirmation" />
|
<input type="hidden" name="post" value="generic_confirmation" />
|
||||||
"""
|
"""
|
||||||
def decorator(func, extra_context=extra_context, template=template):
|
def decorator(func, extra_context=extra_context, template=template, action_name=action_name):
|
||||||
@wraps(func, assigned=available_attrs(func))
|
@wraps(func, assigned=available_attrs(func))
|
||||||
def inner(modeladmin, request, queryset):
|
def inner(modeladmin, request, queryset, action_name=action_name):
|
||||||
# The user has already confirmed the action.
|
# The user has already confirmed the action.
|
||||||
if request.POST.get('post') == "generic_confirmation":
|
if request.POST.get('post') == "generic_confirmation":
|
||||||
stay = func(modeladmin, request, queryset)
|
stay = func(modeladmin, request, queryset)
|
||||||
|
@ -48,7 +48,8 @@ def action_with_confirmation(action_name, extra_context={},
|
||||||
objects_name = force_text(opts.verbose_name)
|
objects_name = force_text(opts.verbose_name)
|
||||||
else:
|
else:
|
||||||
objects_name = force_text(opts.verbose_name_plural)
|
objects_name = force_text(opts.verbose_name_plural)
|
||||||
|
if not action_name:
|
||||||
|
action_name = func.__name__
|
||||||
context = {
|
context = {
|
||||||
"title": "Are you sure?",
|
"title": "Are you sure?",
|
||||||
"content_message": "Are you sure you want to %s the selected %s?" %
|
"content_message": "Are you sure you want to %s the selected %s?" %
|
||||||
|
|
|
@ -62,7 +62,8 @@ class ChangeViewActionsMixin(object):
|
||||||
action.url_name)))
|
action.url_name)))
|
||||||
return new_urls + urls
|
return new_urls + urls
|
||||||
|
|
||||||
def get_change_view_actions(self):
|
def get_change_view_actions(self, obj=None):
|
||||||
|
""" allow customization on modelamdin """
|
||||||
views = []
|
views = []
|
||||||
for action in self.change_view_actions:
|
for action in self.change_view_actions:
|
||||||
if isinstance(action, basestring):
|
if isinstance(action, basestring):
|
||||||
|
@ -79,8 +80,9 @@ class ChangeViewActionsMixin(object):
|
||||||
def change_view(self, request, object_id, **kwargs):
|
def change_view(self, request, object_id, **kwargs):
|
||||||
if not 'extra_context' in kwargs:
|
if not 'extra_context' in kwargs:
|
||||||
kwargs['extra_context'] = {}
|
kwargs['extra_context'] = {}
|
||||||
|
obj = self.get_object(request, unquote(object_id))
|
||||||
kwargs['extra_context']['object_tools_items'] = [
|
kwargs['extra_context']['object_tools_items'] = [
|
||||||
action.__dict__ for action in self.get_change_view_actions()
|
action.__dict__ for action in self.get_change_view_actions(obj=obj)
|
||||||
]
|
]
|
||||||
return super(ChangeViewActionsMixin, self).change_view(request, object_id, **kwargs)
|
return super(ChangeViewActionsMixin, self).change_view(request, object_id, **kwargs)
|
||||||
|
|
||||||
|
|
|
@ -46,8 +46,7 @@ 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)
|
||||||
extra=0)
|
|
||||||
formset = SelectSourceFormSet(queryset=queryset)
|
formset = SelectSourceFormSet(queryset=queryset)
|
||||||
if request.POST.get('post') == 'generic_confirmation':
|
if request.POST.get('post') == 'generic_confirmation':
|
||||||
formset = SelectSourceFormSet(request.POST, request.FILES, queryset=queryset)
|
formset = SelectSourceFormSet(request.POST, request.FILES, queryset=queryset)
|
||||||
|
@ -55,6 +54,8 @@ def close_bills(modeladmin, request, queryset):
|
||||||
for form in formset.forms:
|
for form in formset.forms:
|
||||||
source = form.cleaned_data['source']
|
source = form.cleaned_data['source']
|
||||||
form.instance.close(payment=source)
|
form.instance.close(payment=source)
|
||||||
|
for bill in queryset:
|
||||||
|
modeladmin.log_change(request, bill, 'Closed')
|
||||||
messages.success(request, _("Selected bills have been closed"))
|
messages.success(request, _("Selected bills have been closed"))
|
||||||
return
|
return
|
||||||
opts = modeladmin.model._meta
|
opts = modeladmin.model._meta
|
||||||
|
@ -80,5 +81,6 @@ close_bills.url_name = 'close'
|
||||||
def send_bills(modeladmin, request, queryset):
|
def send_bills(modeladmin, request, queryset):
|
||||||
for bill in queryset:
|
for bill in queryset:
|
||||||
bill.send()
|
bill.send()
|
||||||
|
modeladmin.log_change(request, bill, 'Sent')
|
||||||
send_bills.verbose_name = _("Send")
|
send_bills.verbose_name = _("Send")
|
||||||
send_bills.url_name = 'send'
|
send_bills.url_name = 'send'
|
||||||
|
|
|
@ -17,7 +17,7 @@ def change_ticket_state_factory(action, final_state):
|
||||||
'form': ChangeReasonForm()
|
'form': ChangeReasonForm()
|
||||||
}
|
}
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
@action_with_confirmation(action, extra_context=context)
|
@action_with_confirmation(action_name=action, extra_context=context)
|
||||||
def change_ticket_state(modeladmin, request, queryset, action=action, final_state=final_state):
|
def change_ticket_state(modeladmin, request, queryset, action=action, final_state=final_state):
|
||||||
form = ChangeReasonForm(request.POST)
|
form = ChangeReasonForm(request.POST)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
|
@ -81,6 +81,7 @@ def take_tickets(modeladmin, request, queryset):
|
||||||
ticket.messages.create(content=content, author=request.user)
|
ticket.messages.create(content=content, author=request.user)
|
||||||
if is_read and not ticket.is_read_by(request.user):
|
if is_read and not ticket.is_read_by(request.user):
|
||||||
ticket.mark_as_read_by(request.user)
|
ticket.mark_as_read_by(request.user)
|
||||||
|
modeladmin.log_change(request, ticket, 'Taken')
|
||||||
context = {
|
context = {
|
||||||
'count': queryset.count(),
|
'count': queryset.count(),
|
||||||
'user': request.user
|
'user': request.user
|
||||||
|
@ -97,6 +98,7 @@ def mark_as_unread(modeladmin, request, queryset):
|
||||||
""" Mark a tickets as unread """
|
""" Mark a tickets as unread """
|
||||||
for ticket in queryset:
|
for ticket in queryset:
|
||||||
ticket.mark_as_unread_by(request.user)
|
ticket.mark_as_unread_by(request.user)
|
||||||
|
modeladmin.log_change(request, ticket, 'Marked as unread')
|
||||||
msg = _("%s selected tickets have been marked as unread.") % queryset.count()
|
msg = _("%s selected tickets have been marked as unread.") % queryset.count()
|
||||||
modeladmin.message_user(request, msg)
|
modeladmin.message_user(request, msg)
|
||||||
|
|
||||||
|
@ -106,6 +108,7 @@ def mark_as_read(modeladmin, request, queryset):
|
||||||
""" Mark a tickets as unread """
|
""" Mark a tickets as unread """
|
||||||
for ticket in queryset:
|
for ticket in queryset:
|
||||||
ticket.mark_as_read_by(request.user)
|
ticket.mark_as_read_by(request.user)
|
||||||
|
modeladmin.log_change(request, ticket, 'Marked as read')
|
||||||
msg = _("%s selected tickets have been marked as read.") % queryset.count()
|
msg = _("%s selected tickets have been marked as read.") % queryset.count()
|
||||||
modeladmin.message_user(request, msg)
|
modeladmin.message_user(request, msg)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from django.contrib import admin, messages
|
from django.contrib import admin, messages
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
|
from django.db import transaction
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.utils.translation import ungettext
|
from django.utils.translation import ungettext
|
||||||
|
@ -71,10 +72,13 @@ class BillSelectedOrders(object):
|
||||||
})
|
})
|
||||||
return render(request, self.template, self.context)
|
return render(request, self.template, self.context)
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
def confirmation(self, request):
|
def confirmation(self, request):
|
||||||
form = BillSelectConfirmationForm(initial=self.options)
|
form = BillSelectConfirmationForm(initial=self.options)
|
||||||
if int(request.POST.get('step')) >= 3:
|
if int(request.POST.get('step')) >= 3:
|
||||||
bills = self.queryset.bill(commit=True, **self.options)
|
bills = self.queryset.bill(commit=True, **self.options)
|
||||||
|
for order in self.queryset:
|
||||||
|
modeladmin.log_change(request, order, 'Billed')
|
||||||
if not bills:
|
if not bills:
|
||||||
msg = _("Selected orders do not have pending billing")
|
msg = _("Selected orders do not have pending billing")
|
||||||
self.modeladmin.message_user(request, msg, messages.WARNING)
|
self.modeladmin.message_user(request, msg, messages.WARNING)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.migrations.recorder import MigrationRecorder
|
from django.db.migrations.recorder import MigrationRecorder
|
||||||
from django.db.models import F, Q
|
from django.db.models import F, Q
|
||||||
|
@ -39,6 +40,11 @@ class ContractedPlan(models.Model):
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return str(self.plan)
|
return str(self.plan)
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
if not self.pk and not self.plan.allow_multipls:
|
||||||
|
if ContractedPlan.objects.filter(plan=self.plan, account=self.account).exists():
|
||||||
|
raise ValidationError("A contracted plan for this account already exists")
|
||||||
|
|
||||||
|
|
||||||
class RateQuerySet(models.QuerySet):
|
class RateQuerySet(models.QuerySet):
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
|
from django.db import transaction
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from orchestra.admin.decorators import action_with_confirmation
|
||||||
|
|
||||||
from .methods import PaymentMethod
|
from .methods import PaymentMethod
|
||||||
from .models import Transaction
|
from .models import Transaction
|
||||||
|
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
def process_transactions(modeladmin, request, queryset):
|
def process_transactions(modeladmin, request, queryset):
|
||||||
processes = []
|
processes = []
|
||||||
if queryset.exclude(state=Transaction.WAITTING_PROCESSING).exists():
|
if queryset.exclude(state=Transaction.WAITTING_PROCESSING).exists():
|
||||||
|
@ -16,6 +21,8 @@ def process_transactions(modeladmin, request, queryset):
|
||||||
method = PaymentMethod.get_plugin(method)
|
method = PaymentMethod.get_plugin(method)
|
||||||
procs = method.process(transactions)
|
procs = method.process(transactions)
|
||||||
processes += procs
|
processes += procs
|
||||||
|
for transaction in transactions:
|
||||||
|
modeladmin.log_change(request, transaction, 'Processed')
|
||||||
if not processes:
|
if not processes:
|
||||||
return
|
return
|
||||||
opts = modeladmin.model._meta
|
opts = modeladmin.model._meta
|
||||||
|
@ -27,3 +34,42 @@ def process_transactions(modeladmin, request, queryset):
|
||||||
'app_label': opts.app_label,
|
'app_label': opts.app_label,
|
||||||
}
|
}
|
||||||
return render(request, 'admin/payments/transaction/get_processes.html', context)
|
return render(request, 'admin/payments/transaction/get_processes.html', context)
|
||||||
|
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
|
@action_with_confirmation()
|
||||||
|
def mark_as_executed(modeladmin, request, queryset):
|
||||||
|
""" Mark a tickets as unread """
|
||||||
|
for transaction in queryset:
|
||||||
|
transaction.mark_as_executed()
|
||||||
|
modeladmin.log_change(request, transaction, 'Executed')
|
||||||
|
msg = _("%s selected transactions have been marked as executed.") % queryset.count()
|
||||||
|
modeladmin.message_user(request, msg)
|
||||||
|
mark_as_executed.url_name = 'execute'
|
||||||
|
mark_as_executed.verbose_name = _("Mark as executed")
|
||||||
|
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
|
@action_with_confirmation()
|
||||||
|
def mark_as_secured(modeladmin, request, queryset):
|
||||||
|
""" Mark a tickets as unread """
|
||||||
|
for transaction in queryset:
|
||||||
|
transaction.mark_as_secured()
|
||||||
|
modeladmin.log_change(request, transaction, 'Secured')
|
||||||
|
msg = _("%s selected transactions have been marked as secured.") % queryset.count()
|
||||||
|
modeladmin.message_user(request, msg)
|
||||||
|
mark_as_secured.url_name = 'secure'
|
||||||
|
mark_as_secured.verbose_name = _("Mark as secured")
|
||||||
|
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
|
@action_with_confirmation()
|
||||||
|
def mark_as_rejected(modeladmin, request, queryset):
|
||||||
|
""" Mark a tickets as unread """
|
||||||
|
for transaction in queryset:
|
||||||
|
transaction.mark_as_rejected()
|
||||||
|
modeladmin.log_change(request, transaction, 'Rejected')
|
||||||
|
msg = _("%s selected transactions have been marked as rejected.") % queryset.count()
|
||||||
|
modeladmin.message_user(request, msg)
|
||||||
|
mark_as_rejected.url_name = 'reject'
|
||||||
|
mark_as_rejected.verbose_name = _("Mark as rejected")
|
||||||
|
|
|
@ -5,10 +5,11 @@ 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 import ChangeViewActionsMixin
|
||||||
from orchestra.admin.utils import admin_colored, admin_link, wrap_admin_view
|
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 . import actions
|
||||||
from .methods import PaymentMethod
|
from .methods import PaymentMethod
|
||||||
from .models import PaymentSource, Transaction, TransactionProcess
|
from .models import PaymentSource, Transaction, TransactionProcess
|
||||||
|
|
||||||
|
@ -16,10 +17,9 @@ from .models import PaymentSource, Transaction, TransactionProcess
|
||||||
STATE_COLORS = {
|
STATE_COLORS = {
|
||||||
Transaction.WAITTING_PROCESSING: 'darkorange',
|
Transaction.WAITTING_PROCESSING: 'darkorange',
|
||||||
Transaction.WAITTING_CONFIRMATION: 'magenta',
|
Transaction.WAITTING_CONFIRMATION: 'magenta',
|
||||||
Transaction.CONFIRMED: 'olive',
|
Transaction.EXECUTED: 'olive',
|
||||||
Transaction.SECURED: 'green',
|
Transaction.SECURED: 'green',
|
||||||
Transaction.REJECTED: 'red',
|
Transaction.REJECTED: 'red',
|
||||||
Transaction.DISCARTED: 'blue',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,7 +27,10 @@ class TransactionInline(admin.TabularInline):
|
||||||
model = Transaction
|
model = Transaction
|
||||||
can_delete = False
|
can_delete = False
|
||||||
extra = 0
|
extra = 0
|
||||||
fields = ('transaction_link', 'bill_link', 'source_link', 'display_state', 'amount', 'currency')
|
fields = (
|
||||||
|
'transaction_link', 'bill_link', 'source_link', 'display_state',
|
||||||
|
'amount', 'currency'
|
||||||
|
)
|
||||||
readonly_fields = fields
|
readonly_fields = fields
|
||||||
|
|
||||||
transaction_link = admin_link('__unicode__', short_description=_("ID"))
|
transaction_link = admin_link('__unicode__', short_description=_("ID"))
|
||||||
|
@ -44,14 +47,19 @@ class TransactionInline(admin.TabularInline):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class TransactionAdmin(AccountAdminMixin, admin.ModelAdmin):
|
class TransactionAdmin(ChangeViewActionsMixin, AccountAdminMixin, admin.ModelAdmin):
|
||||||
list_display = (
|
list_display = (
|
||||||
'id', 'bill_link', 'account_link', 'source_link', 'display_state', 'amount', 'process_link'
|
'id', 'bill_link', 'account_link', 'source_link', 'display_state',
|
||||||
|
'amount', 'process_link'
|
||||||
)
|
)
|
||||||
list_filter = ('source__method', 'state')
|
list_filter = ('source__method', 'state')
|
||||||
actions = (process_transactions,)
|
actions = (
|
||||||
|
actions.process_transactions, actions.mark_as_executed,
|
||||||
|
actions.mark_as_secured, actions.mark_as_rejected
|
||||||
|
)
|
||||||
|
change_view_actions = actions
|
||||||
filter_by_account_fields = ['source']
|
filter_by_account_fields = ['source']
|
||||||
readonly_fields = ('process_link', 'account_link')
|
readonly_fields = ('bill_link', 'display_state', 'process_link', 'account_link')
|
||||||
|
|
||||||
bill_link = admin_link('bill')
|
bill_link = admin_link('bill')
|
||||||
source_link = admin_link('source')
|
source_link = admin_link('source')
|
||||||
|
@ -62,6 +70,20 @@ class TransactionAdmin(AccountAdminMixin, admin.ModelAdmin):
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
qs = super(TransactionAdmin, self).get_queryset(request)
|
qs = super(TransactionAdmin, self).get_queryset(request)
|
||||||
return qs.select_related('source', 'bill__account__user')
|
return qs.select_related('source', 'bill__account__user')
|
||||||
|
|
||||||
|
def get_change_view_actions(self, obj=None):
|
||||||
|
actions = super(TransactionAdmin, self).get_change_view_actions()
|
||||||
|
discard = []
|
||||||
|
if obj:
|
||||||
|
if obj.state == Transaction.EXECUTED:
|
||||||
|
discard = ['mark_as_executed']
|
||||||
|
elif obj.state == Transaction.REJECTED:
|
||||||
|
discard = ['mark_as_rejected']
|
||||||
|
elif obj.state == Transaction.SECURED:
|
||||||
|
discard = ['mark_as_secured']
|
||||||
|
if not discard:
|
||||||
|
return actions
|
||||||
|
return [action for action in actions if action.__name__ not in discard]
|
||||||
|
|
||||||
|
|
||||||
class PaymentSourceAdmin(AccountAdminMixin, admin.ModelAdmin):
|
class PaymentSourceAdmin(AccountAdminMixin, admin.ModelAdmin):
|
||||||
|
@ -89,10 +111,14 @@ class PaymentSourceAdmin(AccountAdminMixin, admin.ModelAdmin):
|
||||||
return select_urls + urls
|
return select_urls + urls
|
||||||
|
|
||||||
def select_method_view(self, request):
|
def select_method_view(self, request):
|
||||||
|
opts = self.model._meta
|
||||||
context = {
|
context = {
|
||||||
|
'opts': opts,
|
||||||
|
'app_label': opts.app_label,
|
||||||
'methods': PaymentMethod.get_plugin_choices(),
|
'methods': PaymentMethod.get_plugin_choices(),
|
||||||
}
|
}
|
||||||
return render(request, 'admin/payments/payment_source/select_method.html', context)
|
template = 'admin/payments/payment_source/select_method.html'
|
||||||
|
return render(request, template, context)
|
||||||
|
|
||||||
def add_view(self, request, form_url='', extra_context=None):
|
def add_view(self, request, form_url='', extra_context=None):
|
||||||
""" Redirects to select account view if required """
|
""" Redirects to select account view if required """
|
||||||
|
|
|
@ -67,17 +67,15 @@ class TransactionQuerySet(models.QuerySet):
|
||||||
class Transaction(models.Model):
|
class Transaction(models.Model):
|
||||||
WAITTING_PROCESSING = 'WAITTING_PROCESSING' # CREATED
|
WAITTING_PROCESSING = 'WAITTING_PROCESSING' # CREATED
|
||||||
WAITTING_CONFIRMATION = 'WAITTING_CONFIRMATION' # PROCESSED
|
WAITTING_CONFIRMATION = 'WAITTING_CONFIRMATION' # PROCESSED
|
||||||
CONFIRMED = 'CONFIRMED'
|
EXECUTED = 'EXECUTED'
|
||||||
REJECTED = 'REJECTED'
|
|
||||||
DISCARTED = 'DISCARTED'
|
|
||||||
SECURED = 'SECURED'
|
SECURED = 'SECURED'
|
||||||
|
REJECTED = 'REJECTED'
|
||||||
STATES = (
|
STATES = (
|
||||||
(WAITTING_PROCESSING, _("Waitting processing")),
|
(WAITTING_PROCESSING, _("Waitting processing")),
|
||||||
(WAITTING_CONFIRMATION, _("Waitting confirmation")),
|
(WAITTING_CONFIRMATION, _("Waitting confirmation")),
|
||||||
(CONFIRMED, _("Confirmed")),
|
(EXECUTED, _("Executed")),
|
||||||
(REJECTED, _("Rejected")),
|
|
||||||
(SECURED, _("Secured")),
|
(SECURED, _("Secured")),
|
||||||
(DISCARTED, _("Discarted")),
|
(REJECTED, _("Rejected")),
|
||||||
)
|
)
|
||||||
|
|
||||||
objects = TransactionQuerySet.as_manager()
|
objects = TransactionQuerySet.as_manager()
|
||||||
|
@ -101,6 +99,21 @@ class Transaction(models.Model):
|
||||||
@property
|
@property
|
||||||
def account(self):
|
def account(self):
|
||||||
return self.bill.account
|
return self.bill.account
|
||||||
|
|
||||||
|
def mark_as_executed(self):
|
||||||
|
self.state = self.EXECUTED
|
||||||
|
self.save()
|
||||||
|
|
||||||
|
def mark_as_secured(self):
|
||||||
|
self.state = self.SECURED
|
||||||
|
# TODO think carefully about bill feedback
|
||||||
|
self.bill.mark_as_paid()
|
||||||
|
self.save()
|
||||||
|
|
||||||
|
def mark_as_rejected(self):
|
||||||
|
self.state = self.REJECTED
|
||||||
|
# TODO bill feedback
|
||||||
|
self.save()
|
||||||
|
|
||||||
|
|
||||||
class TransactionProcess(models.Model):
|
class TransactionProcess(models.Model):
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
{% extends "admin/orchestra/generic_confirmation.html" %}
|
||||||
|
{% load i18n l10n staticfiles admin_urls %}
|
||||||
|
|
||||||
|
|
||||||
|
{% 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 %}
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
<p>{{ content_message | safe }}</p>
|
<p>{{ content_message | safe }}</p>
|
||||||
<ul>
|
<ul>
|
||||||
{% for display_object in display_objects %}
|
{% for display_object in display_objects %}
|
||||||
<li> <a href="{% url 'admin:nodes_node_change' deletable_object.id %}">{{ deletable_object }} </a></li>
|
<li> <a href="{% url opts|admin_urlname:'change' display_object.pk %}">{{ display_object }} </a></li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
<form action="" method="post">{% csrf_token %}
|
<form action="" method="post">{% csrf_token %}
|
||||||
|
|
Loading…
Reference in New Issue