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 %}
|
||||
|
||||
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.
|
||||
<br />
|
||||
<a href="{% url 'ag-billplanupdate' request.user.profile.agency.pk %}" class="btn btn-primary btn mt-2" onclick="">Zahlplan jetzt auswählen</a>
|
||||
{% 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>
|
||||
{% endif %}
|
||||
<hr>
|
||||
<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>.
|
||||
<!-- 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>
|
||||
|
|
@ -73,7 +75,7 @@
|
|||
<div class="card-body">
|
||||
<h5 class="card-title">Rechnungen</h5>
|
||||
{% 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 %}
|
||||
</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 . import views
|
||||
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!
|
||||
'''
|
||||
|
|
@ -35,6 +35,7 @@ urlpatterns = [
|
|||
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/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
|
||||
context.update({"bills" : AgencyBills.objects.filter(agency=request.user.profile.agency)})
|
||||
|
||||
|
||||
#r = requests.get("https://api.lexoffice.io/v1/invoices/" + AgencyBills.objects.filter(agency=request.user.profile.agency)[0].lexid, data=json_data, headers=headers)
|
||||
|
||||
context.update({"bills" : AgencyBills.objects.filter(agency=request.user.profile.agency).order_by("billdate")})
|
||||
|
||||
|
||||
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
|
||||
|
|
@ -1532,9 +1587,12 @@ class BillPlanUpdate(UpdateView):
|
|||
end_date = month + relativedelta(months=plan)
|
||||
end_date_string= end_date.strftime("%d.%m.%Y")
|
||||
|
||||
|
||||
voucher_date_today = date.today().strftime("%Y-%m-%d")
|
||||
# TODO: Nachgebuchte Mitarbeiter
|
||||
# TODO: Was passiert bei Änderungen der Agenturdaten?
|
||||
# TODO: Kündigungsmöglichkeit, den Zahlplan zu beenden
|
||||
# TODO: voucherDate muss HEUTE sein, Leistungszeitraum aber das von der Agenturregistrierung
|
||||
# DataJSON
|
||||
'''
|
||||
|
||||
|
|
@ -1545,9 +1603,8 @@ class BillPlanUpdate(UpdateView):
|
|||
if form.cleaned_data['paymentplan'] == "1":
|
||||
monthword = "Monat"
|
||||
|
||||
|
||||
lexdata = {
|
||||
"voucherDate": voucher_date + "T00:00:00.000+00:00",
|
||||
"voucherDate": voucher_date_today + "T00:00:00.000+00:00",
|
||||
"address" : {
|
||||
"name" : agency.name,
|
||||
"street": agency.street,
|
||||
|
|
@ -1563,7 +1620,7 @@ class BillPlanUpdate(UpdateView):
|
|||
"type" : "custom",
|
||||
"name" : "Digitale Agentur: Grundbetrag für " + str(plan) + " " + monthword,
|
||||
"quantity" : 1,
|
||||
"unitName" : "Anzahl",
|
||||
"unitName" : "Stück",
|
||||
"description" : "Zeitraum " + start_date_string + " - " + end_date_string,
|
||||
"unitPrice" :
|
||||
{
|
||||
|
|
@ -1577,7 +1634,7 @@ class BillPlanUpdate(UpdateView):
|
|||
"name" : "Digitale Agentur: Zusätzliche Mitarbeiter",
|
||||
"description" : "Zeitraum " + start_date_string + " - " + end_date_string,
|
||||
"quantity" : usercount,
|
||||
"unitName" : "Anzahl",
|
||||
"unitName" : "Stück",
|
||||
"unitPrice" :
|
||||
{
|
||||
"currency" : "EUR",
|
||||
|
|
@ -1594,16 +1651,16 @@ class BillPlanUpdate(UpdateView):
|
|||
"paymentTermDuration": 14,
|
||||
},
|
||||
"shippingConditions": {
|
||||
"shippingDate": voucher_date + "T00:00:00.000+00:00",
|
||||
"shippingType": "service"
|
||||
},
|
||||
#"shippingDate": voucher_date_today + "T00:00:00.000+00:00",
|
||||
"shippingType": "none"
|
||||
}
|
||||
}
|
||||
json_data = json.dumps(lexdata)
|
||||
|
||||
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):
|
||||
messages.success(self.request, f"Rechnung erstellt!")
|
||||
# Response in JSON umwandeln
|
||||
|
|
@ -1627,12 +1684,9 @@ class BillPlanUpdate(UpdateView):
|
|||
response_text = json.loads(r.text)
|
||||
if len(agency.lexofficeid) == 0:
|
||||
self.object.lexofficeid = response_text["organizationId"]
|
||||
|
||||
|
||||
|
||||
newbill = AgencyBills(agency=agency, lexid=newbill_id, billtype="invoice", billnumber=response_text["voucherNumber"])
|
||||
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.save()
|
||||
|
||||
self.object.save()
|
||||
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -153,8 +153,11 @@ class AgencyBills(models.Model):
|
|||
billtype = models.CharField(default="", max_length=200)
|
||||
billdate = models.DateField(default=timezone.now)
|
||||
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):
|
||||
return f'{self.lexid}'
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue