Payment flow
This commit is contained in:
parent
5c8c570589
commit
e85074dc9f
14 changed files with 162 additions and 38 deletions
|
@ -16,4 +16,4 @@ class InquiryProcessForm(forms.ModelForm):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Inquiry
|
model = Inquiry
|
||||||
fields = ["destination_radius", "arrival", "min_nights", "budget", "adults", "children", "comment"]
|
fields = ["gateway"]
|
|
@ -4,12 +4,14 @@ from django.contrib import messages
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.contrib.gis.geos import Point
|
from django.contrib.gis.geos import Point
|
||||||
from django.contrib.gis.db.models.functions import Distance
|
from django.contrib.gis.db.models.functions import Distance
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
from public.mixins import InConstructionMixin
|
from public.mixins import InConstructionMixin
|
||||||
from partners.mixins import PartnerProfileRequiredMixin
|
from partners.mixins import PartnerProfileRequiredMixin
|
||||||
from localauth.helpers import name_to_coords
|
from localauth.helpers import name_to_coords
|
||||||
from partners.models import Establishment
|
from partners.models import Establishment
|
||||||
from payment.models import BillingAddress, Invoice, InvoiceItem, InvoicePayment
|
from payment.models import BillingAddress, Invoice, InvoiceItem, InvoicePayment
|
||||||
|
from clients.models import ClientProfile
|
||||||
|
|
||||||
from .models import Inquiry, Offer
|
from .models import Inquiry, Offer
|
||||||
from .forms import InquiryProcessForm
|
from .forms import InquiryProcessForm
|
||||||
|
@ -59,7 +61,7 @@ class InquiryProcessView(InConstructionMixin, UpdateView):
|
||||||
return initial
|
return initial
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
profile = self.request.user.clientprofile
|
profile, _ = ClientProfile.objects.get_or_create(user=self.request.user)
|
||||||
profile.first_name = form.cleaned_data["first_name"]
|
profile.first_name = form.cleaned_data["first_name"]
|
||||||
profile.last_name = form.cleaned_data["last_name"]
|
profile.last_name = form.cleaned_data["last_name"]
|
||||||
profile.street = form.cleaned_data["street"]
|
profile.street = form.cleaned_data["street"]
|
||||||
|
@ -69,12 +71,30 @@ class InquiryProcessView(InConstructionMixin, UpdateView):
|
||||||
profile.country = form.cleaned_data["country"]
|
profile.country = form.cleaned_data["country"]
|
||||||
profile.save()
|
profile.save()
|
||||||
|
|
||||||
|
form.instance.client = profile
|
||||||
|
|
||||||
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
def form_invalid(self, form, *args, **kwargs):
|
||||||
|
for field in form:
|
||||||
|
for error in field.errors:
|
||||||
|
messages.error(self.request, f"{field.name}: {error}")
|
||||||
|
|
||||||
|
return redirect("/")
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
return reverse("auction:inquiry_payment", args=(self.object.uuid,))
|
return reverse("auction:inquiry_payment", args=(self.object.uuid,))
|
||||||
|
|
||||||
class InquiryPaymentView(InConstructionMixin, View):
|
class InquiryPaymentView(InConstructionMixin, View):
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
inquiry = Inquiry.objects.get(uuid=kwargs["uuid"])
|
inquiry = Inquiry.objects.get(uuid=kwargs["uuid"])
|
||||||
|
try:
|
||||||
|
invoice = inquiry.invoice
|
||||||
|
except Invoice.DoesNotExist:
|
||||||
|
invoice = Invoice.from_inquiry(inquiry)
|
||||||
|
payment_url = InvoicePayment.from_invoice(invoice, inquiry.gateway)
|
||||||
|
|
||||||
|
return redirect(payment_url)
|
||||||
|
|
||||||
class OfferSelectionView(InConstructionMixin, DetailView):
|
class OfferSelectionView(InConstructionMixin, DetailView):
|
||||||
model = Inquiry
|
model = Inquiry
|
||||||
|
|
|
@ -100,12 +100,17 @@ class PhoneMixin(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
class Profile(AddressMixin, PhoneMixin):
|
class PersonMixin(models.Model):
|
||||||
user = models.OneToOneField(User, models.CASCADE)
|
|
||||||
company = models.CharField("Firma", max_length=64, null=True, blank=True)
|
company = models.CharField("Firma", max_length=64, null=True, blank=True)
|
||||||
vat_id = models.CharField("UID-Nummer", max_length=32, null=True, blank=True)
|
vat_id = models.CharField("UID-Nummer", max_length=32, null=True, blank=True)
|
||||||
first_name = models.CharField("Vorname", max_length=64)
|
first_name = models.CharField("Vorname", max_length=64)
|
||||||
last_name = models.CharField("Nachname", max_length=64)
|
last_name = models.CharField("Nachname", max_length=64)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
|
||||||
|
class Profile(PersonMixin, AddressMixin, PhoneMixin):
|
||||||
|
user = models.OneToOneField(User, models.CASCADE)
|
||||||
verified = models.BooleanField(default=False)
|
verified = models.BooleanField(default=False)
|
||||||
enabled = models.BooleanField(default=True)
|
enabled = models.BooleanField(default=True)
|
||||||
|
|
||||||
|
|
|
@ -28,4 +28,10 @@ AWS_STORAGE_BUCKET_NAME = "AWS Bucket"
|
||||||
|
|
||||||
# Countries the app can be used in (currently no more than 5 due to Google Maps restrictions)
|
# Countries the app can be used in (currently no more than 5 due to Google Maps restrictions)
|
||||||
|
|
||||||
JOKER_COUNTRIES = ["AT"]
|
JOKER_COUNTRIES = ["AT"]
|
||||||
|
|
||||||
|
# Currency to use
|
||||||
|
|
||||||
|
CURRENCY_SYMBOL = "€"
|
||||||
|
CURRENCY_CODE = "EUR"
|
||||||
|
CURRENCY_NAME = "Euro"
|
|
@ -1,15 +1,30 @@
|
||||||
from payment.models import InvoicePayment, Invoice
|
from payment.models import InvoicePayment, Invoice
|
||||||
|
from payment.signals import initiate_payment
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
|
from django.dispatch import receiver
|
||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
class DemoInvoicePayment(InvoicePayment):
|
class DemoInvoicePayment(InvoicePayment):
|
||||||
@property
|
@property
|
||||||
def gateway(self):
|
def gateway(self):
|
||||||
return "Paypal"
|
return "Demo"
|
||||||
|
|
||||||
@staticmethod
|
@classmethod
|
||||||
def initiate(invoice):
|
def initiate(cls, invoice):
|
||||||
self.objects.create(invoice=invoice, amount=invoice.amount, gateway_id=uuid.uuid4())
|
payment = cls.objects.create(invoice=invoice, amount=invoice.balance * -1, gateway_id=uuid.uuid4())
|
||||||
|
invoice.generate_invoice()
|
||||||
|
return reverse_lazy("payment:status", args=[payment.uuid])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def status(self):
|
||||||
|
return 0
|
||||||
|
|
||||||
|
@receiver(initiate_payment)
|
||||||
|
def from_signal(sender, **kwargs):
|
||||||
|
if kwargs["gateway"] == "demo":
|
||||||
|
return {"redirect": DemoInvoicePayment.initiate(kwargs["invoice"])}
|
||||||
|
else:
|
||||||
|
return {}
|
|
@ -2,6 +2,7 @@ from django.db import models
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.core.files.base import ContentFile
|
from django.core.files.base import ContentFile
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
|
|
||||||
|
@ -13,27 +14,38 @@ from django_countries.fields import CountryField
|
||||||
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
|
||||||
import urllib.request
|
import urllib.request
|
||||||
|
|
||||||
from dbsettings.functions import getValue
|
from dbsettings.functions import getValue
|
||||||
|
|
||||||
from .functions import invoice_upload_path
|
from .functions import invoice_upload_path
|
||||||
|
from .signals import initiate_payment
|
||||||
|
|
||||||
from auction.models import Inquiry
|
from auction.models import Inquiry
|
||||||
|
from localauth.models import PersonMixin, AddressMixin
|
||||||
|
|
||||||
class BillingAddress(models.Model):
|
class BillingAddress(PersonMixin, AddressMixin):
|
||||||
user = models.ForeignKey(get_user_model(), models.CASCADE)
|
user = models.ForeignKey(get_user_model(), models.CASCADE)
|
||||||
company = models.CharField(max_length=64, null=True, blank=True)
|
|
||||||
vat_id = models.CharField(max_length=32, null=True, blank=True)
|
@classmethod
|
||||||
first_name = models.CharField(max_length=64)
|
def from_profile(cls, profile):
|
||||||
last_name = models.CharField(max_length=64)
|
return cls.objects.create(
|
||||||
street = models.CharField(max_length=128)
|
company = profile.company,
|
||||||
city = models.CharField(max_length=64)
|
vat_id = profile.vat_id,
|
||||||
zip = models.CharField(max_length=16)
|
first_name = profile.first_name,
|
||||||
state = models.CharField(max_length=32, null=True, blank=True)
|
last_name = profile.last_name,
|
||||||
country = CountryField()
|
street = profile.street,
|
||||||
|
city = profile.city,
|
||||||
|
zip = profile.zip,
|
||||||
|
state = profile.state,
|
||||||
|
country = profile.country,
|
||||||
|
user = profile.user
|
||||||
|
)
|
||||||
|
|
||||||
class Invoice(models.Model):
|
class Invoice(models.Model):
|
||||||
|
uuid = models.UUIDField(default=uuid.uuid4)
|
||||||
user = models.ForeignKey(get_user_model(), models.PROTECT)
|
user = models.ForeignKey(get_user_model(), models.PROTECT)
|
||||||
billing_address = models.ForeignKey(BillingAddress, models.PROTECT)
|
billing_address = models.ForeignKey(BillingAddress, models.PROTECT)
|
||||||
currency = models.CharField(max_length=3)
|
currency = models.CharField(max_length=3)
|
||||||
|
@ -45,7 +57,7 @@ class Invoice(models.Model):
|
||||||
def price_net(self):
|
def price_net(self):
|
||||||
price = 0
|
price = 0
|
||||||
|
|
||||||
for item in self.invoiceitem_set().all():
|
for item in self.invoiceitem_set.all():
|
||||||
price += item.net_total
|
price += item.net_total
|
||||||
|
|
||||||
return price
|
return price
|
||||||
|
@ -67,16 +79,18 @@ class Invoice(models.Model):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_paid(self):
|
def balance(self):
|
||||||
paid_amount = 0
|
paid_amount = 0
|
||||||
|
|
||||||
for payment in self.invoicepayment_set().all():
|
for payment in self.invoicepayment_set.all():
|
||||||
paid_amount += payment.amount
|
paid_amount += payment.amount
|
||||||
|
|
||||||
if paid_amount >= price_gross:
|
return paid_amount - self.price_gross
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_paid(self):
|
||||||
|
return self.balance >= 0
|
||||||
|
|
||||||
def generate_invoice(self):
|
def generate_invoice(self):
|
||||||
output = BytesIO()
|
output = BytesIO()
|
||||||
|
|
||||||
|
@ -116,21 +130,21 @@ class Invoice(models.Model):
|
||||||
"state": profile.state,
|
"state": profile.state,
|
||||||
"country": profile.country,
|
"country": profile.country,
|
||||||
"post_code": profile.zip,
|
"post_code": profile.zip,
|
||||||
"vat_tax_number": profile.vat_id,
|
|
||||||
"email": self.user.email,
|
"email": self.user.email,
|
||||||
}.items() if value}
|
}.items() if value}
|
||||||
|
|
||||||
doc.client_info = ClientInfo(**client_data)
|
doc.client_info = ClientInfo(**client_data)
|
||||||
|
|
||||||
for item in self.invoiceitem_set().all():
|
for item in self.invoiceitem_set.all():
|
||||||
doc.add_item(Item(item.name, item.description, item.count, item.net_each))
|
doc.add_item(Item(item.name, item.description, item.count, item.net_each))
|
||||||
|
|
||||||
doc.set_item_tax_rate(self.tax_rate)
|
doc.set_item_tax_rate(self.tax_rate)
|
||||||
|
|
||||||
for payment in self.invoicepayment_set().all():
|
for payment in self.invoicepayment_set.all():
|
||||||
doc.add_transaction(Transaction(payment.gateway, payment.gateway_id, payment.timestamp, payment.amount))
|
doc.add_transaction(Transaction(payment.gateway, payment.gateway_id, payment.timestamp, payment.amount))
|
||||||
|
|
||||||
bottom_tip = (f"{ self.payment_instructions }<br /><br />" if self.payment_instructions else "") + getValue("billing.bottom_tip", "")
|
bottom_tip = ("Kunden-UID: %s<br /><br />" % profile.vat_id) if profile.vat_id else ""
|
||||||
|
bottom_tip += (f"{ self.payment_instructions }<br /><br />" if self.payment_instructions else "") + getValue("billing.bottom_tip", "")
|
||||||
bottom_tip += "<br /><br />" if bottom_tip else ""
|
bottom_tip += "<br /><br />" if bottom_tip else ""
|
||||||
bottom_tip += "Rechnung erstellt: %s" % str(timezone.now())
|
bottom_tip += "Rechnung erstellt: %s" % str(timezone.now())
|
||||||
|
|
||||||
|
@ -141,6 +155,26 @@ class Invoice(models.Model):
|
||||||
self.invoice = ContentFile(output.getvalue(), "invoice.pdf")
|
self.invoice = ContentFile(output.getvalue(), "invoice.pdf")
|
||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_inquiry(cls, inquiry):
|
||||||
|
invoice = cls.objects.create(
|
||||||
|
user = inquiry.client.user,
|
||||||
|
billing_address = BillingAddress.from_profile(inquiry.client),
|
||||||
|
currency = settings.CURRENCY_CODE,
|
||||||
|
tax_rate = 0,
|
||||||
|
inquiry = inquiry
|
||||||
|
)
|
||||||
|
|
||||||
|
InvoiceItem.objects.create(
|
||||||
|
invoice = invoice,
|
||||||
|
name = "Sicherheitsleistung",
|
||||||
|
description = "Rückzahlbare Sicherheitsleistung zu JourneyJoker-Anfrage #%i" % inquiry.id,
|
||||||
|
count = 1,
|
||||||
|
net_each = inquiry.budget
|
||||||
|
)
|
||||||
|
|
||||||
|
return invoice
|
||||||
|
|
||||||
class InvoiceItem(models.Model):
|
class InvoiceItem(models.Model):
|
||||||
invoice = models.ForeignKey(Invoice, models.CASCADE)
|
invoice = models.ForeignKey(Invoice, models.CASCADE)
|
||||||
name = models.CharField(max_length=64)
|
name = models.CharField(max_length=64)
|
||||||
|
@ -148,7 +182,12 @@ class InvoiceItem(models.Model):
|
||||||
count = models.IntegerField()
|
count = models.IntegerField()
|
||||||
net_each = models.DecimalField(max_digits=11, decimal_places=2)
|
net_each = models.DecimalField(max_digits=11, decimal_places=2)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def net_total(self):
|
||||||
|
return self.net_each * self.count
|
||||||
|
|
||||||
class InvoicePayment(PolymorphicModel):
|
class InvoicePayment(PolymorphicModel):
|
||||||
|
uuid = models.UUIDField(default=uuid.uuid4)
|
||||||
invoice = models.ForeignKey(Invoice, models.PROTECT)
|
invoice = models.ForeignKey(Invoice, models.PROTECT)
|
||||||
amount = models.DecimalField(max_digits=9, decimal_places=2)
|
amount = models.DecimalField(max_digits=9, decimal_places=2)
|
||||||
gateway_id = models.CharField(max_length=256)
|
gateway_id = models.CharField(max_length=256)
|
||||||
|
@ -158,6 +197,23 @@ class InvoicePayment(PolymorphicModel):
|
||||||
def gateway(self):
|
def gateway(self):
|
||||||
raise NotImplementedError("%s does not implement gateway" % type(self))
|
raise NotImplementedError("%s does not implement gateway" % type(self))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def status(self):
|
||||||
|
raise NotImplementedError("%s does not implement status" % type(self))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def initiate(cls, invoice):
|
def initiate(cls, invoice):
|
||||||
raise NotImplementedError("%s does not implement initiate()" % cls.__name__)
|
raise NotImplementedError("%s does not implement initiate()" % cls.__name__)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_invoice(cls, invoice, gateway):
|
||||||
|
if invoice.balance < 0:
|
||||||
|
responses = initiate_payment.send_robust(sender=cls, invoice=invoice, gateway=gateway)
|
||||||
|
|
||||||
|
for handler, response in responses:
|
||||||
|
try:
|
||||||
|
return response["redirect"]
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
|
||||||
|
return False
|
3
payment/signals.py
Normal file
3
payment/signals.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import django.dispatch
|
||||||
|
|
||||||
|
initiate_payment = django.dispatch.Signal()
|
|
@ -1,8 +1,11 @@
|
||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
|
|
||||||
|
from .views import PaymentStatusView
|
||||||
|
|
||||||
app_name = "payment"
|
app_name = "payment"
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('gateways/paypal/', include("payment.paypal.urls"), name="paypal"),
|
path('gateways/paypal/', include("payment.paypal.urls"), name="paypal"),
|
||||||
path('gateways/sepa/', include("payment.sepa.urls"), name="sepa"),
|
path('gateways/sepa/', include("payment.sepa.urls"), name="sepa"),
|
||||||
|
path('status/<slug:uuid>/', PaymentStatusView.as_view(), name="status"),
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
from django.views.generic import DetailView
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
|
|
||||||
|
from .models import InvoicePayment
|
||||||
|
|
||||||
|
class PaymentStatusView(DetailView):
|
||||||
|
model = InvoicePayment
|
||||||
|
template_name = "payment/status.html"
|
||||||
|
|
||||||
|
def get_object(self):
|
||||||
|
return get_object_or_404(InvoicePayment, uuid=self.kwargs["uuid"])
|
|
@ -1,3 +1,3 @@
|
||||||
function setPaymentMethod() {
|
function setPaymentMethod() {
|
||||||
$('#id_payment').val($(".nav-link.active")[0].href.split("#tab-")[1])
|
$('#id_gateway').val($(".nav-link.active")[0].href.split("#tab-")[1])
|
||||||
}
|
}
|
1
static/frontend/js/language.js
Normal file
1
static/frontend/js/language.js
Normal file
|
@ -0,0 +1 @@
|
||||||
|
var language="DE";
|
|
@ -90,7 +90,7 @@
|
||||||
|
|
||||||
|
|
||||||
<div class="col-12 col-md-12 col-lg-7 col-xl-8 content-side">
|
<div class="col-12 col-md-12 col-lg-7 col-xl-8 content-side">
|
||||||
<form class="lg-booking-form" id="frm_booking" name="frm_booking" method="post" action="{% url "auction:inquiry_payment" object.uuid %}">
|
<form class="lg-booking-form" id="frm_booking" name="frm_booking" method="post" %}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{% if not request.user.is_authenticated %}
|
{% if not request.user.is_authenticated %}
|
||||||
<div class="lg-booking-form-heading">
|
<div class="lg-booking-form-heading">
|
||||||
|
@ -295,7 +295,7 @@
|
||||||
<label><input type="checkbox" {% if request.user.is_authenticated %}required{% else %}disabled{% endif %} id="id_terms" name="terms"> {% trans "Ich erkläre mich einverstanden mit den" %} <a href="#">{% trans "Allgemeinen Geschäftsbedingungen" %}</a> {% trans "und der" %} <a href="#">{% trans "Datenschutzerklärung" %}</a>.</label>
|
<label><input type="checkbox" {% if request.user.is_authenticated %}required{% else %}disabled{% endif %} id="id_terms" name="terms"> {% trans "Ich erkläre mich einverstanden mit den" %} <a href="#">{% trans "Allgemeinen Geschäftsbedingungen" %}</a> {% trans "und der" %} <a href="#">{% trans "Datenschutzerklärung" %}</a>.</label>
|
||||||
</div><!-- end checkbox -->
|
</div><!-- end checkbox -->
|
||||||
<div class="col-md-12 text-center" id="result_msg"></div>
|
<div class="col-md-12 text-center" id="result_msg"></div>
|
||||||
<input type="hidden" id="id_payment" name="payment">
|
<input type="hidden" id="id_gateway" name="gateway">
|
||||||
<button type="submit" onclick="setPaymentMethod(); return true;" class="btn btn-orange" name="submit" id="submit">{% trans "Zahlung durchführen" %}</button>
|
<button type="submit" onclick="setPaymentMethod(); return true;" class="btn btn-orange" name="submit" id="submit">{% trans "Zahlung durchführen" %}</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
|
@ -340,7 +340,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Page Scripts Starts -->
|
<!-- Page Scripts Starts -->
|
||||||
<script>var language="{{ request.LANGUAGE_CODE }}";</script>
|
<script src="{% static "frontend/js/language.js" %}"></script>
|
||||||
<script src="{% static "vendor/js/jquery-3.3.1.min.js" %}"></script>
|
<script src="{% static "vendor/js/jquery-3.3.1.min.js" %}"></script>
|
||||||
<script src="{% static "vendor/js/jquery.magnific-popup.min.js" %}"></script>
|
<script src="{% static "vendor/js/jquery.magnific-popup.min.js" %}"></script>
|
||||||
<script src="{% static "vendor/js/jquery.mCustomScrollbar.concat.min.js" %}"></script>
|
<script src="{% static "vendor/js/jquery.mCustomScrollbar.concat.min.js" %}"></script>
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
<div class="col-md-12 col-lg-8 col-lg-offset-2">
|
<div class="col-md-12 col-lg-8 col-lg-offset-2">
|
||||||
<div class="payment-success-text">
|
<div class="payment-success-text">
|
||||||
<h2>{% trans "Zahlung" %} {% if object.status == 0 %}{% trans "erfolgreich" %}{% elif object.status == -1 %}{% trans "autorisiert" %}{% endif %}</h2>
|
<h2>{% trans "Zahlung" %} {% if object.status == 0 %}{% trans "erfolgreich" %}{% elif object.status == -1 %}{% trans "autorisiert" %}{% endif %}</h2>
|
||||||
<p>{% blocktrans with currency=object.invoice.currency|upper amount=object.invoice.amount %}Die Zahlung über {{ currency }} {{ amount }} wurde{% endblocktrans %} {% if object.status == 0 %}{% trans "erfolgreich durchgeführt" %}{% elif object.status == -1 %}{% trans "autorisiert" %}{% endif %}</p>
|
<p>{% blocktrans with currency=object.invoice.currency|upper amount=object.amount %}Die Zahlung über {{ currency }} {{ amount }} wurde{% endblocktrans %} {% if object.status == 0 %}{% trans "erfolgreich durchgeführt" %}{% elif object.status == -1 %}{% trans "autorisiert" %}{% endif %}</p>
|
||||||
|
|
||||||
<span><i class="fa fa-check-circle"></i></span>
|
<span><i class="fa fa-check-circle"></i></span>
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
|
@ -22,16 +22,20 @@
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
{% for line in object.invoice.invoiceitem_set.all %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><span><i class="fa fa-building"></i></span>{% trans "Gebot" %}</td>
|
<td><span><i class="fa fa-building"></i></span>{% if object.invoice.inquiry %}{% trans "Gebot" %}{% else %}{% trans "Gebühren" %}{% endif %}</td>
|
||||||
<td>{{ object.invoice.destination_name }}<span class="t-date">{{ object.first_date|date:"SHORT_DATE_FORMAT" }} – {{ object.last_date|date:"SHORT_DATE_FORMAT" }}</span></td>
|
<td>{{ line.description }}</td>
|
||||||
<td>{{ object.invoice.currency|upper }} {{ object.invoice.amount }}</td>
|
<td>{{ object.invoice.currency|upper }} {{ line.net_total }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
<a href="{% url "auction:offer_selection" object.invoice.inquiry.uuid %}" class="btn btn-orange">Angebote erhalten!</a><br /><br />
|
||||||
|
<a href="{{ object.invoice.invoice.url }}" class="btn">PDF-Beleg herunterladen</a>
|
||||||
{% if object.status == -1 %}
|
{% if object.status == -1 %}
|
||||||
<p>{% trans "Die Zahlung wurde autorisiert." %} <a href="/">{% trans "Was bedeutet das?" %}</a></p>
|
<p>{% trans "Die Zahlung wurde autorisiert." %} <a href="#">{% trans "Was bedeutet das?" %}</a></p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<p>{% trans "Die Zahlungsdaten wurden auch per E-Mail versendet." %}</p>
|
<p>{% trans "Die Zahlungsdaten wurden auch per E-Mail versendet." %}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue