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)
|
||||
|
||||
|
||||
def get_ids(modeladmin, request, queryset):
|
||||
ids = ','.join(map(str, queryset.values_list('id', flat=True)))
|
||||
return HttpResponseRedirect('?id__in=%s' % ids)
|
||||
def list_bills(modeladmin, request, queryset):
|
||||
ids = ','.join(map(str, queryset.values_list('bill_id', flat=True).distinct()))
|
||||
return HttpResponseRedirect('../bill/?id__in=%s' % ids)
|
||||
|
|
|
@ -138,7 +138,8 @@ class BillLineAdmin(admin.ModelAdmin):
|
|||
'tax', 'subtotal', 'display_sublinetotal', 'display_total'
|
||||
)
|
||||
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 = (
|
||||
(None, {
|
||||
|
@ -171,8 +172,9 @@ class BillLineAdmin(admin.ModelAdmin):
|
|||
display_is_open.boolean = True
|
||||
|
||||
def display_sublinetotal(self, instance):
|
||||
return instance.subline_total or ''
|
||||
display_sublinetotal.short_description = _("Subline")
|
||||
total = instance.subline_total
|
||||
return total if total is not None else '---'
|
||||
display_sublinetotal.short_description = _("Sublines")
|
||||
display_sublinetotal.admin_order_field = 'subline_total'
|
||||
|
||||
def display_total(self, instance):
|
||||
|
@ -196,6 +198,11 @@ class BillLineAdmin(admin.ModelAdmin):
|
|||
computed_total=(F('subtotal') + Sum(Coalesce('sublines__total', 0))) * (1+F('tax')/100),
|
||||
)
|
||||
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):
|
||||
|
@ -216,19 +223,21 @@ class BillLineManagerAdmin(BillLineAdmin):
|
|||
messages.error(request, _("No bills selected."))
|
||||
return redirect('..')
|
||||
self.bill_ids = bill_ids
|
||||
bill = None
|
||||
if len(bill_ids) == 1:
|
||||
bill_url = reverse('admin:bills_bill_change', args=(bill_ids[0],))
|
||||
bill = Bill.objects.get(pk=bill_ids[0])
|
||||
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:
|
||||
messages.warning(request, _("Bill not in open state."))
|
||||
else:
|
||||
if Bill.objects.filter(id__in=bill_ids, is_open=False).exists():
|
||||
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 = {
|
||||
'title': title,
|
||||
'bill': bill,
|
||||
}
|
||||
context.update(extra_context or {})
|
||||
return super().changelist_view(request, context)
|
||||
|
@ -244,7 +253,7 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
|||
AmendedListFilter
|
||||
)
|
||||
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 = (
|
||||
(None, {
|
||||
'fields': ['number', 'type', 'amend_of_link', 'account_link',
|
||||
|
@ -270,7 +279,7 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
|||
actions = [
|
||||
actions.manage_lines, actions.download_bills, actions.close_bills, actions.send_bills,
|
||||
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 = (
|
||||
'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',
|
||||
)
|
||||
inlines = [BillLineInline, ClosedBillLineInline]
|
||||
date_hierarchy = 'closed_on'
|
||||
#date_hierarchy = 'closed_on'
|
||||
|
||||
created_on_display = admin_date('created_on', short_description=_("Created"))
|
||||
closed_on_display = admin_date('closed_on', short_description=_("Closed"))
|
||||
|
|
|
@ -423,7 +423,7 @@ class BillLine(models.Model):
|
|||
def get_verbose_quantity(self):
|
||||
return self.verbose_quantity or self.quantity
|
||||
|
||||
def clean():
|
||||
def clean(self):
|
||||
if not self.verbose_quantity:
|
||||
quantity = str(self.quantity)
|
||||
# Strip trailing zeros
|
||||
|
|
|
@ -3,6 +3,12 @@
|
|||
|
||||
|
||||
{% 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>
|
||||
{% url 'admin:bills_bill_add' as add_url %}
|
||||
<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):
|
||||
self.state = Ticket.REJECTED
|
||||
self.save(update_fields=['state'])
|
||||
self.save(update_fields=('state', 'updated_at'))
|
||||
|
||||
def resolve(self):
|
||||
self.state = Ticket.RESOLVED
|
||||
self.save(update_fields=['state'])
|
||||
self.save(update_fields=('state', 'updated_at'))
|
||||
|
||||
def close(self):
|
||||
self.state = Ticket.CLOSED
|
||||
self.save(update_fields=['state'])
|
||||
self.save(update_fields=('state', 'updated_at'))
|
||||
|
||||
def take(self, user):
|
||||
self.owner = user
|
||||
self.save(update_fields=['state'])
|
||||
self.save(update_fields=('state', 'updated_at'))
|
||||
|
||||
|
||||
class Message(models.Model):
|
||||
|
|
|
@ -4,7 +4,7 @@ from django.http import HttpResponseRedirect
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
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.admin import AccountAdminMixin, SelectAccountAdminMixin
|
||||
from orchestra.plugins.admin import SelectPluginAdminMixin
|
||||
|
@ -61,7 +61,7 @@ class TransactionInline(admin.TabularInline):
|
|||
|
||||
class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||
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'
|
||||
)
|
||||
list_filter = ('source__method', 'state')
|
||||
|
@ -78,6 +78,10 @@ class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
|||
'process_link'
|
||||
)
|
||||
}),
|
||||
(_("Dates"), {
|
||||
'classes': ('wide',),
|
||||
'fields': ('display_created_at', 'display_modified_at'),
|
||||
}),
|
||||
)
|
||||
add_fieldsets = (
|
||||
(None, {
|
||||
|
@ -100,7 +104,8 @@ class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
|||
filter_by_account_fields = ('bill', 'source')
|
||||
change_readonly_fields = ('amount', 'currency')
|
||||
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')
|
||||
date_hierarchy = 'created_at'
|
||||
|
@ -109,6 +114,8 @@ class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
|||
source_link = admin_link('source')
|
||||
process_link = admin_link('process', short_description=_("proc"))
|
||||
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):
|
||||
actions = super(TransactionAdmin, self).get_change_view_actions()
|
||||
|
@ -135,7 +142,7 @@ class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
|||
|
||||
|
||||
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')
|
||||
readonly_fields = ('data', 'file_url', 'display_transactions', 'created_at')
|
||||
list_prefetch_related = ('transactions',)
|
||||
|
@ -145,6 +152,8 @@ class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
|
|||
)
|
||||
actions = change_view_actions + (actions.delete_selected,)
|
||||
|
||||
display_created_at = admin_date('created_at', short_description=_("Created"))
|
||||
|
||||
def file_url(self, process):
|
||||
if process.file:
|
||||
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')
|
||||
state = trans.get_state_display()
|
||||
ids.append('<span style="color:%s" title="%s">%i</span>' % (color, state, trans.id))
|
||||
counter += 1
|
||||
if counter > 10:
|
||||
counter += 1 + len(str(trans.id))
|
||||
if counter > 125:
|
||||
counter = 0
|
||||
lines.append(','.join(ids))
|
||||
ids = []
|
||||
|
|
|
@ -27,7 +27,7 @@ def post_delete_processes(modeladmin, request, related_transactions):
|
|||
num = 0
|
||||
for transaction in related_transactions:
|
||||
transaction.state = Transaction.WAITTING_PROCESSING
|
||||
transaction.save(update_fields=('state',))
|
||||
transaction.save(update_fields=('state', 'modified_at'))
|
||||
num += 1
|
||||
modeladmin.log_change(request, transaction, _("Unprocessed"))
|
||||
messages.success(request, ungettext(
|
||||
|
|
|
@ -200,7 +200,7 @@ class SEPADirectDebit(PaymentMethod):
|
|||
for transaction in transactions:
|
||||
transaction.process = process
|
||||
transaction.state = transaction.WAITTING_EXECUTION
|
||||
transaction.save(update_fields=['state', 'process'])
|
||||
transaction.save(update_fields=('state', 'process', 'modified_at'))
|
||||
account = transaction.account
|
||||
data = transaction.source.data
|
||||
yield E.DrctDbtTxInf( # Direct Debit Transaction Info
|
||||
|
@ -245,7 +245,7 @@ class SEPADirectDebit(PaymentMethod):
|
|||
for transaction in transactions:
|
||||
transaction.process = process
|
||||
transaction.state = transaction.WAITTING_EXECUTION
|
||||
transaction.save(update_fields=['state', 'process'])
|
||||
transaction.save(update_fields=('state', 'process', 'modified_at'))
|
||||
account = transaction.account
|
||||
data = transaction.source.data
|
||||
yield E.CdtTrfTxInf( # Credit Transfer Transaction Info
|
||||
|
|
|
@ -190,16 +190,16 @@ class TransactionProcess(models.Model):
|
|||
self.state = self.EXECUTED
|
||||
for transaction in self.transactions.all():
|
||||
transaction.mark_as_executed()
|
||||
self.save(update_fields=('state',))
|
||||
self.save(update_fields=('state', 'updated_at'))
|
||||
|
||||
def abort(self):
|
||||
self.state = self.ABORTED
|
||||
for transaction in self.transaction.all():
|
||||
transaction.mark_as_aborted()
|
||||
self.save(update_fields=('state',))
|
||||
self.save(update_fields=('state', 'updated_at'))
|
||||
|
||||
def commit(self):
|
||||
self.state = self.COMMITED
|
||||
for transaction in self.transactions.processing():
|
||||
transaction.mark_as_secured()
|
||||
self.save(update_fields=('state',))
|
||||
self.save(update_fields=('state', 'updated_at'))
|
||||
|
|
Loading…
Reference in a new issue