mirror of
https://gitlab.crans.org/bde/nk20
synced 2025-06-20 17:41:55 +02:00
Billing -> Invoice
This commit is contained in:
@ -3,11 +3,11 @@
|
||||
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import Billing, Product
|
||||
from .models import Invoice, Product
|
||||
|
||||
|
||||
@admin.register(Billing)
|
||||
class BillingAdmin(admin.ModelAdmin):
|
||||
@admin.register(Invoice)
|
||||
class InvoiceAdmin(admin.ModelAdmin):
|
||||
list_display = ('id', 'name', 'subject', 'acquitted', )
|
||||
|
||||
|
||||
|
@ -4,17 +4,17 @@
|
||||
from crispy_forms.helper import FormHelper
|
||||
from django import forms
|
||||
|
||||
from .models import Billing, Product
|
||||
from .models import Invoice, Product
|
||||
|
||||
|
||||
class BillingForm(forms.ModelForm):
|
||||
class InvoiceForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Billing
|
||||
model = Invoice
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
ProductFormSet = forms.inlineformset_factory(
|
||||
Billing,
|
||||
Invoice,
|
||||
Product,
|
||||
fields='__all__',
|
||||
extra=1,
|
||||
|
@ -5,10 +5,10 @@ from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class Billing(models.Model):
|
||||
class Invoice(models.Model):
|
||||
id = models.PositiveIntegerField(
|
||||
primary_key=True,
|
||||
verbose_name=_("Billing identifier"),
|
||||
verbose_name=_("Invoice identifier"),
|
||||
)
|
||||
|
||||
bde = models.CharField(
|
||||
@ -104,8 +104,8 @@ class Billing(models.Model):
|
||||
|
||||
|
||||
class Product(models.Model):
|
||||
billing = models.ForeignKey(
|
||||
Billing,
|
||||
invoice = models.ForeignKey(
|
||||
Invoice,
|
||||
on_delete=models.PROTECT,
|
||||
)
|
||||
|
||||
|
@ -5,16 +5,16 @@ import django_tables2 as tables
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django_tables2 import A
|
||||
|
||||
from .models import Billing
|
||||
from .models import Invoice
|
||||
|
||||
|
||||
class BillingTable(tables.Table):
|
||||
id = tables.LinkColumn("treasury:billing_update",
|
||||
class InvoiceTable(tables.Table):
|
||||
id = tables.LinkColumn("treasury:invoice_update",
|
||||
args=[A("pk")],
|
||||
text=lambda record: _("Billing #{:d}").format(record.id), )
|
||||
text=lambda record: _("Invoice #{:d}").format(record.id), )
|
||||
|
||||
billing = tables.LinkColumn("treasury:billing_render",
|
||||
verbose_name=_("Billing"),
|
||||
invoice = tables.LinkColumn("treasury:invoice_render",
|
||||
verbose_name=_("Invoice"),
|
||||
args=[A("pk")],
|
||||
accessor="pk",
|
||||
text="",
|
||||
@ -27,6 +27,6 @@ class BillingTable(tables.Table):
|
||||
attrs = {
|
||||
'class': 'table table-condensed table-striped table-hover'
|
||||
}
|
||||
model = Billing
|
||||
model = Invoice
|
||||
template_name = 'django_tables2/bootstrap4.html'
|
||||
fields = ('id', 'name', 'subject', 'acquitted', 'billing',)
|
||||
fields = ('id', 'name', 'subject', 'acquitted', 'invoice',)
|
||||
|
@ -3,12 +3,12 @@
|
||||
|
||||
from django.urls import path
|
||||
|
||||
from .views import BillingCreateView, BillingListView, BillingUpdateView, BillingRenderView
|
||||
from .views import InvoiceCreateView, InvoiceListView, InvoiceUpdateView, InvoiceRenderView
|
||||
|
||||
app_name = 'treasury'
|
||||
urlpatterns = [
|
||||
path('billing/', BillingListView.as_view(), name='billing'),
|
||||
path('billing/create/', BillingCreateView.as_view(), name='billing_create'),
|
||||
path('billing/<int:pk>/', BillingUpdateView.as_view(), name='billing_update'),
|
||||
path('billing/render/<int:pk>/', BillingRenderView.as_view(), name='billing_render'),
|
||||
path('invoice/', InvoiceListView.as_view(), name='invoice'),
|
||||
path('invoice/create/', InvoiceCreateView.as_view(), name='invoice_create'),
|
||||
path('invoice/<int:pk>/', InvoiceUpdateView.as_view(), name='invoice_update'),
|
||||
path('invoice/render/<int:pk>/', InvoiceRenderView.as_view(), name='invoice_render'),
|
||||
]
|
||||
|
@ -17,17 +17,17 @@ from django.views.generic.base import View
|
||||
from django_tables2 import SingleTableView
|
||||
from note_kfet.settings.base import BASE_DIR
|
||||
|
||||
from .forms import BillingForm, ProductFormSet, ProductFormSetHelper
|
||||
from .models import Billing, Product
|
||||
from .tables import BillingTable
|
||||
from .forms import InvoiceForm, ProductFormSet, ProductFormSetHelper
|
||||
from .models import Invoice, Product
|
||||
from .tables import InvoiceTable
|
||||
|
||||
|
||||
class BillingCreateView(LoginRequiredMixin, CreateView):
|
||||
class InvoiceCreateView(LoginRequiredMixin, CreateView):
|
||||
"""
|
||||
Create Billing
|
||||
Create Invoice
|
||||
"""
|
||||
model = Billing
|
||||
form_class = BillingForm
|
||||
model = Invoice
|
||||
form_class = InvoiceForm
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
@ -64,23 +64,23 @@ class BillingCreateView(LoginRequiredMixin, CreateView):
|
||||
return ret
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse_lazy('treasury:billing')
|
||||
return reverse_lazy('treasury:invoice')
|
||||
|
||||
|
||||
class BillingListView(LoginRequiredMixin, SingleTableView):
|
||||
class InvoiceListView(LoginRequiredMixin, SingleTableView):
|
||||
"""
|
||||
List existing Billings
|
||||
List existing Invoices
|
||||
"""
|
||||
model = Billing
|
||||
table_class = BillingTable
|
||||
model = Invoice
|
||||
table_class = InvoiceTable
|
||||
|
||||
|
||||
class BillingUpdateView(LoginRequiredMixin, UpdateView):
|
||||
class InvoiceUpdateView(LoginRequiredMixin, UpdateView):
|
||||
"""
|
||||
Create Billing
|
||||
Create Invoice
|
||||
"""
|
||||
model = Billing
|
||||
form_class = BillingForm
|
||||
model = Invoice
|
||||
form_class = InvoiceForm
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
@ -119,27 +119,27 @@ class BillingUpdateView(LoginRequiredMixin, UpdateView):
|
||||
else:
|
||||
f.instance = None
|
||||
|
||||
Product.objects.filter(~Q(pk__in=saved), billing=form.instance).delete()
|
||||
Product.objects.filter(~Q(pk__in=saved), invoice=form.instance).delete()
|
||||
|
||||
return ret
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse_lazy('treasury:billing')
|
||||
return reverse_lazy('treasury:invoice')
|
||||
|
||||
|
||||
class BillingRenderView(LoginRequiredMixin, View):
|
||||
class InvoiceRenderView(LoginRequiredMixin, View):
|
||||
"""
|
||||
Render Billing as generated PDF
|
||||
Render Invoice as generated PDF
|
||||
"""
|
||||
|
||||
def get(self, request, **kwargs):
|
||||
pk = kwargs["pk"]
|
||||
billing = Billing.objects.get(pk=pk)
|
||||
products = Product.objects.filter(billing=billing).all()
|
||||
invoice = Invoice.objects.get(pk=pk)
|
||||
products = Product.objects.filter(invoice=invoice).all()
|
||||
|
||||
billing.description = billing.description.replace("\n", "\\newline\n")
|
||||
billing.address = billing.address.replace("\n", "\\newline\n")
|
||||
tex = render_to_string("treasury/billing_sample.tex", dict(obj=billing, products=products))
|
||||
invoice.description = invoice.description.replace("\n", "\\newline\n")
|
||||
invoice.address = invoice.address.replace("\n", "\\newline\n")
|
||||
tex = render_to_string("treasury/invoice_sample.tex", dict(obj=invoice, products=products))
|
||||
try:
|
||||
os.mkdir(BASE_DIR + "/tmp")
|
||||
except FileExistsError:
|
||||
@ -147,13 +147,13 @@ class BillingRenderView(LoginRequiredMixin, View):
|
||||
tmp_dir = mkdtemp(prefix=BASE_DIR + "/tmp/")
|
||||
|
||||
try:
|
||||
with open("{}/billing-{:d}.tex".format(tmp_dir, pk), "wb") as f:
|
||||
with open("{}/invoice-{:d}.tex".format(tmp_dir, pk), "wb") as f:
|
||||
f.write(tex.encode("UTF-8"))
|
||||
del tex
|
||||
|
||||
for _ in range(2):
|
||||
error = subprocess.Popen(
|
||||
["pdflatex", "billing-{}.tex".format(pk)],
|
||||
["pdflatex", "invoice-{}.tex".format(pk)],
|
||||
cwd=tmp_dir,
|
||||
stdin=open(os.devnull, "r"),
|
||||
stderr=open(os.devnull, "wb"),
|
||||
@ -161,11 +161,11 @@ class BillingRenderView(LoginRequiredMixin, View):
|
||||
).wait()
|
||||
|
||||
if error:
|
||||
raise IOError("An error attempted while generating a billing (code=" + str(error) + ")")
|
||||
raise IOError("An error attempted while generating a invoice (code=" + str(error) + ")")
|
||||
|
||||
pdf = open("{}/billing-{}.pdf".format(tmp_dir, pk), 'rb').read()
|
||||
pdf = open("{}/invoice-{}.pdf".format(tmp_dir, pk), 'rb').read()
|
||||
response = HttpResponse(pdf, content_type="application/pdf")
|
||||
response['Content-Disposition'] = "inline;filename=billing-{:d}.pdf".format(pk)
|
||||
response['Content-Disposition'] = "inline;filename=invoice-{:d}.pdf".format(pk)
|
||||
except IOError as e:
|
||||
raise e
|
||||
finally:
|
||||
|
Reference in New Issue
Block a user