PDF Rechnung fertig
This commit is contained in:
parent
8b106c569c
commit
91114eea82
|
|
@ -0,0 +1,8 @@
|
||||||
|
{% extends "users/base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="content-section col-12">
|
||||||
|
<h3>Rechnung betrachten</h3>
|
||||||
|
<hr>
|
||||||
|
<a href="{% url 'ag-getbillpdf' bill.pk %}" target="_blank">Hier herunterladen</a>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
||||||
|
|
@ -37,19 +37,21 @@
|
||||||
{% getNextMonth request.user.profile.agency as nextMonth %}
|
{% getNextMonth request.user.profile.agency as nextMonth %}
|
||||||
|
|
||||||
Ihre Agentur wurde am {{ request.user.profile.agency.registerdate|date:"d.m.Y" }} registriert.
|
Ihre Agentur wurde am {{ request.user.profile.agency.registerdate|date:"d.m.Y" }} registriert.
|
||||||
{% if paymentplan == "" or request.user.profile.agency.lexofficeid == "" %}
|
{% if paymentplan == "" %}
|
||||||
Es wurde noch keine Zahlungsweise ausgewählt. Sie können die Digitale Agentur bis zum {{nextMonth|date:"d.m.Y"}} kostenlos nutzen. Möchten Sie die Digitale Agentur auch nach diesem Zeitraum nutzen, wählen Sie bitte einen Zahlplan aus.
|
Es wurde noch keine Zahlungsweise ausgewählt. Sie können die Digitale Agentur bis zum {{nextMonth|date:"d.m.Y"}} kostenlos nutzen. Möchten Sie die Digitale Agentur auch nach diesem Zeitraum nutzen, wählen Sie bitte einen Zahlplan aus.
|
||||||
<br />
|
<br />
|
||||||
<a href="{% url 'ag-billplanupdate' request.user.profile.agency.pk %}" class="btn btn-primary btn mt-2" onclick="">Zahlplan jetzt auswählen</a>
|
<a href="{% url 'ag-billplanupdate' request.user.profile.agency.pk %}" class="btn btn-primary btn mt-2" onclick="">Zahlplan jetzt auswählen</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<br />Ausgewählter Zahlungsplan: {{request.user.profile.agency.paymentplan}} Monat{% if request.user.profile.agency.paymentplan > 1 %}e{% endif %} <br />
|
<br />
|
||||||
|
Ausgewählter Zahlungsplan: {{request.user.profile.agency.paymentplan}} Monat{% if request.user.profile.agency.paymentplan > 1 %}e{% endif %}<br />
|
||||||
|
Nächste Rechnungserstellung am: {{bills.0.end|date:"d.m.Y"}}<br />
|
||||||
<a href="#" class="btn btn-primary btn mt-2" onclick="">Zahlplan abbestellen</a>
|
<a href="#" class="btn btn-primary btn mt-2" onclick="">Zahlplan abbestellen</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<hr>
|
<hr>
|
||||||
<h5 class="card-title.">Fragen, Hilfe, Kündigung</h5>
|
<h5 class="card-title.">Fragen, Hilfe, Kündigung</h5>
|
||||||
Bei Fragen zu Ihrer Abrechnung melden Sie sich bitte per E-Mail an <a href="mailto:abrechnung@digitale-agentur.com">abrechnung@digitale-agentur.com</a>.
|
Bei Fragen zu Ihrer Abrechnung melden Sie sich bitte per E-Mail an <a href="mailto:abrechnung@digitale-agentur.com">abrechnung@digitale-agentur.com</a>.
|
||||||
<!-- TASK: Kündigungsmodaliäten einfügen -->
|
<!-- TASK: Kündigungsmodaliäten einfügen -->
|
||||||
KÜNDIGUNGSMODALITÄTEN NOCH EINFÜGEN
|
Die Kündigungsmodalitäten finden Sie in den AGB's. Alternativ wenden Sie sich an den Support.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -73,7 +75,7 @@
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">Rechnungen</h5>
|
<h5 class="card-title">Rechnungen</h5>
|
||||||
{% for bill in bills %}
|
{% for bill in bills %}
|
||||||
<a href="{{bill.lexid}}">Rechnung vom {{bill.billdate|date:"d.m.Y"}} (Nr. {{bill.billnumber}})</a><br />
|
<a href="{% url 'ag-getbillpdf' bill.pk %}" target="_blank">Rechnung vom {{bill.billdate|date:"d.m.Y"}} ({{bill.billnumber}})</a> - {% if bill.billstatus == "open" %} Offen {% elif bill.billstatus == "paid" %} Bezahlt {% endif %} <br />
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ from django.contrib.auth import views as auth_views
|
||||||
from django.contrib.auth.decorators import login_required, permission_required
|
from django.contrib.auth.decorators import login_required, permission_required
|
||||||
from . import views
|
from . import views
|
||||||
from .views import FreeDayDeleteView, AbsenceReasonDeleteView, AbsenceReasonUpdateView, AbsenceReasonAddView
|
from .views import FreeDayDeleteView, AbsenceReasonDeleteView, AbsenceReasonUpdateView, AbsenceReasonAddView
|
||||||
from .views import NewUserFirstStep, UserProfileUpdate, UserChangeMain, BillMailUpdate, BillPlanUpdate
|
from .views import NewUserFirstStep, UserProfileUpdate, UserChangeMain, BillMailUpdate, BillPlanUpdate, GetBill, GetBillPDF
|
||||||
'''
|
'''
|
||||||
Permissions definiert in models.py bei USERS und dann hier vor die View geschrieben!
|
Permissions definiert in models.py bei USERS und dann hier vor die View geschrieben!
|
||||||
'''
|
'''
|
||||||
|
|
@ -35,6 +35,7 @@ urlpatterns = [
|
||||||
path('abcatadd/', AbsenceReasonAddView.as_view(), name="abcat-add"),
|
path('abcatadd/', AbsenceReasonAddView.as_view(), name="abcat-add"),
|
||||||
path('ag/billmail/update/<int:pk>', permission_required('users.agencyinfo')(BillMailUpdate.as_view()), name='ag-billmailupdate'),
|
path('ag/billmail/update/<int:pk>', permission_required('users.agencyinfo')(BillMailUpdate.as_view()), name='ag-billmailupdate'),
|
||||||
path('ag/billplan/<int:pk>', permission_required('users.agencyinfo')(BillPlanUpdate.as_view()), name='ag-billplanupdate'),
|
path('ag/billplan/<int:pk>', permission_required('users.agencyinfo')(BillPlanUpdate.as_view()), name='ag-billplanupdate'),
|
||||||
#path('ag/getbill/<slug:billid>', permission_required('users.agencyinfo')(GetBill), name='ag-getbill'),
|
path('ag/getbill/<int:pk>', permission_required('users.agencyinfo')(GetBill), name='ag-getbill'),
|
||||||
|
path('ag/getbillpdf/<int:pk>', permission_required('users.agencyinfo')(GetBillPDF), name='ag-getbillpdf'),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
@ -259,15 +259,70 @@ def DASettings(request):
|
||||||
|
|
||||||
|
|
||||||
# Alle Rechnungen der Agentur abfragen
|
# Alle Rechnungen der Agentur abfragen
|
||||||
context.update({"bills" : AgencyBills.objects.filter(agency=request.user.profile.agency)})
|
context.update({"bills" : AgencyBills.objects.filter(agency=request.user.profile.agency).order_by("billdate")})
|
||||||
|
|
||||||
|
|
||||||
#r = requests.get("https://api.lexoffice.io/v1/invoices/" + AgencyBills.objects.filter(agency=request.user.profile.agency)[0].lexid, data=json_data, headers=headers)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return render(request, 'dasettings/settings.html', context)
|
return render(request, 'dasettings/settings.html', context)
|
||||||
|
|
||||||
|
from django.http import FileResponse, Http404
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def GetBill(request, pk):
|
||||||
|
# HEADERS CURL
|
||||||
|
headers = {
|
||||||
|
'Authorization': 'Bearer 8f9ba01f-9e84-42c7-9548-48c254f14c19',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Accept': 'application/json',
|
||||||
|
}
|
||||||
|
|
||||||
|
json_data = {}
|
||||||
|
|
||||||
|
r = requests.get("https://api.lexoffice.io/v1/invoices/"+AgencyBills.objects.get(pk=pk).lexid+"/document", data=json_data, headers=headers)
|
||||||
|
|
||||||
|
context = {
|
||||||
|
'active_link' : 'dasettings',
|
||||||
|
'bill' : AgencyBills.objects.get(pk=pk),
|
||||||
|
'fileid' : json.loads(r.text)["documentFileId"]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return render(request, 'dasettings/bill_single.html', context)
|
||||||
|
|
||||||
|
from fpdf import FPDF, HTMLMixin
|
||||||
|
class HtmlPdf(FPDF, HTMLMixin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
import io as BytesIO
|
||||||
|
import base64
|
||||||
|
from django.http import HttpResponse
|
||||||
|
@login_required
|
||||||
|
def GetBillPDF(request, pk):
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
'Authorization': 'Bearer 8f9ba01f-9e84-42c7-9548-48c254f14c19',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Accept': 'application/json',
|
||||||
|
}
|
||||||
|
|
||||||
|
lexdata = {
|
||||||
|
"renderType" : "pdf"
|
||||||
|
}
|
||||||
|
json_data = json.dumps(lexdata)
|
||||||
|
|
||||||
|
r = requests.get("https://api.lexoffice.io/v1/invoices/"+AgencyBills.objects.get(pk=pk).lexid+"/document", data=json_data, headers=headers)
|
||||||
|
json.loads(r.text)
|
||||||
|
|
||||||
|
base64String = requests.get("https://api.lexoffice.io/v1/files/"+json.loads(r.text)["documentFileId"]+"/", data=json_data, headers=headers)
|
||||||
|
|
||||||
|
buffer = BytesIO.BytesIO()
|
||||||
|
content = base64.b64decode(base64String.text)
|
||||||
|
buffer.write(content)
|
||||||
|
|
||||||
|
response = HttpResponse(buffer.getvalue(),content_type="application/pdf")
|
||||||
|
response['Content-Disposition'] = 'inline;filename=some_file.pdf'
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
AGENCY
|
AGENCY
|
||||||
|
|
@ -1532,9 +1587,12 @@ class BillPlanUpdate(UpdateView):
|
||||||
end_date = month + relativedelta(months=plan)
|
end_date = month + relativedelta(months=plan)
|
||||||
end_date_string= end_date.strftime("%d.%m.%Y")
|
end_date_string= end_date.strftime("%d.%m.%Y")
|
||||||
|
|
||||||
|
|
||||||
|
voucher_date_today = date.today().strftime("%Y-%m-%d")
|
||||||
# TODO: Nachgebuchte Mitarbeiter
|
# TODO: Nachgebuchte Mitarbeiter
|
||||||
# TODO: Was passiert bei Änderungen der Agenturdaten?
|
# TODO: Was passiert bei Änderungen der Agenturdaten?
|
||||||
# TODO: Kündigungsmöglichkeit, den Zahlplan zu beenden
|
# TODO: Kündigungsmöglichkeit, den Zahlplan zu beenden
|
||||||
|
# TODO: voucherDate muss HEUTE sein, Leistungszeitraum aber das von der Agenturregistrierung
|
||||||
# DataJSON
|
# DataJSON
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
@ -1545,9 +1603,8 @@ class BillPlanUpdate(UpdateView):
|
||||||
if form.cleaned_data['paymentplan'] == "1":
|
if form.cleaned_data['paymentplan'] == "1":
|
||||||
monthword = "Monat"
|
monthword = "Monat"
|
||||||
|
|
||||||
|
|
||||||
lexdata = {
|
lexdata = {
|
||||||
"voucherDate": voucher_date + "T00:00:00.000+00:00",
|
"voucherDate": voucher_date_today + "T00:00:00.000+00:00",
|
||||||
"address" : {
|
"address" : {
|
||||||
"name" : agency.name,
|
"name" : agency.name,
|
||||||
"street": agency.street,
|
"street": agency.street,
|
||||||
|
|
@ -1563,7 +1620,7 @@ class BillPlanUpdate(UpdateView):
|
||||||
"type" : "custom",
|
"type" : "custom",
|
||||||
"name" : "Digitale Agentur: Grundbetrag für " + str(plan) + " " + monthword,
|
"name" : "Digitale Agentur: Grundbetrag für " + str(plan) + " " + monthword,
|
||||||
"quantity" : 1,
|
"quantity" : 1,
|
||||||
"unitName" : "Anzahl",
|
"unitName" : "Stück",
|
||||||
"description" : "Zeitraum " + start_date_string + " - " + end_date_string,
|
"description" : "Zeitraum " + start_date_string + " - " + end_date_string,
|
||||||
"unitPrice" :
|
"unitPrice" :
|
||||||
{
|
{
|
||||||
|
|
@ -1577,7 +1634,7 @@ class BillPlanUpdate(UpdateView):
|
||||||
"name" : "Digitale Agentur: Zusätzliche Mitarbeiter",
|
"name" : "Digitale Agentur: Zusätzliche Mitarbeiter",
|
||||||
"description" : "Zeitraum " + start_date_string + " - " + end_date_string,
|
"description" : "Zeitraum " + start_date_string + " - " + end_date_string,
|
||||||
"quantity" : usercount,
|
"quantity" : usercount,
|
||||||
"unitName" : "Anzahl",
|
"unitName" : "Stück",
|
||||||
"unitPrice" :
|
"unitPrice" :
|
||||||
{
|
{
|
||||||
"currency" : "EUR",
|
"currency" : "EUR",
|
||||||
|
|
@ -1594,15 +1651,15 @@ class BillPlanUpdate(UpdateView):
|
||||||
"paymentTermDuration": 14,
|
"paymentTermDuration": 14,
|
||||||
},
|
},
|
||||||
"shippingConditions": {
|
"shippingConditions": {
|
||||||
"shippingDate": voucher_date + "T00:00:00.000+00:00",
|
#"shippingDate": voucher_date_today + "T00:00:00.000+00:00",
|
||||||
"shippingType": "service"
|
"shippingType": "none"
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
json_data = json.dumps(lexdata)
|
json_data = json.dumps(lexdata)
|
||||||
|
|
||||||
self.object = form.save(commit=False)
|
self.object = form.save(commit=False)
|
||||||
|
|
||||||
r = requests.post("https://api.lexoffice.io/v1/invoices", data=json_data, headers=headers)
|
r = requests.post("https://api.lexoffice.io/v1/invoices/?finalize=true", data=json_data, headers=headers)
|
||||||
|
|
||||||
if(r.status_code == 201):
|
if(r.status_code == 201):
|
||||||
messages.success(self.request, f"Rechnung erstellt!")
|
messages.success(self.request, f"Rechnung erstellt!")
|
||||||
|
|
@ -1628,11 +1685,8 @@ class BillPlanUpdate(UpdateView):
|
||||||
if len(agency.lexofficeid) == 0:
|
if len(agency.lexofficeid) == 0:
|
||||||
self.object.lexofficeid = response_text["organizationId"]
|
self.object.lexofficeid = response_text["organizationId"]
|
||||||
|
|
||||||
|
newbill = AgencyBills(agency=agency, lexid=newbill_id, billtype="invoice", billnumber=response_text["voucherNumber"], billstatus=response_text["voucherStatus"], start=start_date, end=end_date, plan=plan)
|
||||||
|
|
||||||
newbill = AgencyBills(agency=agency, lexid=newbill_id, billtype="invoice", billnumber=response_text["voucherNumber"])
|
|
||||||
newbill.save()
|
newbill.save()
|
||||||
|
|
||||||
self.object.save()
|
self.object.save()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,10 @@ class AgencyBills(models.Model):
|
||||||
billtype = models.CharField(default="", max_length=200)
|
billtype = models.CharField(default="", max_length=200)
|
||||||
billdate = models.DateField(default=timezone.now)
|
billdate = models.DateField(default=timezone.now)
|
||||||
billnumber = models.CharField(default="", max_length=200)
|
billnumber = models.CharField(default="", max_length=200)
|
||||||
# TODO: Rechnungsstatus dazu ob offen oder nicht
|
billstatus = models.CharField(default="", max_length=200, null=True, blank=True)
|
||||||
|
start = models.DateField(default=timezone.now)
|
||||||
|
end = models.DateField(default=timezone.now)
|
||||||
|
plan = models.CharField(default="", max_length=20)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f'{self.lexid}'
|
return f'{self.lexid}'
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue