mirror of
https://github.com/pretix/pretix.git
synced 2025-12-05 21:32:28 +00:00
Compare commits
1 Commits
fix-5455
...
invoice-to
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f243ad2a58 |
@@ -61,6 +61,7 @@ invoice_address object Invoice address
|
||||
AU, BR, CA, CN, MY, MX, and US.
|
||||
├ internal_reference string Customer's internal reference to be printed on the invoice
|
||||
├ custom_field string Custom invoice address field
|
||||
├ invoice_email string Email address that should receive all invoices
|
||||
├ vat_id string Customer VAT ID
|
||||
└ vat_id_validated string ``true``, if the VAT ID has been validated against the
|
||||
EU VAT service and validation was successful. This only
|
||||
@@ -342,6 +343,7 @@ List of all orders
|
||||
"country": "DE",
|
||||
"state": "",
|
||||
"internal_reference": "",
|
||||
"invoice_email": null,
|
||||
"vat_id": "EU123456789",
|
||||
"vat_id_validated": false
|
||||
},
|
||||
@@ -518,6 +520,7 @@ Fetching individual orders
|
||||
"country": "DE",
|
||||
"state": "",
|
||||
"internal_reference": "",
|
||||
"invoice_email": null,
|
||||
"vat_id": "EU123456789",
|
||||
"vat_id_validated": false
|
||||
},
|
||||
@@ -895,6 +898,7 @@ Creating orders
|
||||
* ``country``
|
||||
* ``state``
|
||||
* ``internal_reference``
|
||||
* ``invoice_email``
|
||||
* ``vat_id``
|
||||
* ``vat_id_validated`` (optional) – If you need support for reverse charge (rarely the case), you need to check
|
||||
yourself if the passed VAT ID is a valid EU VAT ID. In that case, set this to ``true``. Only valid VAT IDs will
|
||||
@@ -992,6 +996,7 @@ Creating orders
|
||||
"country": "UK",
|
||||
"state": "",
|
||||
"internal_reference": "",
|
||||
"invoice_email": null,
|
||||
"vat_id": ""
|
||||
},
|
||||
"positions": [
|
||||
|
||||
@@ -745,6 +745,7 @@ class EventSettingsSerializer(SettingsSerializer):
|
||||
'invoice_include_expire_date',
|
||||
'invoice_address_explanation_text',
|
||||
'invoice_email_attachment',
|
||||
'invoice_email_asked',
|
||||
'invoice_email_organizer',
|
||||
'invoice_address_from_name',
|
||||
'invoice_address_from',
|
||||
|
||||
@@ -92,7 +92,7 @@ class InvoiceAddressSerializer(I18nAwareModelSerializer):
|
||||
class Meta:
|
||||
model = InvoiceAddress
|
||||
fields = ('last_modified', 'is_business', 'company', 'name', 'name_parts', 'street', 'zipcode', 'city', 'country',
|
||||
'state', 'vat_id', 'vat_id_validated', 'custom_field', 'internal_reference')
|
||||
'state', 'vat_id', 'vat_id_validated', 'custom_field', 'internal_reference', 'invoice_email')
|
||||
read_only_fields = ('last_modified',)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
@@ -376,6 +376,14 @@ def base_placeholders(sender, **kwargs):
|
||||
SimpleFunctionalMailTextPlaceholder(
|
||||
'currency', ['event'], lambda event: event.currency, lambda event: event.currency
|
||||
),
|
||||
SimpleFunctionalMailTextPlaceholder(
|
||||
'order_email', ['order'], lambda order: order.email, 'john@example.org'
|
||||
),
|
||||
SimpleFunctionalMailTextPlaceholder(
|
||||
'invoice_number', ['invoice'],
|
||||
lambda invoice: invoice.full_invoice_no,
|
||||
f'{sender.settings.invoice_numbers_prefix or (sender.slug.upper() + "-")}00000'
|
||||
),
|
||||
SimpleFunctionalMailTextPlaceholder(
|
||||
'refund_amount', ['event_or_subevent', 'refund_amount'],
|
||||
lambda event_or_subevent, refund_amount: LazyCurrencyNumber(refund_amount, event_or_subevent.currency),
|
||||
|
||||
@@ -919,7 +919,7 @@ class BaseInvoiceAddressForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = InvoiceAddress
|
||||
fields = ('is_business', 'company', 'name_parts', 'street', 'zipcode', 'city', 'country', 'state',
|
||||
'vat_id', 'internal_reference', 'beneficiary', 'custom_field')
|
||||
'vat_id', 'internal_reference', 'beneficiary', 'custom_field', 'invoice_email')
|
||||
widgets = {
|
||||
'is_business': BusinessBooleanRadio,
|
||||
'street': forms.Textarea(attrs={
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.2.16 on 2022-11-15 10:16
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pretixbase', '0223_voucher_min_usages'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='invoiceaddress',
|
||||
name='invoice_email',
|
||||
field=models.EmailField(max_length=254, null=True),
|
||||
),
|
||||
]
|
||||
@@ -1038,6 +1038,59 @@ class Order(LockModel, LoggedModel):
|
||||
}
|
||||
)
|
||||
|
||||
def send_invoice_to_alternate_email(self, invoice):
|
||||
"""
|
||||
Sends an email to the alternate invoice address.
|
||||
"""
|
||||
from pretix.base.services.mail import (
|
||||
SendMailException, TolerantDict, mail, render_mail,
|
||||
)
|
||||
|
||||
try:
|
||||
recipient = self.invoice_address.invoice_email
|
||||
except InvoiceAddress.DoesNotExist:
|
||||
return
|
||||
if not recipient:
|
||||
return
|
||||
|
||||
with language(self.locale, self.event.settings.region):
|
||||
context = get_email_context(event=self.event, order=self, invoice=invoice, event_or_subevent=self.event,
|
||||
invoice_address=self.invoice_address)
|
||||
template = self.event.settings.email_text_invoice_only
|
||||
subject = self.event.settings.email_subject_invoice_only
|
||||
|
||||
try:
|
||||
email_content = render_mail(template, context)
|
||||
subject = subject.format_map(TolerantDict(context))
|
||||
mail(
|
||||
recipient,
|
||||
subject,
|
||||
template,
|
||||
context=context,
|
||||
event=self.event,
|
||||
locale=self.locale,
|
||||
order=self,
|
||||
invoices=[invoice],
|
||||
attach_tickets=False,
|
||||
auto_email=True,
|
||||
attach_ical=False,
|
||||
)
|
||||
except SendMailException:
|
||||
raise
|
||||
else:
|
||||
self.log_action(
|
||||
'pretix.event.order.email.order_invoice_only',
|
||||
data={
|
||||
'subject': subject,
|
||||
'message': email_content,
|
||||
'position': None,
|
||||
'recipient': recipient,
|
||||
'invoices': invoice.pk,
|
||||
'attach_tickets': False,
|
||||
'attach_ical': False,
|
||||
}
|
||||
)
|
||||
|
||||
def resend_link(self, user=None, auth=None):
|
||||
with language(self.locale, self.event.settings.region):
|
||||
email_template = self.event.settings.mail_text_resend_link
|
||||
@@ -2781,6 +2834,14 @@ class InvoiceAddress(models.Model):
|
||||
verbose_name=_('Beneficiary'),
|
||||
blank=True
|
||||
)
|
||||
invoice_email = models.EmailField(
|
||||
verbose_name=_('Send invoice to'),
|
||||
help_text=_('If your accounting department requires that we send them the invoice directly, you can enter '
|
||||
'their email address here. They will receive a separate email. You will still receive the invoice '
|
||||
'and booking confirmation as well.'),
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
|
||||
objects = ScopedManager(organizer='order__event__organizer')
|
||||
profiles = ScopedManager(organizer='customer__organizer')
|
||||
@@ -2865,6 +2926,7 @@ class InvoiceAddress(models.Model):
|
||||
'vat_id': self.vat_id,
|
||||
'custom_field': self.custom_field,
|
||||
'internal_reference': self.internal_reference,
|
||||
'invoice_email': self.invoice_email,
|
||||
'beneficiary': self.beneficiary,
|
||||
})
|
||||
return d
|
||||
|
||||
@@ -379,13 +379,18 @@ def invoice_pdf_task(invoice: int):
|
||||
with scope(organizer=i.order.event.organizer):
|
||||
if i.shredded:
|
||||
return None
|
||||
if i.file:
|
||||
i.file.delete()
|
||||
with language(i.locale, i.event.settings.region):
|
||||
|
||||
to_delete = i.file.name
|
||||
with transaction.atomic(), language(i.locale, i.event.settings.region):
|
||||
fname, ftype, fcontent = i.event.invoice_renderer.generate(i)
|
||||
i.file.save(fname, ContentFile(fcontent), save=False)
|
||||
i.save(update_fields=['file'])
|
||||
return i.file.name
|
||||
|
||||
try:
|
||||
i.file.storage.delete(to_delete)
|
||||
except:
|
||||
logger.exception('Could not delete previous PDF file for invoice')
|
||||
return i.file.name
|
||||
|
||||
|
||||
def invoice_qualified(order: Order):
|
||||
@@ -484,6 +489,14 @@ def fetch_ecb_rates(sender, **kwargs):
|
||||
logger.exception('Could not retrieve rates from ECB')
|
||||
|
||||
|
||||
@app.task(base=TransactionAwareTask)
|
||||
def send_invoice_to_customer_alternative_email(invoice_id):
|
||||
with scopes_disabled():
|
||||
i = Invoice.objects.get(pk=invoice_id)
|
||||
with scope(organizer=i.order.event.organizer):
|
||||
i.order.send_invoice_to_alternate_email(i)
|
||||
|
||||
|
||||
@receiver(signal=periodic_task)
|
||||
@scopes_disabled()
|
||||
def send_invoices_to_organizer(sender, **kwargs):
|
||||
|
||||
@@ -98,7 +98,8 @@ def mail(email: Union[str, Sequence[str]], subject: str, template: Union[str, La
|
||||
context: Dict[str, Any] = None, event: Event = None, locale: str = None, order: Order = None,
|
||||
position: OrderPosition = None, *, headers: dict = None, sender: str = None, organizer: Organizer = None,
|
||||
customer: Customer = None, invoices: Sequence = None, attach_tickets=False, auto_email=True, user=None,
|
||||
attach_ical=False, attach_cached_files: Sequence = None, attach_other_files: list=None):
|
||||
attach_ical=False, attach_cached_files: Sequence = None, attach_other_files: list=None,
|
||||
plain_text_without_links=False):
|
||||
"""
|
||||
Sends out an email to a user. The mail will be sent synchronously or asynchronously depending on the installation.
|
||||
|
||||
@@ -242,7 +243,7 @@ def mail(email: Union[str, Sequence[str]], subject: str, template: Union[str, La
|
||||
if order and order.testmode:
|
||||
subject = "[TESTMODE] " + subject
|
||||
|
||||
if order and position:
|
||||
if order and position and not plain_text_without_links:
|
||||
body_plain += _(
|
||||
"You are receiving this email because someone placed an order for {event} for you."
|
||||
).format(event=event.name)
|
||||
@@ -258,7 +259,7 @@ def mail(email: Union[str, Sequence[str]], subject: str, template: Union[str, La
|
||||
}
|
||||
)
|
||||
)
|
||||
elif order:
|
||||
elif order and not plain_text_without_links:
|
||||
body_plain += _(
|
||||
"You are receiving this email because you placed an order for {event}."
|
||||
).format(event=event.name)
|
||||
@@ -278,7 +279,9 @@ def mail(email: Union[str, Sequence[str]], subject: str, template: Union[str, La
|
||||
|
||||
with override(timezone):
|
||||
try:
|
||||
if 'position' in inspect.signature(renderer.render).parameters:
|
||||
if plain_text_without_links:
|
||||
body_html = None
|
||||
elif 'position' in inspect.signature(renderer.render).parameters:
|
||||
body_html = renderer.render(content_plain, signature, raw_subject, order, position)
|
||||
else:
|
||||
# Backwards compatibility
|
||||
@@ -596,8 +599,9 @@ def mail_send_task(self, *args, to: List[str], subject: str, body: str, html: st
|
||||
raise SendMailException('Failed to send an email to {}.'.format(to))
|
||||
else:
|
||||
for i in invoices_sent:
|
||||
i.sent_to_customer = now()
|
||||
i.save(update_fields=['sent_to_customer'])
|
||||
if not i.order.invoice_address.invoice_email or i.order.invoice_address.invoice_email in to:
|
||||
i.sent_to_customer = now()
|
||||
i.save(update_fields=['sent_to_customer'])
|
||||
|
||||
|
||||
def mail_send(*args, **kwargs):
|
||||
|
||||
@@ -80,6 +80,7 @@ from pretix.base.secrets import assign_ticket_secret
|
||||
from pretix.base.services import tickets
|
||||
from pretix.base.services.invoices import (
|
||||
generate_cancellation, generate_invoice, invoice_qualified,
|
||||
send_invoice_to_customer_alternative_email,
|
||||
)
|
||||
from pretix.base.services.locking import LockTimeoutException, NoLockManager
|
||||
from pretix.base.services.mail import SendMailException
|
||||
@@ -1091,6 +1092,13 @@ def _perform_order(event: Event, payment_provider: str, position_ids: List[str],
|
||||
if p.addon_to_id is None and p.attendee_email and p.attendee_email != order.email:
|
||||
_order_placed_email_attendee(event, order, p, email_attendees_template, subject_attendees_template, log_entry,
|
||||
is_free=free_order_flow)
|
||||
try:
|
||||
if invoice and order.invoice_address.invoice_email:
|
||||
# We fire this task with a little delay since both mail() calls will call invoice_pdf_task and this
|
||||
# will reduce the chance of the PDF renderer running twice except under exceptional load patterns.
|
||||
send_invoice_to_customer_alternative_email.apply_async(args=(invoice.pk,), countdown=60)
|
||||
except InvoiceAddress.DoesNotExist:
|
||||
pass
|
||||
|
||||
return order.id
|
||||
|
||||
|
||||
@@ -972,6 +972,18 @@ DEFAULTS = {
|
||||
"to emails."),
|
||||
)
|
||||
},
|
||||
'invoice_email_asked': {
|
||||
'default': 'False',
|
||||
'type': bool,
|
||||
'form_class': forms.BooleanField,
|
||||
'serializer_class': serializers.BooleanField,
|
||||
'form_kwargs': dict(
|
||||
label=_("Allow customers to enter an alternate email address"),
|
||||
help_text=_("If an alternate email address is entered, the invoice will be sent there in addition to being "
|
||||
"sent to the user."),
|
||||
widget=forms.CheckboxInput(attrs={'data-checkbox-dependency': '#id_invoice_email_attachment'}),
|
||||
)
|
||||
},
|
||||
'invoice_email_organizer': {
|
||||
'default': '',
|
||||
'type': str,
|
||||
@@ -2098,6 +2110,20 @@ You can view the details of your order here:
|
||||
{url}
|
||||
|
||||
Best regards,
|
||||
Your {event} team"""))
|
||||
},
|
||||
'mail_subject_invoice_only': {
|
||||
'type': LazyI18nString,
|
||||
'default': LazyI18nString.from_gettext(gettext_noop("Invoice {invoice_number}")),
|
||||
},
|
||||
'mail_text_invoice_only': {
|
||||
'type': LazyI18nString,
|
||||
'default': LazyI18nString.from_gettext(gettext_noop("""Hello,
|
||||
|
||||
you receive this message because an order for {event} was placed by {order_email} and we have been asked to forward the invoice to you.
|
||||
|
||||
Best regards,
|
||||
|
||||
Your {event} team"""))
|
||||
},
|
||||
'mail_text_order_custom_mail': {
|
||||
|
||||
@@ -802,6 +802,7 @@ class InvoiceSettingsForm(SettingsForm):
|
||||
'invoice_numbers_counter_length',
|
||||
'invoice_address_explanation_text',
|
||||
'invoice_email_attachment',
|
||||
'invoice_email_asked',
|
||||
'invoice_email_organizer',
|
||||
'invoice_address_from_name',
|
||||
'invoice_address_from',
|
||||
@@ -1170,6 +1171,16 @@ class MailSettingsForm(SettingsForm):
|
||||
required=False,
|
||||
widget=I18nTextarea,
|
||||
)
|
||||
mail_subject_invoice_only = I18nFormField(
|
||||
label=_("Subject"),
|
||||
required=False,
|
||||
widget=I18nTextInput,
|
||||
)
|
||||
mail_text_invoice_only = I18nFormField(
|
||||
label=_("Text"),
|
||||
required=False,
|
||||
widget=I18nTextarea,
|
||||
)
|
||||
base_context = {
|
||||
'mail_text_order_placed': ['event', 'order', 'payment'],
|
||||
'mail_subject_order_placed': ['event', 'order', 'payment'],
|
||||
@@ -1210,6 +1221,8 @@ class MailSettingsForm(SettingsForm):
|
||||
'mail_subject_waiting_list': ['event', 'waiting_list_entry'],
|
||||
'mail_text_resend_all_links': ['event', 'orders'],
|
||||
'mail_subject_resend_all_links': ['event', 'orders'],
|
||||
'mail_subject_invoice_only': ['event', 'order', 'invoice'],
|
||||
'mail_text_invoice_only': ['event', 'order', 'invoice'],
|
||||
'mail_attach_ical_description': ['event', 'event_or_subevent'],
|
||||
}
|
||||
|
||||
|
||||
@@ -392,6 +392,7 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs):
|
||||
'pretix.event.order.email.order_approved': _('An email has been sent to notify the user that the order has '
|
||||
'been approved.'),
|
||||
'pretix.event.order.email.order_placed': _('An email has been sent to notify the user that the order has been received and requires payment.'),
|
||||
'pretix.event.order.email.order_invoice_only': _('An invoice has been sent to an alternate email address.'),
|
||||
'pretix.event.order.email.order_placed_require_approval': _('An email has been sent to notify the user that '
|
||||
'the order has been received and requires '
|
||||
'approval.'),
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
{% bootstrap_field form.invoice_generate layout="control" %}
|
||||
{% bootstrap_field form.invoice_generate_sales_channels layout="control" %}
|
||||
{% bootstrap_field form.invoice_email_attachment layout="control" %}
|
||||
{% bootstrap_field form.invoice_email_asked layout="control" %}
|
||||
{% bootstrap_field form.invoice_email_organizer layout="control" %}
|
||||
{% bootstrap_field form.invoice_language layout="control" %}
|
||||
{% bootstrap_field form.invoice_include_free layout="control" %}
|
||||
|
||||
@@ -119,6 +119,10 @@
|
||||
|
||||
{% blocktrans asvar title_require_approval %}Order approval process{% endblocktrans %}
|
||||
{% include "pretixcontrol/event/mail_settings_fragment.html" with pid="ticket_reminder" title=title_require_approval items="mail_subject_order_placed_require_approval,mail_text_order_placed_require_approval,mail_subject_order_approved,mail_text_order_approved,mail_subject_order_approved_free,mail_text_order_approved_free,mail_subject_order_denied,mail_text_order_denied" %}
|
||||
|
||||
{% blocktrans asvar title_invoice_only %}Invoice to alternate address{% endblocktrans %}
|
||||
{% blocktrans asvar description_invoice_only %}This email text is used if you activated "Allow customers to enter an alternate email address" in your invoice settings and a user asks that the invoice is sent to an alternate email address. This email, unlike all other emails, will be sent without any styling to prevent issues with automated processing in accounting systems.{% endblocktrans %}
|
||||
{% include "pretixcontrol/event/mail_settings_fragment.html" with pid="ticket_reminder" title=title_invoice_only description=description_invoice_only items="mail_subject_invoice_only,mail_text_invoice_only" %}
|
||||
</div>
|
||||
<h4>{% trans "Attachments" %}</h4>
|
||||
{% bootstrap_field form.mail_attachment_new_order layout="control" %}
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
</summary>
|
||||
<div id="{{ pid }}">
|
||||
<div class="panel-body">
|
||||
{% if description %}
|
||||
<p class="help-block">{{ description }}</p>
|
||||
{% endif %}
|
||||
{% with exclude|split as exclusion %}
|
||||
{% with items|split as item_list %}
|
||||
{% for item in item_list %}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<fieldset>
|
||||
<legend>{% trans "General information" %}</legend>
|
||||
{% bootstrap_field form.name layout="control" %}
|
||||
<div class="internal-name-wrapper">
|
||||
<div class="optional-field-wrapper" data-text="{% trans "Use a different name internally" %}">
|
||||
{% bootstrap_field form.internal_name layout="control" %}
|
||||
</div>
|
||||
{% bootstrap_field form.copy_from layout="control" %}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<legend>{% trans "General" %}</legend>
|
||||
{% bootstrap_field form.active layout="control" %}
|
||||
{% bootstrap_field form.name layout="control" %}
|
||||
<div class="internal-name-wrapper">
|
||||
<div class="optional-field-wrapper" data-text="{% trans "Use a different name internally" %}">
|
||||
{% bootstrap_field form.internal_name layout="control" %}
|
||||
</div>
|
||||
{% bootstrap_field form.category layout="control" %}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<fieldset>
|
||||
<legend>{% trans "General information" %}</legend>
|
||||
{% bootstrap_field form.name layout="control" %}
|
||||
<div class="internal-name-wrapper">
|
||||
<div class="optional-field-wrapper" data-text="{% trans "Use a different name internally" %}">
|
||||
{% bootstrap_field form.internal_name layout="control" %}
|
||||
</div>
|
||||
{% bootstrap_field form.description layout="control" %}
|
||||
|
||||
@@ -923,6 +923,10 @@
|
||||
{% endif %}
|
||||
<dt>{% trans "Internal reference" %}</dt>
|
||||
<dd>{{ order.invoice_address.internal_reference }}</dd>
|
||||
{% if request.event.settings.invoice_email_asked %}
|
||||
<dt>{% trans "Send invoice to" %}</dt>
|
||||
<dd>{{ order.invoice_address.invoice_email }}</dd>
|
||||
{% endif %}
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -733,7 +733,7 @@ class MailSettingsPreview(EventPermissionRequiredMixin, View):
|
||||
idx = matched.group('idx')
|
||||
if idx in self.supported_locale:
|
||||
with language(self.supported_locale[idx], self.request.event.settings.region):
|
||||
if k.startswith('mail_subject_'):
|
||||
if k.startswith('mail_subject_') or k.endswith('_invoice_only'):
|
||||
msgs[self.supported_locale[idx]] = bleach.clean(v).format_map(self.placeholders(preview_item))
|
||||
else:
|
||||
msgs[self.supported_locale[idx]] = markdown_compile_email(
|
||||
|
||||
@@ -1048,7 +1048,8 @@ class QuestionsStep(QuestionsViewMixin, CartMixin, TemplateFlowStep):
|
||||
|
||||
for k in (
|
||||
"company", "street", "zipcode", "city", "country", "state",
|
||||
"state_for_address", "vat_id", "custom_field", "internal_reference", "beneficiary"
|
||||
"state_for_address", "vat_id", "custom_field", "internal_reference",
|
||||
"beneficiary", "invoice_email",
|
||||
):
|
||||
v = getattr(a, k) or ""
|
||||
# always add all values of an address even when empty,
|
||||
|
||||
@@ -105,6 +105,10 @@
|
||||
{% endif %}
|
||||
<dt>{% trans "Internal reference" %}</dt>
|
||||
<dd>{{ addr.internal_reference }}</dd>
|
||||
{% if request.event.settings.invoice_email_asked and addr.invoice_email %}
|
||||
<dt>{% trans "Send invoice to" %}</dt>
|
||||
<dd>{{ addr.invoice_email }}</dd>
|
||||
{% endif %}
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -68,7 +68,16 @@
|
||||
{{ event.settings.invoice_address_explanation_text|rich_text }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% bootstrap_form invoice_form layout="checkout" %}
|
||||
{% bootstrap_form_errors invoice_form layout="checkout" %}
|
||||
{% for f in invoice_form %}
|
||||
{% if f.name == "invoice_email" %}
|
||||
<div class="optional-field-wrapper" data-text="{% trans "Send invoice to a different email address" %}">
|
||||
{% bootstrap_field f layout="checkout" %}
|
||||
</div>
|
||||
{% else %}
|
||||
{% bootstrap_field f layout="checkout" %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
@@ -339,6 +339,10 @@
|
||||
{% endif %}
|
||||
<dt>{% trans "Internal Reference" %}</dt>
|
||||
<dd>{{ order.invoice_address.internal_reference }}</dd>
|
||||
{% if request.event.settings.invoice_email_asked and order.invoice_address.invoice_email %}
|
||||
<dt>{% trans "Send invoice to" %}</dt>
|
||||
<dd>{{ order.invoice_address.invoice_email }}</dd>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
@@ -846,8 +846,8 @@ function setup_basics(el) {
|
||||
update();
|
||||
});
|
||||
|
||||
// Items and categories
|
||||
el.find(".internal-name-wrapper").each(function () {
|
||||
// Hide optional field
|
||||
el.find(".optional-field-wrapper").each(function () {
|
||||
if ($(this).find("input").val() === "") {
|
||||
var $fg = $(this).find(".form-group");
|
||||
$fg.hide();
|
||||
@@ -855,7 +855,7 @@ function setup_basics(el) {
|
||||
$("<div>").addClass("col-md-9 col-md-offset-3").append(
|
||||
$("<div>").addClass("help-block").append(
|
||||
$("<a>").attr("href", "#").text(
|
||||
gettext("Use a different name internally")
|
||||
$(this).attr("data-text")
|
||||
).click(function () {
|
||||
$fg.slideDown();
|
||||
$fgl.slideUp();
|
||||
|
||||
@@ -139,6 +139,28 @@ var form_handlers = function (el) {
|
||||
});
|
||||
});
|
||||
|
||||
// Hide optional field
|
||||
el.find(".optional-field-wrapper").each(function () {
|
||||
if ($(this).find("input").val() === "") {
|
||||
var $fg = $(this).find(".form-group");
|
||||
$fg.hide();
|
||||
var $fgl = $("<div>").addClass("form-group").append(
|
||||
$("<div>").addClass("col-md-9 col-md-offset-3").append(
|
||||
$("<div>").addClass("help-block").append(
|
||||
$("<a>").attr("href", "#").text(
|
||||
$(this).attr("data-text")
|
||||
).click(function () {
|
||||
$fg.slideDown();
|
||||
$fgl.slideUp();
|
||||
return false;
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
$(this).append($fgl);
|
||||
}
|
||||
});
|
||||
|
||||
el.find("input[name*=question], select[name*=question]").change(questions_toggle_dependent);
|
||||
questions_toggle_dependent();
|
||||
questions_init_photos(el);
|
||||
|
||||
@@ -412,7 +412,11 @@ function questions_init_profiles(el) {
|
||||
var answer = selectedProfile[key].value;
|
||||
var $field = selectedProfile[key].field;
|
||||
if (!$field || !$field.length) return;
|
||||
|
||||
|
||||
if ($field.closest('.optional-field-wrapper').length) {
|
||||
$field.closest('.optional-field-wrapper').find('.form-group').first().show()
|
||||
$field.closest('.optional-field-wrapper').find('.form-group').last().hide()
|
||||
}
|
||||
if ($field.attr("type") === "checkbox") {
|
||||
if (answer === true || answer === false) {
|
||||
// boolean
|
||||
|
||||
@@ -323,7 +323,8 @@ def test_order_create_simulate(token_client, organizer, event, item, quota, ques
|
||||
'vat_id': '',
|
||||
'vat_id_validated': False,
|
||||
'internal_reference': '',
|
||||
'custom_field': None
|
||||
'custom_field': None,
|
||||
'invoice_email': None,
|
||||
},
|
||||
'positions': [
|
||||
{
|
||||
|
||||
@@ -265,6 +265,7 @@ TEST_ORDER_RES = {
|
||||
"country": "NZ",
|
||||
"state": "",
|
||||
"internal_reference": "",
|
||||
"invoice_email": None,
|
||||
"custom_field": "Custom info",
|
||||
"vat_id": "DE123",
|
||||
"vat_id_validated": True
|
||||
|
||||
Reference in New Issue
Block a user