Fixes on payments
This commit is contained in:
parent
d849ec8867
commit
27aec2e5f0
|
@ -370,6 +370,6 @@ def service_report(modeladmin, request, queryset):
|
||||||
return render(request, 'admin/bills/billline/report.html', context)
|
return render(request, 'admin/bills/billline/report.html', context)
|
||||||
|
|
||||||
|
|
||||||
def get_ids(modeladmin, request, queryset):
|
def list_bills(modeladmin, request, queryset):
|
||||||
ids = ','.join(map(str, queryset.values_list('id', flat=True)))
|
ids = ','.join(map(str, queryset.values_list('bill_id', flat=True).distinct()))
|
||||||
return HttpResponseRedirect('?id__in=%s' % ids)
|
return HttpResponseRedirect('../bill/?id__in=%s' % ids)
|
||||||
|
|
|
@ -138,7 +138,8 @@ class BillLineAdmin(admin.ModelAdmin):
|
||||||
'tax', 'subtotal', 'display_sublinetotal', 'display_total'
|
'tax', 'subtotal', 'display_sublinetotal', 'display_total'
|
||||||
)
|
)
|
||||||
actions = (
|
actions = (
|
||||||
actions.undo_billing, actions.move_lines, actions.copy_lines, actions.service_report
|
actions.undo_billing, actions.move_lines, actions.copy_lines, actions.service_report,
|
||||||
|
actions.list_bills,
|
||||||
)
|
)
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
(None, {
|
(None, {
|
||||||
|
@ -171,8 +172,9 @@ class BillLineAdmin(admin.ModelAdmin):
|
||||||
display_is_open.boolean = True
|
display_is_open.boolean = True
|
||||||
|
|
||||||
def display_sublinetotal(self, instance):
|
def display_sublinetotal(self, instance):
|
||||||
return instance.subline_total or ''
|
total = instance.subline_total
|
||||||
display_sublinetotal.short_description = _("Subline")
|
return total if total is not None else '---'
|
||||||
|
display_sublinetotal.short_description = _("Sublines")
|
||||||
display_sublinetotal.admin_order_field = 'subline_total'
|
display_sublinetotal.admin_order_field = 'subline_total'
|
||||||
|
|
||||||
def display_total(self, instance):
|
def display_total(self, instance):
|
||||||
|
@ -197,6 +199,11 @@ class BillLineAdmin(admin.ModelAdmin):
|
||||||
)
|
)
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
|
def has_delete_permission(self, request, obj=None):
|
||||||
|
if obj and not obj.bill.is_open:
|
||||||
|
return False
|
||||||
|
return super().has_delete_permission(request, obj)
|
||||||
|
|
||||||
|
|
||||||
class BillLineManagerAdmin(BillLineAdmin):
|
class BillLineManagerAdmin(BillLineAdmin):
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
|
@ -216,19 +223,21 @@ class BillLineManagerAdmin(BillLineAdmin):
|
||||||
messages.error(request, _("No bills selected."))
|
messages.error(request, _("No bills selected."))
|
||||||
return redirect('..')
|
return redirect('..')
|
||||||
self.bill_ids = bill_ids
|
self.bill_ids = bill_ids
|
||||||
|
bill = None
|
||||||
if len(bill_ids) == 1:
|
if len(bill_ids) == 1:
|
||||||
bill_url = reverse('admin:bills_bill_change', args=(bill_ids[0],))
|
bill_url = reverse('admin:bills_bill_change', args=(bill_ids[0],))
|
||||||
bill = Bill.objects.get(pk=bill_ids[0])
|
bill = Bill.objects.get(pk=bill_ids[0])
|
||||||
bill_link = '<a href="%s">%s</a>' % (bill_url, bill.number)
|
bill_link = '<a href="%s">%s</a>' % (bill_url, bill.number)
|
||||||
title = mark_safe(_("Manage %s bill lines.") % bill_link)
|
title = mark_safe(_("Manage %s bill lines") % bill_link)
|
||||||
if not bill.is_open:
|
if not bill.is_open:
|
||||||
messages.warning(request, _("Bill not in open state."))
|
messages.warning(request, _("Bill not in open state."))
|
||||||
else:
|
else:
|
||||||
if Bill.objects.filter(id__in=bill_ids, is_open=False).exists():
|
if Bill.objects.filter(id__in=bill_ids, is_open=False).exists():
|
||||||
messages.warning(request, _("Not all bills are in open state."))
|
messages.warning(request, _("Not all bills are in open state."))
|
||||||
title = _("Manage bill lines of multiple bills.")
|
title = _("Manage bill lines of multiple bills")
|
||||||
context = {
|
context = {
|
||||||
'title': title,
|
'title': title,
|
||||||
|
'bill': bill,
|
||||||
}
|
}
|
||||||
context.update(extra_context or {})
|
context.update(extra_context or {})
|
||||||
return super().changelist_view(request, context)
|
return super().changelist_view(request, context)
|
||||||
|
@ -244,7 +253,7 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
AmendedListFilter
|
AmendedListFilter
|
||||||
)
|
)
|
||||||
add_fields = ('account', 'type', 'amend_of', 'is_open', 'due_on', 'comments')
|
add_fields = ('account', 'type', 'amend_of', 'is_open', 'due_on', 'comments')
|
||||||
change_list_template = 'admin/bills/change_list.html'
|
change_list_template = 'admin/bills/bill/change_list.html'
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
(None, {
|
(None, {
|
||||||
'fields': ['number', 'type', 'amend_of_link', 'account_link',
|
'fields': ['number', 'type', 'amend_of_link', 'account_link',
|
||||||
|
@ -270,7 +279,7 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
actions = [
|
actions = [
|
||||||
actions.manage_lines, actions.download_bills, actions.close_bills, actions.send_bills,
|
actions.manage_lines, actions.download_bills, actions.close_bills, actions.send_bills,
|
||||||
actions.amend_bills, actions.bill_report, actions.service_report,
|
actions.amend_bills, actions.bill_report, actions.service_report,
|
||||||
actions.close_send_download_bills, list_accounts, actions.get_ids,
|
actions.close_send_download_bills, list_accounts,
|
||||||
]
|
]
|
||||||
change_readonly_fields = (
|
change_readonly_fields = (
|
||||||
'account_link', 'type', 'is_open', 'amend_of_link', 'amend_links'
|
'account_link', 'type', 'is_open', 'amend_of_link', 'amend_links'
|
||||||
|
@ -280,7 +289,7 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
'closed_on_display', 'updated_on_display', 'display_total_with_subtotals',
|
'closed_on_display', 'updated_on_display', 'display_total_with_subtotals',
|
||||||
)
|
)
|
||||||
inlines = [BillLineInline, ClosedBillLineInline]
|
inlines = [BillLineInline, ClosedBillLineInline]
|
||||||
date_hierarchy = 'closed_on'
|
#date_hierarchy = 'closed_on'
|
||||||
|
|
||||||
created_on_display = admin_date('created_on', short_description=_("Created"))
|
created_on_display = admin_date('created_on', short_description=_("Created"))
|
||||||
closed_on_display = admin_date('closed_on', short_description=_("Closed"))
|
closed_on_display = admin_date('closed_on', short_description=_("Closed"))
|
||||||
|
|
|
@ -423,7 +423,7 @@ class BillLine(models.Model):
|
||||||
def get_verbose_quantity(self):
|
def get_verbose_quantity(self):
|
||||||
return self.verbose_quantity or self.quantity
|
return self.verbose_quantity or self.quantity
|
||||||
|
|
||||||
def clean():
|
def clean(self):
|
||||||
if not self.verbose_quantity:
|
if not self.verbose_quantity:
|
||||||
quantity = str(self.quantity)
|
quantity = str(self.quantity)
|
||||||
# Strip trailing zeros
|
# Strip trailing zeros
|
||||||
|
|
|
@ -3,6 +3,12 @@
|
||||||
|
|
||||||
|
|
||||||
{% block object-tools-items %}
|
{% block object-tools-items %}
|
||||||
|
<li>
|
||||||
|
{% url 'admin:bills_billline_changelist' as list_url %}
|
||||||
|
<a href="{% add_preserved_filters list_url is_popup to_field %}" class="historylink">
|
||||||
|
{% trans "Lines" %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
{% url 'admin:bills_bill_add' as add_url %}
|
{% url 'admin:bills_bill_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">
|
|
@ -0,0 +1,12 @@
|
||||||
|
{% extends "admin/change_list.html" %}
|
||||||
|
{% load i18n admin_urls %}
|
||||||
|
|
||||||
|
{% block breadcrumbs %}
|
||||||
|
<div class="breadcrumbs">
|
||||||
|
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
|
||||||
|
› <a href="{% url 'admin:app_list' app_label=cl.opts.app_label %}">{{ cl.opts.app_config.verbose_name }}</a>
|
||||||
|
› <a href="{% url 'admin:bills_bill_changelist' %}">{% trans "Bills" %}</a>
|
||||||
|
› {% if bill %}<a href="{% url 'admin:bills_bill_change' bill.pk %}">{{ bill }}</a>{% else %}{% trans 'Multiple bills' %}{% endif %}
|
||||||
|
› {{ cl.opts.verbose_name_plural|capfirst }}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
|
@ -143,19 +143,19 @@ class Ticket(models.Model):
|
||||||
|
|
||||||
def reject(self):
|
def reject(self):
|
||||||
self.state = Ticket.REJECTED
|
self.state = Ticket.REJECTED
|
||||||
self.save(update_fields=['state'])
|
self.save(update_fields=('state', 'updated_at'))
|
||||||
|
|
||||||
def resolve(self):
|
def resolve(self):
|
||||||
self.state = Ticket.RESOLVED
|
self.state = Ticket.RESOLVED
|
||||||
self.save(update_fields=['state'])
|
self.save(update_fields=('state', 'updated_at'))
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
self.state = Ticket.CLOSED
|
self.state = Ticket.CLOSED
|
||||||
self.save(update_fields=['state'])
|
self.save(update_fields=('state', 'updated_at'))
|
||||||
|
|
||||||
def take(self, user):
|
def take(self, user):
|
||||||
self.owner = user
|
self.owner = user
|
||||||
self.save(update_fields=['state'])
|
self.save(update_fields=('state', 'updated_at'))
|
||||||
|
|
||||||
|
|
||||||
class Message(models.Model):
|
class Message(models.Model):
|
||||||
|
|
|
@ -4,7 +4,7 @@ from django.http import HttpResponseRedirect
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.admin import ChangeViewActionsMixin, ExtendedModelAdmin
|
from orchestra.admin import ChangeViewActionsMixin, ExtendedModelAdmin
|
||||||
from orchestra.admin.utils import admin_colored, admin_link
|
from orchestra.admin.utils import admin_colored, admin_link, admin_date
|
||||||
from orchestra.contrib.accounts.actions import list_accounts
|
from orchestra.contrib.accounts.actions import list_accounts
|
||||||
from orchestra.contrib.accounts.admin import AccountAdminMixin, SelectAccountAdminMixin
|
from orchestra.contrib.accounts.admin import AccountAdminMixin, SelectAccountAdminMixin
|
||||||
from orchestra.plugins.admin import SelectPluginAdminMixin
|
from orchestra.plugins.admin import SelectPluginAdminMixin
|
||||||
|
@ -61,7 +61,7 @@ class TransactionInline(admin.TabularInline):
|
||||||
|
|
||||||
class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
list_display = (
|
list_display = (
|
||||||
'id', 'bill_link', 'account_link', 'source_link', 'display_state',
|
'id', 'bill_link', 'account_link', 'source_link', 'display_created_at', 'display_modified_at', 'display_state',
|
||||||
'amount', 'process_link'
|
'amount', 'process_link'
|
||||||
)
|
)
|
||||||
list_filter = ('source__method', 'state')
|
list_filter = ('source__method', 'state')
|
||||||
|
@ -78,6 +78,10 @@ class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
'process_link'
|
'process_link'
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
|
(_("Dates"), {
|
||||||
|
'classes': ('wide',),
|
||||||
|
'fields': ('display_created_at', 'display_modified_at'),
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
add_fieldsets = (
|
add_fieldsets = (
|
||||||
(None, {
|
(None, {
|
||||||
|
@ -100,7 +104,8 @@ class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
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 = (
|
||||||
'bill_link', 'display_state', 'process_link', 'account_link', 'source_link'
|
'bill_link', 'display_state', 'process_link', 'account_link', 'source_link',
|
||||||
|
'display_created_at', 'display_modified_at'
|
||||||
)
|
)
|
||||||
list_select_related = ('source', 'bill__account', 'process')
|
list_select_related = ('source', 'bill__account', 'process')
|
||||||
date_hierarchy = 'created_at'
|
date_hierarchy = 'created_at'
|
||||||
|
@ -109,6 +114,8 @@ class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
source_link = admin_link('source')
|
source_link = admin_link('source')
|
||||||
process_link = admin_link('process', short_description=_("proc"))
|
process_link = admin_link('process', short_description=_("proc"))
|
||||||
account_link = admin_link('bill__account')
|
account_link = admin_link('bill__account')
|
||||||
|
display_created_at = admin_date('created_at', short_description=_("Created"))
|
||||||
|
display_modified_at = admin_date('modified_at', short_description=_("Modified"))
|
||||||
|
|
||||||
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()
|
||||||
|
@ -135,7 +142,7 @@ class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
|
|
||||||
|
|
||||||
class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
|
class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
|
||||||
list_display = ('id', 'file_url', 'display_transactions', 'created_at')
|
list_display = ('id', 'file_url', 'display_transactions', 'display_created_at')
|
||||||
fields = ('data', 'file_url', 'created_at')
|
fields = ('data', 'file_url', 'created_at')
|
||||||
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',)
|
||||||
|
@ -145,6 +152,8 @@ class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
|
||||||
)
|
)
|
||||||
actions = change_view_actions + (actions.delete_selected,)
|
actions = change_view_actions + (actions.delete_selected,)
|
||||||
|
|
||||||
|
display_created_at = admin_date('created_at', short_description=_("Created"))
|
||||||
|
|
||||||
def file_url(self, process):
|
def file_url(self, process):
|
||||||
if process.file:
|
if process.file:
|
||||||
return '<a href="%s">%s</a>' % (process.file.url, process.file.name)
|
return '<a href="%s">%s</a>' % (process.file.url, process.file.name)
|
||||||
|
@ -159,8 +168,8 @@ class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
|
||||||
color = STATE_COLORS.get(trans.state, 'black')
|
color = STATE_COLORS.get(trans.state, 'black')
|
||||||
state = trans.get_state_display()
|
state = trans.get_state_display()
|
||||||
ids.append('<span style="color:%s" title="%s">%i</span>' % (color, state, trans.id))
|
ids.append('<span style="color:%s" title="%s">%i</span>' % (color, state, trans.id))
|
||||||
counter += 1
|
counter += 1 + len(str(trans.id))
|
||||||
if counter > 10:
|
if counter > 125:
|
||||||
counter = 0
|
counter = 0
|
||||||
lines.append(','.join(ids))
|
lines.append(','.join(ids))
|
||||||
ids = []
|
ids = []
|
||||||
|
|
|
@ -27,7 +27,7 @@ def post_delete_processes(modeladmin, request, related_transactions):
|
||||||
num = 0
|
num = 0
|
||||||
for transaction in related_transactions:
|
for transaction in related_transactions:
|
||||||
transaction.state = Transaction.WAITTING_PROCESSING
|
transaction.state = Transaction.WAITTING_PROCESSING
|
||||||
transaction.save(update_fields=('state',))
|
transaction.save(update_fields=('state', 'modified_at'))
|
||||||
num += 1
|
num += 1
|
||||||
modeladmin.log_change(request, transaction, _("Unprocessed"))
|
modeladmin.log_change(request, transaction, _("Unprocessed"))
|
||||||
messages.success(request, ungettext(
|
messages.success(request, ungettext(
|
||||||
|
|
|
@ -200,7 +200,7 @@ class SEPADirectDebit(PaymentMethod):
|
||||||
for transaction in transactions:
|
for transaction in transactions:
|
||||||
transaction.process = process
|
transaction.process = process
|
||||||
transaction.state = transaction.WAITTING_EXECUTION
|
transaction.state = transaction.WAITTING_EXECUTION
|
||||||
transaction.save(update_fields=['state', 'process'])
|
transaction.save(update_fields=('state', 'process', 'modified_at'))
|
||||||
account = transaction.account
|
account = transaction.account
|
||||||
data = transaction.source.data
|
data = transaction.source.data
|
||||||
yield E.DrctDbtTxInf( # Direct Debit Transaction Info
|
yield E.DrctDbtTxInf( # Direct Debit Transaction Info
|
||||||
|
@ -245,7 +245,7 @@ class SEPADirectDebit(PaymentMethod):
|
||||||
for transaction in transactions:
|
for transaction in transactions:
|
||||||
transaction.process = process
|
transaction.process = process
|
||||||
transaction.state = transaction.WAITTING_EXECUTION
|
transaction.state = transaction.WAITTING_EXECUTION
|
||||||
transaction.save(update_fields=['state', 'process'])
|
transaction.save(update_fields=('state', 'process', 'modified_at'))
|
||||||
account = transaction.account
|
account = transaction.account
|
||||||
data = transaction.source.data
|
data = transaction.source.data
|
||||||
yield E.CdtTrfTxInf( # Credit Transfer Transaction Info
|
yield E.CdtTrfTxInf( # Credit Transfer Transaction Info
|
||||||
|
|
|
@ -190,16 +190,16 @@ class TransactionProcess(models.Model):
|
||||||
self.state = self.EXECUTED
|
self.state = self.EXECUTED
|
||||||
for transaction in self.transactions.all():
|
for transaction in self.transactions.all():
|
||||||
transaction.mark_as_executed()
|
transaction.mark_as_executed()
|
||||||
self.save(update_fields=('state',))
|
self.save(update_fields=('state', 'updated_at'))
|
||||||
|
|
||||||
def abort(self):
|
def abort(self):
|
||||||
self.state = self.ABORTED
|
self.state = self.ABORTED
|
||||||
for transaction in self.transaction.all():
|
for transaction in self.transaction.all():
|
||||||
transaction.mark_as_aborted()
|
transaction.mark_as_aborted()
|
||||||
self.save(update_fields=('state',))
|
self.save(update_fields=('state', 'updated_at'))
|
||||||
|
|
||||||
def commit(self):
|
def commit(self):
|
||||||
self.state = self.COMMITED
|
self.state = self.COMMITED
|
||||||
for transaction in self.transactions.processing():
|
for transaction in self.transactions.processing():
|
||||||
transaction.mark_as_secured()
|
transaction.mark_as_secured()
|
||||||
self.save(update_fields=('state',))
|
self.save(update_fields=('state', 'updated_at'))
|
||||||
|
|
Loading…
Reference in a new issue