Show invoice address form once again before generating a new invoice

This commit is contained in:
Raphael Michel
2019-12-06 20:03:22 +01:00
parent 12b9d23efb
commit a74bde60eb
4 changed files with 59 additions and 33 deletions

View File

@@ -2053,6 +2053,13 @@ class InvoiceAddress(models.Model):
self.name_parts = {}
super().save(**kwargs)
@property
def is_empty(self):
return (
not self.name_cached and not self.company and not self.street and not self.zipcode and not self.city
and not self.internal_reference and not self.beneficiary
)
@property
def state_name(self):
sd = pycountry.subdivisions.get(code='{}-{}'.format(self.country, self.state))

View File

@@ -186,6 +186,11 @@
<div class="alert alert-info">
{% trans "You need to select a payment method above before you can request an invoice." %}
</div>
{% elif invoice_address_asked and order.invoice_address.is_empty %}
<a href="{% eventurl event "presale:event.order.modify" secret=order.secret order=order.code %}?generate_invoice=true"
class="btn btn-default">
{% trans "Request invoice" %}
</a>
{% else %}
<form class="form-inline helper-display-inline" method="post"
action="{% eventurl event "presale:event.order.geninvoice" order=order.code secret=order.secret %}">

View File

@@ -13,7 +13,7 @@
{% csrf_token %}
<div class="panel-group" id="questions_accordion">
{% if invoice_address_asked or event.settings.invoice_name_required %}
{% if invoice_address_asked %}
{% if invoice_address_asked and not request.GET.generate_invoice == "true" %}
<div class="alert alert-info">
{% blocktrans trimmed %}
Modifying your invoice address will not automatically generate a new invoice.
@@ -81,7 +81,11 @@
</div>
<div class="col-md-4 col-md-offset-4">
<button class="btn btn-block btn-primary btn-lg" type="submit">
{% trans "Save changes" %}
{% if request.GET.generate_invoice == "true" %}
{% trans "Request invoice" %}
{% else %}
{% trans "Save changes" %}
{% endif %}
</button>
</div>
<div class="clearfix"></div>

View File

@@ -176,17 +176,7 @@ class OrderDetails(EventViewMixin, OrderDetailMixin, CartMixin, TicketPageMixin,
[p.generate_ticket for p in ctx['cart']['positions']].count(True) > 1
)
ctx['invoices'] = list(self.order.invoices.all())
can_generate_invoice = (
self.order.sales_channel in self.request.event.settings.get('invoice_generate_sales_channels')
and (
self.request.event.settings.get('invoice_generate') in ('user', 'True')
or (
self.request.event.settings.get('invoice_generate') == 'paid'
and self.order.status == Order.STATUS_PAID
)
)
)
ctx['can_generate_invoice'] = invoice_qualified(self.order) and can_generate_invoice
ctx['can_generate_invoice'] = can_generate_invoice(self.request.event, self.order, True)
if ctx['can_generate_invoice']:
if not self.order.payments.exclude(
state__in=[OrderPayment.PAYMENT_STATE_CANCELED, OrderPayment.PAYMENT_STATE_FAILED]
@@ -590,6 +580,28 @@ class OrderPayChangeMethod(EventViewMixin, OrderDetailMixin, TemplateView):
})
def can_generate_invoice(event, order, ignore_payments=False):
v = (
order.sales_channel in event.settings.get('invoice_generate_sales_channels')
and (
event.settings.get('invoice_generate') in ('user', 'True')
or (
event.settings.get('invoice_generate') == 'paid'
and order.status == Order.STATUS_PAID
)
) and (
invoice_qualified(order)
)
)
if not ignore_payments:
v = v and not (
not order.payments.exclude(
state__in=[OrderPayment.PAYMENT_STATE_CANCELED, OrderPayment.PAYMENT_STATE_FAILED]
).exists() and order.status == Order.STATUS_PENDING
)
return v
@method_decorator(xframe_options_exempt, 'dispatch')
class OrderInvoiceCreate(EventViewMixin, OrderDetailMixin, View):
@@ -600,21 +612,7 @@ class OrderInvoiceCreate(EventViewMixin, OrderDetailMixin, View):
return super().dispatch(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
can_generate_invoice = (
self.order.sales_channel in self.request.event.settings.get('invoice_generate_sales_channels')
and (
self.request.event.settings.get('invoice_generate') in ('user', 'True')
or (
self.request.event.settings.get('invoice_generate') == 'paid'
and self.order.status == Order.STATUS_PAID
)
) and not (
not self.order.payments.exclude(
state__in=[OrderPayment.PAYMENT_STATE_CANCELED, OrderPayment.PAYMENT_STATE_FAILED]
).exists() and self.order.status == Order.STATUS_PENDING
)
)
if not can_generate_invoice or not invoice_qualified(self.order):
if not can_generate_invoice(self.request.event, self.order):
messages.error(self.request, _('You cannot generate an invoice for this order.'))
elif self.order.invoices.exists():
messages.error(self.request, _('An invoice for this order already exists.'))
@@ -633,6 +631,12 @@ class OrderModify(EventViewMixin, OrderDetailMixin, OrderQuestionsViewMixin, Tem
invoice_form_class = InvoiceAddressForm
template_name = "pretixpresale/event/order_modify.html"
@cached_property
def positions(self):
if self.request.GET.get('generate_invoice') == 'true':
return []
return super().positions
def post(self, request, *args, **kwargs):
failed = not self.save() or not self.invoice_form.is_valid()
if failed:
@@ -651,11 +655,17 @@ class OrderModify(EventViewMixin, OrderDetailMixin, OrderQuestionsViewMixin, Tem
} for f in self.forms]
})
order_modified.send(sender=self.request.event, order=self.order)
if self.invoice_form.has_changed():
messages.success(self.request, _('Your invoice address has been updated. Please contact us if you need us '
'to regenerate your invoice.'))
else:
messages.success(self.request, _('Your changes have been saved.'))
if request.GET.get('generate_invoice') == 'true':
if not can_generate_invoice(self.request.event, self.order):
messages.error(self.request, _('You cannot generate an invoice for this order.'))
elif self.order.invoices.exists():
messages.error(self.request, _('An invoice for this order already exists.'))
else:
i = generate_invoice(self.order)
self.order.log_action('pretix.event.order.invoice.generated', data={
'invoice': i.pk
})
messages.success(self.request, _('The invoice has been generated.'))
invalidate_cache.apply_async(kwargs={'event': self.request.event.pk, 'order': self.order.pk})
CachedTicket.objects.filter(order_position__order=self.order).delete()