Added support for reissue rejected transactions
This commit is contained in:
parent
fdd84b7e74
commit
e804a1d102
|
@ -122,7 +122,7 @@ class AccountAdmin(ChangePasswordAdminMixin, auth.UserAdmin, ExtendedModelAdmin)
|
||||||
return views
|
return views
|
||||||
|
|
||||||
def get_actions(self, request):
|
def get_actions(self, request):
|
||||||
actions = super(AccountAdmin, self).get_actions(request)
|
actions = super().get_actions(request)
|
||||||
if 'delete_selected' in actions:
|
if 'delete_selected' in actions:
|
||||||
del actions['delete_selected']
|
del actions['delete_selected']
|
||||||
return actions
|
return actions
|
||||||
|
|
9
orchestra/contrib/mailer/actions.py
Normal file
9
orchestra/contrib/mailer/actions.py
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
|
from django.shortcuts import redirect
|
||||||
|
|
||||||
|
|
||||||
|
def last(modeladmin, request, queryset):
|
||||||
|
last_id = queryset.order_by('id').values_list('id', flat=True).first()
|
||||||
|
url = reverse('admin:mailer_message_change', args=(last_id,))
|
||||||
|
print(url)
|
||||||
|
return redirect(url)
|
|
@ -8,9 +8,11 @@ from django.db.models import Count
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from orchestra.admin import ExtendedModelAdmin
|
||||||
from orchestra.admin.utils import admin_link, admin_colored, admin_date, wrap_admin_view
|
from orchestra.admin.utils import admin_link, admin_colored, admin_date, wrap_admin_view
|
||||||
from orchestra.contrib.tasks import task
|
from orchestra.contrib.tasks import task
|
||||||
|
|
||||||
|
from .actions import last
|
||||||
from .engine import send_pending
|
from .engine import send_pending
|
||||||
from .models import Message, SMTPLog
|
from .models import Message, SMTPLog
|
||||||
|
|
||||||
|
@ -25,13 +27,13 @@ COLORS = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class MessageAdmin(admin.ModelAdmin):
|
class MessageAdmin(ExtendedModelAdmin):
|
||||||
list_display = (
|
list_display = (
|
||||||
'display_subject', 'colored_state', 'priority', 'to_address', 'from_address',
|
'display_subject', 'colored_state', 'priority', 'to_address', 'from_address',
|
||||||
'created_at_delta', 'display_retries', 'last_try_delta',
|
'created_at_delta', 'display_retries', 'last_try_delta',
|
||||||
)
|
)
|
||||||
list_filter = ('state', 'priority', 'retries')
|
list_filter = ('state', 'priority', 'retries')
|
||||||
list_prefetch_related = ('logs__id')
|
list_prefetch_related = ('logs',)
|
||||||
search_fields = ('to_address', 'from_address', 'subject',)
|
search_fields = ('to_address', 'from_address', 'subject',)
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
(None, {
|
(None, {
|
||||||
|
@ -49,6 +51,7 @@ class MessageAdmin(admin.ModelAdmin):
|
||||||
'display_to', 'display_from', 'display_content',
|
'display_to', 'display_from', 'display_content',
|
||||||
)
|
)
|
||||||
date_hierarchy = 'created_at'
|
date_hierarchy = 'created_at'
|
||||||
|
change_view_actions = (last,)
|
||||||
|
|
||||||
colored_state = admin_colored('state', colors=COLORS)
|
colored_state = admin_colored('state', colors=COLORS)
|
||||||
created_at_delta = admin_date('created_at')
|
created_at_delta = admin_date('created_at')
|
||||||
|
@ -114,7 +117,7 @@ class MessageAdmin(admin.ModelAdmin):
|
||||||
|
|
||||||
def get_urls(self):
|
def get_urls(self):
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
urls = super(MessageAdmin, self).get_urls()
|
urls = super().get_urls()
|
||||||
info = self.model._meta.app_label, self.model._meta.model_name
|
info = self.model._meta.app_label, self.model._meta.model_name
|
||||||
urls.insert(0,
|
urls.insert(0,
|
||||||
url(r'^send-pending/$',
|
url(r'^send-pending/$',
|
||||||
|
@ -124,8 +127,8 @@ class MessageAdmin(admin.ModelAdmin):
|
||||||
return urls
|
return urls
|
||||||
|
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
qs = super(MessageAdmin, self).get_queryset(request)
|
qs = super().get_queryset(request)
|
||||||
return qs.annotate(Count('logs')).prefetch_related('logs').defer('content')
|
return qs.annotate(Count('logs')).defer('content')
|
||||||
|
|
||||||
def send_pending_view(self, request):
|
def send_pending_view(self, request):
|
||||||
task(send_pending).apply_async()
|
task(send_pending).apply_async()
|
||||||
|
@ -135,7 +138,7 @@ class MessageAdmin(admin.ModelAdmin):
|
||||||
def formfield_for_dbfield(self, db_field, **kwargs):
|
def formfield_for_dbfield(self, db_field, **kwargs):
|
||||||
if db_field.name == 'subject':
|
if db_field.name == 'subject':
|
||||||
kwargs['widget'] = forms.TextInput(attrs={'size':'100'})
|
kwargs['widget'] = forms.TextInput(attrs={'size':'100'})
|
||||||
return super(MessageAdmin, self).formfield_for_dbfield(db_field, **kwargs)
|
return super().formfield_for_dbfield(db_field, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class SMTPLogAdmin(admin.ModelAdmin):
|
class SMTPLogAdmin(admin.ModelAdmin):
|
||||||
|
|
|
@ -2,8 +2,9 @@ from functools import partial
|
||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.admin import actions
|
from django.contrib.admin import actions
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render, redirect
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.text import capfirst
|
from django.utils.text import capfirst
|
||||||
from django.utils.translation import ungettext, ugettext_lazy as _
|
from django.utils.translation import ungettext, ugettext_lazy as _
|
||||||
|
@ -205,3 +206,19 @@ def report(modeladmin, request, queryset):
|
||||||
'transactions': transactions,
|
'transactions': transactions,
|
||||||
}
|
}
|
||||||
return render(request, 'admin/payments/transaction/report.html', context)
|
return render(request, 'admin/payments/transaction/report.html', context)
|
||||||
|
|
||||||
|
|
||||||
|
def reissue(modeladmin, request, queryset):
|
||||||
|
if len(queryset) != 1:
|
||||||
|
messages.error(request, _("One transaction should be selected."))
|
||||||
|
return
|
||||||
|
trans = queryset[0]
|
||||||
|
url = reverse('admin:payments_transaction_add')
|
||||||
|
url += '?account=%i&bill=%i&source=%s&amount=%s¤cy=%s' % (
|
||||||
|
trans.bill.account_id,
|
||||||
|
trans.bill_id,
|
||||||
|
trans.source_id or '',
|
||||||
|
trans.amount,
|
||||||
|
trans.currency,
|
||||||
|
)
|
||||||
|
return redirect(url)
|
||||||
|
|
|
@ -105,9 +105,10 @@ class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
)
|
)
|
||||||
change_view_actions = (
|
change_view_actions = (
|
||||||
actions.process_transactions, actions.mark_as_executed, actions.mark_as_secured,
|
actions.process_transactions, actions.mark_as_executed, actions.mark_as_secured,
|
||||||
actions.mark_as_rejected,
|
actions.mark_as_rejected, actions.reissue
|
||||||
)
|
)
|
||||||
actions = change_view_actions + (actions.report, list_accounts)
|
search_fields = ('bill__number', 'bill__account__username', 'id')
|
||||||
|
actions = change_view_actions + (actions.report, list_accounts,)
|
||||||
filter_by_account_fields = ('bill', 'source')
|
filter_by_account_fields = ('bill', 'source')
|
||||||
change_readonly_fields = ('amount', 'currency')
|
change_readonly_fields = ('amount', 'currency')
|
||||||
readonly_fields = (
|
readonly_fields = (
|
||||||
|
@ -124,17 +125,28 @@ class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
display_created_at = admin_date('created_at', short_description=_("Created"))
|
display_created_at = admin_date('created_at', short_description=_("Created"))
|
||||||
display_modified_at = admin_date('modified_at', short_description=_("Modified"))
|
display_modified_at = admin_date('modified_at', short_description=_("Modified"))
|
||||||
|
|
||||||
|
def has_delete_permission(self, *args, **kwargs):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_actions(self, request):
|
||||||
|
actions = super().get_actions(request)
|
||||||
|
if 'delete_selected' in actions:
|
||||||
|
del actions['delete_selected']
|
||||||
|
return actions
|
||||||
|
|
||||||
def get_change_view_actions(self, obj=None):
|
def get_change_view_actions(self, obj=None):
|
||||||
actions = super(TransactionAdmin, self).get_change_view_actions()
|
actions = super(TransactionAdmin, self).get_change_view_actions()
|
||||||
exclude = []
|
exclude = []
|
||||||
if obj:
|
if obj:
|
||||||
if obj.state == Transaction.WAITTING_PROCESSING:
|
if obj.state == Transaction.WAITTING_PROCESSING:
|
||||||
exclude = ['mark_as_executed', 'mark_as_secured']
|
exclude = ['mark_as_executed', 'mark_as_secured', 'reissue']
|
||||||
elif obj.state == Transaction.WAITTING_EXECUTION:
|
elif obj.state == Transaction.WAITTING_EXECUTION:
|
||||||
exclude = ['process_transactions', 'mark_as_secured']
|
exclude = ['process_transactions', 'mark_as_secured', 'reissue']
|
||||||
if obj.state == Transaction.EXECUTED:
|
if obj.state == Transaction.EXECUTED:
|
||||||
exclude = ['process_transactions', 'mark_as_executed']
|
exclude = ['process_transactions', 'mark_as_executed', 'reissue']
|
||||||
elif obj.state in [Transaction.REJECTED, Transaction.SECURED]:
|
elif obj.state == Transaction.REJECTED:
|
||||||
|
exclude = ['process_transactions', 'mark_as_executed', 'mark_as_secured', 'mark_as_rejected']
|
||||||
|
elif obj.state == Transaction.SECURED:
|
||||||
return []
|
return []
|
||||||
return [action for action in actions if action.__name__ not in exclude]
|
return [action for action in actions if action.__name__ not in exclude]
|
||||||
|
|
||||||
|
@ -154,6 +166,7 @@ class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
|
||||||
)
|
)
|
||||||
list_filter = ('state',)
|
list_filter = ('state',)
|
||||||
fields = ('data', 'file_url', 'created_at')
|
fields = ('data', 'file_url', 'created_at')
|
||||||
|
search_fields = ('transactions__bill__number', 'transactions__bill__account__username', 'id')
|
||||||
readonly_fields = ('data', 'file_url', 'display_transactions', 'created_at')
|
readonly_fields = ('data', 'file_url', 'display_transactions', 'created_at')
|
||||||
list_prefetch_related = ('transactions',)
|
list_prefetch_related = ('transactions',)
|
||||||
inlines = [TransactionInline]
|
inlines = [TransactionInline]
|
||||||
|
|
|
@ -135,7 +135,12 @@ class Transaction(models.Model):
|
||||||
if not self.pk:
|
if not self.pk:
|
||||||
amount = self.bill.transactions.exclude(state=self.REJECTED).amount()
|
amount = self.bill.transactions.exclude(state=self.REJECTED).amount()
|
||||||
if amount >= self.bill.total:
|
if amount >= self.bill.total:
|
||||||
raise ValidationError(_("New transactions can not be allocated for this bill."))
|
raise ValidationError(
|
||||||
|
_("Bill %(number)s already has valid transactions that cover bill total amount (%(amount)s).") % {
|
||||||
|
'number': self.bill.number,
|
||||||
|
'amount': amount,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
def get_state_help(self):
|
def get_state_help(self):
|
||||||
if self.source:
|
if self.source:
|
||||||
|
|
Loading…
Reference in a new issue