Skip to content
Snippets Groups Projects
Verified Commit 5a806de1 authored by Nik | Klampfradler's avatar Nik | Klampfradler
Browse files

Implement mass actions for invoices table

parent 05450546
No related branches found
No related tags found
No related merge requests found
from django_filters import ChoiceFilter, FilterSet
from material import Layout, Row
from payments import PaymentStatus
from .models.invoice import Invoice
class InvoicesFilter(FilterSet):
variant = ChoiceFilter(choices=Invoice.get_variant_choices())
status = ChoiceFilter(choices=PaymentStatus.CHOICES)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.form.layout = Layout(
Row("variant", "status"),
)
class Meta:
models = Invoice
from django.utils.translation import gettext as _
from material import Layout, Row
from aleksis.core.forms import ActionForm
from aleksis.core.mixins import ExtensibleForm
from .models.base import Client
from .models.invoice import InvoiceGroup
from .tasks import email_invoice
def send_emails_action(modeladmin, request, queryset):
"""Send e-mails for selected invoices."""
email_invoice.delay(list(queryset.values_list("token", flat=True)))
send_emails_action.short_description = _("Send e-mails")
send_emails_action.permission = "tezor.send_invoice_email"
class InvoicesActionForm(ActionForm):
def get_actions(self):
return [send_emails_action]
class EditClientForm(ExtensibleForm):
"""Form to create or edit clients."""
layout = Layout("name")
layout = Layout("name", "email")
class Meta:
model = Client
......
......@@ -3,6 +3,8 @@ from django.utils.translation import gettext_lazy as _
import django_tables2 as tables
from django_tables2.utils import A
from aleksis.core.util.tables import SelectColumn
class PurchasedItemsTable(tables.Table):
sku = tables.Column(verbose_name=_("Art. No."))
......@@ -86,6 +88,7 @@ class InvoiceGroupsTable(tables.Table):
class InvoicesTable(tables.Table):
selected = SelectColumn()
number = tables.Column()
status = tables.Column()
......@@ -105,3 +108,6 @@ class InvoicesTable(tables.Table):
verbose_name=_("Print"),
text=_("Print"),
)
class Meta:
attrs = {"class": "highlight"}
from typing import Union
from aleksis.core.celery import app
from aleksis.core.util.email import send_email
from aleksis.core.util.pdf import generate_pdf_from_template
......@@ -6,19 +8,23 @@ from .models.invoice import Invoice
@app.task
def email_invoice(invoice_token):
context = {}
invoice = Invoice.objects.get(token=invoice_token)
context["invoice"] = invoice
def email_invoice(tokens: Union[list[str], str]):
if not isinstance(tokens, list):
tokens = [tokens]
for token in tokens:
context = {}
invoice = Invoice.objects.get(token=token)
context["invoice"] = invoice
invoice_pdf, result = generate_pdf_from_template(invoice.group.template_name, context)
result.wait(timeout=30, disable_sync_subtasks=False)
invoice_pdf.refresh_from_db()
invoice_pdf, result = generate_pdf_from_template(invoice.group.template_name, context)
result.wait(timeout=30, disable_sync_subtasks=False)
invoice_pdf.refresh_from_db()
send_email(
template_name="invoice",
from_email=invoice.group.client.email,
recipient_list=invoice.get_billing_email_recipients(),
context=context,
attachments=[(invoice_pdf.file.name, invoice_pdf.file.read(), "application/pdf")],
)
send_email(
template_name="invoice",
from_email=invoice.group.client.email,
recipient_list=invoice.get_billing_email_recipients(),
context=context,
attachments=[(invoice_pdf.file.name, invoice_pdf.file.read(), "application/pdf")],
)
{% extends "core/base.html" %}
{% load material_form i18n %}
{% load material_form i18n static %}
{% load render_table from django_tables2 %}
{% block page_title %}{{ object }}{% endblock %}
{% block browser_title %}{{ object }}{% endblock %}
{% block content %}
<a class="btn colour-primary waves-effect waves-light" href="{% url 'client_by_pk' object.client.pk %}">{% trans "Back" %}</a>
<a class="btn colour-primary waves-effect waves-light" href="{% url 'client_by_pk' object.client.pk %}">{% trans "Back" %}</a>
{% render_table invoices_table %}
<div class="card">
<div class="card-content">
<div class="card-title">{% trans "Filter invoices" %}</div>
<form method="get">
{% form form=filter.form %}{% endform %}
{% trans "Search" as caption %}
{% include "core/partials/save_button.html" with caption=caption icon="search" %}
<button type="reset" class="btn red waves-effect waves-light">
<i class="material-icons left">clear</i>
{% trans "Clear" %}
</button>
</form>
</div>
</div>
<div class="card">
<div class="card-content">
<form action="" method="post">
{% csrf_token %}
<div class="row">
<div class="col s12 {% if action_form %}m4 l4 xl6{% endif %}">
<div class="card-title">{% trans "Selected invoices" %}</div>
</div>
{% if action_form %}
<div class="col s12 m8 l8 xl6">
<div class="col s12 m8">
{% form form=action_form %}{% endform %}
</div>
<div class="col s12 m4">
<button type="submit" class="btn waves-effect waves-primary">
{% trans "Execute" %}
<i class="material-icons right">send</i>
</button>
</div>
</div>
{% endif %}
</div>
{% render_table invoices_table %}
</form>
</div>
</div>
<script src="{% static "js/multi_select.js" %}"></script>
{% endblock %}
from django.conf import settings
from django.core.exceptions import PermissionDenied, SuspiciousOperation
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse_lazy
from django.urls import reverse, reverse_lazy
from django.utils.decorators import method_decorator
from django.utils.translation import ugettext as _
from django.views.decorators.cache import never_cache
......@@ -15,7 +15,8 @@ from rules.contrib.views import PermissionRequiredMixin
from aleksis.core.mixins import AdvancedCreateView, AdvancedDeleteView, AdvancedEditView
from aleksis.core.views import RenderPDFView
from .forms import EditClientForm, EditInvoiceGroupForm
from .filters import InvoicesFilter
from .forms import EditClientForm, EditInvoiceGroupForm, InvoicesActionForm
from .models.base import Client
from .models.invoice import Invoice, InvoiceGroup
from .tables import ClientsTable, InvoiceGroupsTable, InvoicesTable
......@@ -141,14 +142,29 @@ class InvoiceGroupDetailView(PermissionRequiredMixin, DetailView):
permission_required = "tezor.view_invoice_group_rule"
template_name = "tezor/invoice_group/full.html"
def post(self, request, *args, **kwargs):
r = super().get(request, *args, **kwargs)
if self.invoices_action_form.is_valid():
action = self.invoices_action_form._get_actions_dict()[self.invoices_action_form.cleaned_data["action"]]
if request.user.has_perm(action.permission):
self.invoices_action_form.execute()
return r
def get_context_data(self, object):
context = super().get_context_data()
invoices = object.invoices.all()
qs = object.invoices.all()
invoices_filter = InvoicesFilter(self.request.GET, qs)
context["filter"] = invoices_filter
invoices = invoices_filter.qs
invoices_table = InvoicesTable(invoices)
RequestConfig(self.request).configure(invoices_table)
context["invoices_table"] = invoices_table
self.invoices_action_form = InvoicesActionForm(self.request, self.request.POST or None, queryset=invoices)
context["action_form"] = self.invoices_action_form
return context
......@@ -160,7 +176,6 @@ class InvoiceGroupCreateView(PermissionRequiredMixin, AdvancedCreateView):
form_class = EditInvoiceGroupForm
permission_required = "tezor.create_invoice_groups_rule"
template_name = "tezor/invoice_group/create.html"
success_url = reverse_lazy("clients")
success_message = _("The invoice group has been created.")
def form_valid(self, form):
......@@ -173,6 +188,9 @@ class InvoiceGroupCreateView(PermissionRequiredMixin, AdvancedCreateView):
return super().form_valid(form)
def get_success_url(self):
return reverse("client_by_pk", args=[self.object.client.pk])
@method_decorator(never_cache, name="dispatch")
class InvoiceGroupEditView(PermissionRequiredMixin, AdvancedEditView):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment