def convert_old_settings(app, schema_editor):
    EventSettingsStore = app.get_model('pretixbase', 'Event_SettingsStore')
    for es in EventSettingsStore.objects.filter(key='ticketoutput_pdf_layout'):
        locale_es = EventSettingsStore.objects.filter(object=es.object, key='locale').first()
        if locale_es:
            locale = locale_es.value
        else:
            locale = 'en'

        with language(locale):
            es.object.ticket_layouts.create(
                name=gettext('Default layout'),
                default=True,
                layout=es.value
            )

    for es in EventSettingsStore.objects.filter(key='ticketoutput_pdf_background'):
        locale_es = EventSettingsStore.objects.filter(object=es.object, key='locale').first()
        if locale_es:
            locale = locale_es.value
        else:
            locale = 'en'

        with language(locale):
            l = es.object.ticket_layouts.get_or_create(
                default=True,
                defaults={
                    'name': gettext('Default layout'),
                }
            )[0]

            l.background.name = es.value[7:]
            setattr(l, 'background', l.background.name)
            l.save()
            es.delete()
Esempio n. 2
0
def render_pdf(event, positions):
    Renderer._register_fonts()

    renderermap = {
        bi.item_id: _renderer(event, bi.layout)
        for bi in BadgeItem.objects.select_related('layout').filter(item__event=event)
    }
    try:
        default_renderer = _renderer(event, event.badge_layouts.get(default=True))
    except BadgeLayout.DoesNotExist:
        default_renderer = None
    merger = PdfFileMerger()

    for op in positions:
        r = renderermap.get(op.item_id, default_renderer)
        if not r:
            continue

        with language(op.order.locale):
            buffer = BytesIO()
            p = canvas.Canvas(buffer, pagesize=pagesizes.A4)
            r.draw_page(p, op.order, op)
            p.save()
            outbuffer = r.render_background(buffer, 'Badge')
            merger.append(ContentFile(outbuffer.read()))

    outbuffer = BytesIO()
    merger.write(outbuffer)
    merger.close()
    outbuffer.seek(0)
    return outbuffer
Esempio n. 3
0
def preview(event: int, provider: str):
    event = Event.objects.get(id=event)

    with rolledback_transaction(), language(event.settings.locale):
        item = event.items.create(name=_("Sample product"), default_price=42.23,
                                  description=_("Sample product description"))
        item2 = event.items.create(name=_("Sample workshop"), default_price=23.40)

        from pretix.base.models import Order
        order = event.orders.create(status=Order.STATUS_PENDING, datetime=now(),
                                    email='*****@*****.**',
                                    locale=event.settings.locale,
                                    expires=now(), code="PREVIEW1234", total=119)

        scheme = PERSON_NAME_SCHEMES[event.settings.name_scheme]
        sample = {k: str(v) for k, v in scheme['sample'].items()}
        p = order.positions.create(item=item, attendee_name_parts=sample, price=item.default_price)
        order.positions.create(item=item2, attendee_name_parts=sample, price=item.default_price, addon_to=p)
        order.positions.create(item=item2, attendee_name_parts=sample, price=item.default_price, addon_to=p)

        InvoiceAddress.objects.create(order=order, name_parts=sample, company=_("Sample company"))

        responses = register_ticket_outputs.send(event)
        for receiver, response in responses:
            prov = response(event)
            if prov.identifier == provider:
                return prov.generate(p)
Esempio n. 4
0
def add_items_to_cart(self, event: int, items: List[dict], cart_id: str=None, locale='en',
                      invoice_address: int=None, widget_data=None, sales_channel='web') -> None:
    """
    Adds a list of items to a user's cart.
    :param event: The event ID in question
    :param items: A list of dicts with the keys item, variation, number, custom_price, voucher
    :param cart_id: Session ID of a guest
    :raises CartError: On any error that occured
    """
    with language(locale):
        event = Event.objects.get(id=event)

        ia = False
        if invoice_address:
            try:
                ia = InvoiceAddress.objects.get(pk=invoice_address)
            except InvoiceAddress.DoesNotExist:
                pass

        try:
            try:
                cm = CartManager(event=event, cart_id=cart_id, invoice_address=ia, widget_data=widget_data,
                                 sales_channel=sales_channel)
                cm.add_new_items(items)
                cm.commit()
            except LockTimeoutException:
                self.retry()
        except (MaxRetriesExceededError, LockTimeoutException):
            raise CartError(error_messages['busy'])
Esempio n. 5
0
def set_cart_addons(self, event: int, addons: List[dict], cart_id: str=None, locale='en',
                    invoice_address: int=None, sales_channel='web') -> None:
    """
    Removes a list of items from a user's cart.
    :param event: The event ID in question
    :param addons: A list of dicts with the keys addon_to, item, variation
    :param session: Session ID of a guest
    """
    with language(locale):
        event = Event.objects.get(id=event)

        ia = False
        if invoice_address:
            try:
                ia = InvoiceAddress.objects.get(pk=invoice_address)
            except InvoiceAddress.DoesNotExist:
                pass
        try:
            try:
                cm = CartManager(event=event, cart_id=cart_id, invoice_address=ia, sales_channel=sales_channel)
                cm.set_addons(addons)
                cm.commit()
            except LockTimeoutException:
                self.retry()
        except (MaxRetriesExceededError, LockTimeoutException):
            raise CartError(error_messages['busy'])
Esempio n. 6
0
def process_banktransfers(event: int, job: int, data: list) -> None:
    with language("en"):  # We'll translate error messages at display time
        event = Event.objects.get(pk=event)
        job = BankImportJob.objects.get(pk=job)
        job.state = BankImportJob.STATE_RUNNING
        job.save()

        try:
            # Delete left-over transactions from a failed run before so they can reimported
            BankTransaction.objects.filter(event=event, state=BankTransaction.STATE_UNCHECKED).delete()

            transactions = _get_unknown_transactions(event, job, data)

            code_len = settings.ENTROPY['order_code']
            pattern = re.compile(event.slug.upper() + "[ \-_]*([A-Z0-9]{%s})" % code_len)

            for trans in transactions:
                match = pattern.search(trans.reference.upper())

                if match:
                    code = match.group(1)
                    with transaction.atomic():
                        _handle_transaction(event, trans, code)
                else:
                    trans.state = BankTransaction.STATE_NOMATCH
                    trans.save()
        except Exception as e:
            job.state = BankImportJob.STATE_ERROR
            job.save()
            raise e
        else:
            job.state = BankImportJob.STATE_COMPLETED
            job.save()
Esempio n. 7
0
def notify_incomplete_payment(o: Order):
    with language(o.locale):
        tz = pytz.timezone(o.event.settings.get('timezone', settings.TIME_ZONE))
        try:
            invoice_name = o.invoice_address.name
            invoice_company = o.invoice_address.company
        except InvoiceAddress.DoesNotExist:
            invoice_name = ""
            invoice_company = ""
        email_template = o.event.settings.mail_text_order_expire_warning
        email_context = {
            'event': o.event.name,
            'url': build_absolute_uri(o.event, 'presale:event.order.open', kwargs={
                'order': o.code,
                'secret': o.secret,
                'hash': o.email_confirm_hash()
            }),
            'expire_date': date_format(o.expires.astimezone(tz), 'SHORT_DATE_FORMAT'),
            'invoice_name': invoice_name,
            'invoice_company': invoice_company,
        }
        email_subject = ugettext('Your order received an incomplete payment: %(code)s') % {'code': o.code}

        try:
            o.send_mail(
                email_subject, email_template, email_context,
                'pretix.event.order.email.expire_warning_sent'
            )
        except SendMailException:
            logger.exception('Reminder email could not be sent')
Esempio n. 8
0
def mail(email: str, subject: str, template: str,
         context: Dict[str, Any]=None, event: Event=None, locale: str=None,
         order: Order=None):
    """
    Sends out an email to a user. The mail will be sent synchronously or asynchronously depending on the installation.

    :param email: The email address of the recipient

    :param subject: The email subject. Should be localized to the recipients's locale or a lazy object that will be
        localized by being casted to a string.

    :param template: The filename of a template to be used. It will be rendered with the locale given in the locale
        argument and the context given in the next argument. Alternatively, you can pass a LazyI18nString and
        ``context`` will be used as the argument to a  Python ``.format()`` call on the template.

    :param context: The context for rendering the template (see ``template`` parameter)

    :param event: The event this email is related to (optional). If set, this will be used to determine the sender,
        a possible prefix for the subject and the SMTP server that should be used to send this email.

    :param order: The order this email is related to (optional). If set, this will be used to include a link to the
        order below the email.

    :param locale: The locale to be used while evaluating the subject and the template

    :return: ``False`` on obvious, immediate failures, ``True`` otherwise. ``True`` does not necessarily mean that
        the email has been sent, just that it has been queued by the email backend.
    """
    with language(locale):
        if isinstance(template, LazyI18nString):
            body = str(template)
            if context:
                body = body.format_map(TolerantDict(context))
        else:
            tpl = get_template(template)
            body = tpl.render(context)

        sender = event.settings.get('mail_from') if event else settings.MAIL_FROM

        subject = str(subject)
        if event:
            prefix = event.settings.get('mail_prefix')
            if prefix:
                subject = "[%s] %s" % (prefix, subject)

            body += "\r\n\r\n----\r\n"
            body += _(
                "You are receiving this email because you placed an order for {event}."
            ).format(event=event.name)
            if order:
                body += "\r\n"
                body += _(
                    "You can view your order details at the following URL:\r\n{orderurl}."
                ).format(event=event.name, orderurl=build_absolute_uri(order.event, 'presale:event.order', kwargs={
                    'order': order.code,
                    'secret': order.secret
                }))
            body += "\r\n"
        return mail_send([email], subject, body, sender, event.id if event else None)
Esempio n. 9
0
def mark_order_paid(order: Order, provider: str=None, info: str=None, date: datetime=None, manual: bool=None,
                    force: bool=False, send_mail: bool=True, user: User=None) -> Order:
    """
    Marks an order as paid. This sets the payment provider, info and date and returns
    the order object.

    :param provider: The payment provider that marked this as paid
    :type provider: str
    :param info: The information to store in order.payment_info
    :type info: str
    :param date: The date the payment was received (if you pass ``None``, the current
                 time will be used).
    :type date: datetime
    :param force: Whether this payment should be marked as paid even if no remaining
                  quota is available (default: ``False``).
    :type force: boolean
    :param send_mail: Whether an email should be sent to the user about this event (default: ``True``).
    :type send_mail: boolean
    :param user: The user that performed the change
    :raises Quota.QuotaExceededException: if the quota is exceeded and ``force`` is ``False``
    """
    with order.event.lock():
        can_be_paid = order._can_be_paid()
        if not force and can_be_paid is not True:
            raise Quota.QuotaExceededException(can_be_paid)
        order.payment_provider = provider or order.payment_provider
        order.payment_info = info or order.payment_info
        order.payment_date = date or now()
        if manual is not None:
            order.payment_manual = manual
        order.status = Order.STATUS_PAID
        order.save()

    order.log_action('pretix.event.order.paid', {
        'provider': provider,
        'info': info,
        'date': date,
        'manual': manual,
        'force': force
    }, user=user)
    order_paid.send(order.event, order=order)

    if send_mail:
        with language(order.locale):
            mail(
                order.email, _('Payment received for your order: %(code)s') % {'code': order.code},
                order.event.settings.mail_text_order_paid,
                {
                    'event': order.event.name,
                    'url': build_absolute_uri(order.event, 'presale:event.order', kwargs={
                        'order': order.code,
                        'secret': order.secret
                    }),
                    'downloads': order.event.settings.get('ticket_download', as_type=bool)
                },
                order.event, locale=order.locale
            )
    return order
Esempio n. 10
0
def build_preview_invoice_pdf(event):
    locale = event.settings.invoice_language
    if not locale or locale == '__user__':
        locale = event.settings.locale

    with rolledback_transaction(), language(locale):
        order = event.orders.create(status=Order.STATUS_PENDING, datetime=timezone.now(),
                                    expires=timezone.now(), code="PREVIEW", total=119)
        invoice = Invoice(
            order=order, event=event, invoice_no="PREVIEW",
            date=timezone.now().date(), locale=locale, organizer=event.organizer
        )
        invoice.invoice_from = event.settings.get('invoice_address_from')
        invoice.invoice_from_name = invoice.event.settings.get('invoice_address_from_name')
        invoice.invoice_from_zipcode = invoice.event.settings.get('invoice_address_from_zipcode')
        invoice.invoice_from_city = invoice.event.settings.get('invoice_address_from_city')
        invoice.invoice_from_country = invoice.event.settings.get('invoice_address_from_country')
        invoice.invoice_from_tax_id = invoice.event.settings.get('invoice_address_from_tax_id')
        invoice.invoice_from_vat_id = invoice.event.settings.get('invoice_address_from_vat_id')

        introductory = event.settings.get('invoice_introductory_text', as_type=LazyI18nString)
        additional = event.settings.get('invoice_additional_text', as_type=LazyI18nString)
        footer = event.settings.get('invoice_footer_text', as_type=LazyI18nString)
        payment = _("A payment provider specific text might appear here.")

        invoice.introductory_text = str(introductory).replace('\n', '<br />')
        invoice.additional_text = str(additional).replace('\n', '<br />')
        invoice.footer_text = str(footer)
        invoice.payment_provider_text = str(payment).replace('\n', '<br />')
        invoice.invoice_to_name = _("John Doe")
        invoice.invoice_to_street = _("214th Example Street")
        invoice.invoice_to_zipcode = _("012345")
        invoice.invoice_to_city = _('Sample city')
        invoice.invoice_to_country = Country('DE')
        invoice.invoice_to = '{}\n{}\n{} {}'.format(
            invoice.invoice_to_name, invoice.invoice_to_street,
            invoice.invoice_to_zipcode, invoice.invoice_to_city
        )
        invoice.invoice_to_beneficiary = ''
        invoice.file = None
        invoice.save()
        invoice.lines.all().delete()

        if event.tax_rules.exists():
            for i, tr in enumerate(event.tax_rules.all()):
                tax = tr.tax(Decimal('100.00'))
                InvoiceLine.objects.create(
                    invoice=invoice, description=_("Sample product {}").format(i + 1),
                    gross_value=tax.gross, tax_value=tax.tax,
                    tax_rate=tax.rate
                )
        else:
            InvoiceLine.objects.create(
                invoice=invoice, description=_("Sample product A"),
                gross_value=100, tax_value=0, tax_rate=0
            )

        return event.invoice_renderer.generate(invoice)
Esempio n. 11
0
    def send_voucher(self, quota_cache=None, user=None, auth=None):
        availability = (
            self.variation.check_quotas(count_waitinglist=False, subevent=self.subevent, _cache=quota_cache)
            if self.variation
            else self.item.check_quotas(count_waitinglist=False, subevent=self.subevent, _cache=quota_cache)
        )
        if availability[1] is None or availability[1] < 1:
            raise WaitingListException(_('This product is currently not available.'))
        if self.voucher:
            raise WaitingListException(_('A voucher has already been sent to this person.'))
        if '@' not in self.email:
            raise WaitingListException(_('This entry is anonymized and can no longer be used.'))

        with transaction.atomic():
            v = Voucher.objects.create(
                event=self.event,
                max_usages=1,
                valid_until=now() + timedelta(hours=self.event.settings.waiting_list_hours),
                item=self.item,
                variation=self.variation,
                tag='waiting-list',
                comment=_('Automatically created from waiting list entry for {email}').format(
                    email=self.email
                ),
                block_quota=True,
                subevent=self.subevent,
            )
            v.log_action('pretix.voucher.added.waitinglist', {
                'item': self.item.pk,
                'variation': self.variation.pk if self.variation else None,
                'tag': 'waiting-list',
                'block_quota': True,
                'valid_until': v.valid_until.isoformat(),
                'max_usages': 1,
                'email': self.email,
                'waitinglistentry': self.pk,
                'subevent': self.subevent.pk if self.subevent else None,
            }, user=user, auth=auth)
            self.log_action('pretix.waitinglist.voucher', user=user, auth=auth)
            self.voucher = v
            self.save()

        with language(self.locale):
            mail(
                self.email,
                _('You have been selected from the waitinglist for {event}').format(event=str(self.event)),
                self.event.settings.mail_text_waiting_list,
                {
                    'event': self.event.name,
                    'url': build_absolute_uri(self.event, 'presale:event.redeem') + '?voucher=' + self.voucher.code,
                    'code': self.voucher.code,
                    'product': str(self.item) + (' - ' + str(self.variation) if self.variation else ''),
                    'hours': self.event.settings.waiting_list_hours,
                },
                self.event,
                locale=self.locale
            )
Esempio n. 12
0
def _perform_order(event: str, payment_provider: str, position_ids: List[str],
                   email: str, locale: str, address: int):

    event = Event.objects.get(id=event)
    responses = register_payment_providers.send(event)
    pprov = None
    for rec, response in responses:
        provider = response(event)
        if provider.identifier == payment_provider:
            pprov = provider
    if not pprov:
        raise OrderError(error_messages['internal'])

    dt = now()
    with event.lock():
        positions = list(CartPosition.objects.filter(
            id__in=position_ids).select_related('item', 'variation'))
        if len(position_ids) != len(positions):
            raise OrderError(error_messages['internal'])
        _check_positions(event, dt, positions)
        order = _create_order(event, email, positions, dt, pprov,
                              locale=locale)

    if address is not None:
        try:
            addr = InvoiceAddress.objects.get(
                pk=address
            )
            if addr.order is not None:
                addr.pk = None
            addr.order = order
            addr.save()
        except InvoiceAddress.DoesNotExist:
            pass

    if event.settings.get('invoice_generate') == 'True':
        generate_invoice(order)

    with language(order.locale):
        mail(
            order.email, _('Your order: %(code)s') % {'code': order.code},
            event.settings.mail_text_order_placed,
            {
                'total': LazyNumber(order.total),
                'currency': event.currency,
                'date': LazyDate(order.expires),
                'event': event.name,
                'url': build_absolute_uri(event, 'presale:event.order', kwargs={
                    'order': order.code,
                    'secret': order.secret
                }),
                'paymentinfo': str(pprov.order_pending_mail_render(order))
            },
            event, locale=order.locale
        )

    return order.id
Esempio n. 13
0
def invoice_pdf_task(invoice: int):
    i = Invoice.objects.get(pk=invoice)
    with language(i.locale):
        with tempfile.NamedTemporaryFile(suffix=".pdf") as f:
            _invoice_generate_german(i, f)
            f.seek(0)
            i.file.save('invoice.pdf', ContentFile(f.read()))
        i.save()
        return i.file.name
Esempio n. 14
0
def build_invoice(invoice: Invoice) -> Invoice:
    with language(invoice.locale):
        responses = register_payment_providers.send(invoice.event)
        for receiver, response in responses:
            provider = response(invoice.event)
            if provider.identifier == invoice.order.payment_provider:
                payment_provider = provider
                break

        invoice.invoice_from = invoice.event.settings.get('invoice_address_from')

        introductory = invoice.event.settings.get('invoice_introductory_text', as_type=LazyI18nString)
        additional = invoice.event.settings.get('invoice_additional_text', as_type=LazyI18nString)
        footer = invoice.event.settings.get('invoice_footer_text', as_type=LazyI18nString)
        payment = payment_provider.render_invoice_text(invoice.order)

        invoice.introductory_text = str(introductory).replace('\n', '<br />')
        invoice.additional_text = str(additional).replace('\n', '<br />')
        invoice.footer_text = str(footer)
        invoice.payment_provider_text = str(payment).replace('\n', '<br />')

        try:
            addr_template = pgettext("invoice", """{i.company}
{i.name}
{i.street}
{i.zipcode} {i.city}
{i.country}""")
            invoice.invoice_to = addr_template.format(i=invoice.order.invoice_address).strip()
            if invoice.order.invoice_address.vat_id:
                invoice.invoice_to += "\n" + pgettext("invoice", "VAT-ID: %s") % invoice.order.invoice_address.vat_id
        except InvoiceAddress.DoesNotExist:
            invoice.invoice_to = ""

        invoice.file = None
        invoice.save()
        invoice.lines.all().delete()

        for p in invoice.order.positions.all():
            desc = str(p.item.name)
            if p.variation:
                desc += " - " + str(p.variation.value)
            InvoiceLine.objects.create(
                invoice=invoice, description=desc,
                gross_value=p.price, tax_value=p.tax_value,
                tax_rate=p.tax_rate
            )

        if invoice.order.payment_fee:
            InvoiceLine.objects.create(
                invoice=invoice, description=_('Payment via {method}').format(method=str(payment_provider.verbose_name)),
                gross_value=invoice.order.payment_fee, tax_value=invoice.order.payment_fee_tax_value,
                tax_rate=invoice.order.payment_fee_tax_rate
            )

        return invoice
Esempio n. 15
0
    def render(self, form_data):
        merger = PdfFileMerger()

        o = PdfTicketOutput(self.event)
        qs = OrderPosition.objects.filter(
            order__event=self.event
        ).prefetch_related(
            'answers', 'answers__question'
        ).select_related('order', 'item', 'variation', 'addon_to')

        if form_data.get('include_pending'):
            qs = qs.filter(order__status__in=[Order.STATUS_PAID, Order.STATUS_PENDING])
        else:
            qs = qs.filter(order__status__in=[Order.STATUS_PAID])

        if form_data.get('order_by') == 'name':
            qs = qs.order_by('attendee_name_cached', 'order__code')
        elif form_data.get('order_by') == 'code':
            qs = qs.order_by('order__code')
        elif form_data.get('order_by', '').startswith('name:'):
            part = form_data['order_by'][5:]
            qs = qs.annotate(
                resolved_name=Coalesce('attendee_name_parts', 'addon_to__attendee_name_parts', 'order__invoice_address__name_parts')
            ).annotate(
                resolved_name_part=JSONExtract('resolved_name', part)
            ).order_by(
                'resolved_name_part'
            )

        for op in qs:
            if op.addon_to_id and not self.event.settings.ticket_download_addons:
                continue
            if not op.item.admission and not self.event.settings.ticket_download_nonadm:
                continue

            with language(op.order.locale):
                buffer = BytesIO()
                p = o._create_canvas(buffer)
                layout = o.layout_map.get(
                    (op.item_id, op.order.sales_channel),
                    o.layout_map.get(
                        (op.item_id, 'web'),
                        o.default_layout
                    )
                )
                o._draw_page(layout, p, op, op.order)
                p.save()
                outbuffer = o._render_with_background(layout, buffer)
                merger.append(ContentFile(outbuffer.read()))

        outbuffer = BytesIO()
        merger.write(outbuffer)
        merger.close()
        outbuffer.seek(0)
        return '{}_tickets.pdf'.format(self.event.slug), 'application/pdf', outbuffer.read()
Esempio n. 16
0
def invoice_pdf_task(invoice: int):
    i = Invoice.objects.get(pk=invoice)
    if i.shredded:
        return None
    if i.file:
        i.file.delete()
    with language(i.locale):
        fname, ftype, fcontent = i.event.invoice_renderer.generate(i)
        i.file.save(fname, ContentFile(fcontent))
        i.save()
        return i.file.name
Esempio n. 17
0
def export(event: str, fileid: str, provider: str, form_data: Dict[str, Any]) -> None:
    event = Event.objects.get(id=event)
    file = CachedFile.objects.get(id=fileid)
    with language(event.settings.locale):
        responses = register_data_exporters.send(event)
        for receiver, response in responses:
            ex = response(event)
            if ex.identifier == provider:
                file.filename, file.type, data = ex.render(form_data)
                file.file.save(cachedfile_name(file, file.filename), ContentFile(data))
                file.save()
def create_checkin_lists(apps, schema_editor):
    Event = apps.get_model('pretixbase', 'Event')
    Checkin = apps.get_model('pretixbase', 'Checkin')
    EventSettingsStore = apps.get_model('pretixbase', 'Event_SettingsStore')
    for e in Event.objects.all():
        locale = EventSettingsStore.objects.filter(object=e, key='locale').first()
        if locale:
            locale = locale.value
        else:
            locale = settings.LANGUAGE_CODE

        if e.has_subevents:
            for se in e.subevents.all():
                with language(locale):
                    cl = e.checkin_lists.create(name=se.name, subevent=se, all_products=True)
                Checkin.objects.filter(position__subevent=se, position__order__event=e).update(list=cl)
        else:
            with language(locale):
                cl = e.checkin_lists.create(name=_('Default list'), all_products=True)
            Checkin.objects.filter(position__order__event=e).update(list=cl)
Esempio n. 19
0
def generate_invoice(order: Order):
    locale = order.event.settings.get('invoice_language')
    if locale:
        if locale == '__user__':
            locale = order.locale

    with language(locale):
        i = Invoice(order=order, event=order.event)
        i.invoice_from = order.event.settings.get('invoice_address_from')
        i.additional_text = order.event.settings.get('invoice_additional_text')

        try:
            addr_template = pgettext("invoice", """{i.company}
{i.name}
{i.street}
{i.zipcode} {i.city}
{i.country}""")
            i.invoice_to = addr_template.format(i=order.invoice_address).strip()
            if order.invoice_address.vat_id:
                i.invoice_to += "\n" + pgettext("invoice", "VAT-ID: %s") % order.invoice_address.vat_id
        except InvoiceAddress.DoesNotExist:
            i.invoice_to = ""

        i.date = date.today()
        i.locale = locale
        i.save()

        responses = register_payment_providers.send(order.event)
        for receiver, response in responses:
            provider = response(order.event)
            if provider.identifier == order.payment_provider:
                payment_provider = provider
                break

        for p in order.positions.all():
            desc = str(p.item.name)
            if p.variation:
                desc += " - " + str(p.variation.value)
            InvoiceLine.objects.create(
                invoice=i, description=desc,
                gross_value=p.price, tax_value=p.tax_value,
                tax_rate=p.tax_rate
            )

        if order.payment_fee:
            InvoiceLine.objects.create(
                invoice=i, description=_('Payment via {method}').format(method=str(payment_provider.verbose_name)),
                gross_value=order.payment_fee, tax_value=order.payment_fee_tax_value,
                tax_rate=order.payment_fee_tax_rate
            )

        invoice_pdf(i.pk)
    return i
Esempio n. 20
0
 def generate(self, op):
     order = op.order
     layout = self.layout_map.get(
         (op.item_id, order.sales_channel),
         self.layout_map.get(
             (op.item_id, 'web'),
             self.default_layout
         )
     )
     with language(order.locale):
         outbuffer = self._draw_page(layout, op, order)
     return 'order%s%s.pdf' % (self.event.slug, order.code), 'application/pdf', outbuffer.read()
Esempio n. 21
0
    def post(self, request, *args, **kwargs):
        if "background" in request.FILES:
            error, fileobj = self.process_upload()
            if error:
                return JsonResponse({
                    "status": "error",
                    "error": error
                })
            c = CachedFile()
            c.expires = now() + timedelta(days=7)
            c.date = now()
            c.filename = 'background_preview.pdf'
            c.type = 'application/pdf'
            c.file = fileobj
            c.save()
            c.refresh_from_db()
            return JsonResponse({
                "status": "ok",
                "id": c.id,
                "url": reverse('control:pdf.background', kwargs={
                    'event': request.event.slug,
                    'organizer': request.organizer.slug,
                    'filename': str(c.id)
                })
            })

        cf = None
        if request.POST.get("background", "").strip():
            try:
                cf = CachedFile.objects.get(id=request.POST.get("background"))
            except CachedFile.DoesNotExist:
                pass

        if "preview" in request.POST:
            with rolledback_transaction(), language(request.event.settings.locale):
                p = self._get_preview_position()
                fname, mimet, data = self.generate(
                    p,
                    override_layout=(json.loads(self.request.POST.get("data"))
                                     if self.request.POST.get("data") else None),
                    override_background=cf.file if cf else None
                )

            resp = HttpResponse(data, content_type=mimet)
            ftype = fname.split(".")[-1]
            resp['Content-Disposition'] = 'attachment; filename="ticket-preview.{}"'.format(ftype)
            return resp
        elif "data" in request.POST:
            if cf:
                self.save_background(cf)
            self.save_layout()
            return JsonResponse({'status': 'ok'})
        return HttpResponseBadRequest()
Esempio n. 22
0
def process_banktransfers(self, job: int, data: list) -> None:
    with language("en"):  # We'll translate error messages at display time
        job = BankImportJob.objects.get(pk=job)
        job.state = BankImportJob.STATE_RUNNING
        job.save()
        prefixes = []

        try:
            # Delete left-over transactions from a failed run before so they can reimported
            BankTransaction.objects.filter(state=BankTransaction.STATE_UNCHECKED, **job.owner_kwargs).delete()

            transactions = _get_unknown_transactions(job, data, **job.owner_kwargs)

            code_len = settings.ENTROPY['order_code']
            if job.event:
                pattern = re.compile(job.event.slug.upper() + r"[ \-_]*([A-Z0-9]{%s})" % code_len)
            else:
                if not prefixes:
                    prefixes = [e.slug.upper().replace(".", r"\.").replace("-", r"[\- ]*")
                                for e in job.organizer.events.all()]
                pattern = re.compile("(%s)[ \\-_]*([A-Z0-9]{%s})" % ("|".join(prefixes), code_len))

            for trans in transactions:
                match = pattern.search(trans.reference.replace(" ", "").replace("\n", "").upper())

                if match:
                    if job.event:
                        code = match.group(1)
                        with transaction.atomic():
                            _handle_transaction(trans, code, event=job.event)
                    else:
                        slug = match.group(1)
                        code = match.group(2)
                        with transaction.atomic():
                            _handle_transaction(trans, code, organizer=job.organizer, slug=slug)
                else:
                    trans.state = BankTransaction.STATE_NOMATCH
                    trans.save()
        except LockTimeoutException:
            try:
                self.retry()
            except MaxRetriesExceededError:
                logger.exception('Maximum number of retries exceeded for task.')
                job.state = BankImportJob.STATE_ERROR
                job.save()
        except Exception as e:
            job.state = BankImportJob.STATE_ERROR
            job.save()
            raise e
        else:
            job.state = BankImportJob.STATE_COMPLETED
            job.save()
Esempio n. 23
0
 def _notify_user(self):
     with language(self.order.locale):
         mail(
             self.order.email, _('Your order has been changed: %(code)s') % {'code': self.order.code},
             self.order.event.settings.mail_text_order_changed,
             {
                 'event': self.order.event.name,
                 'url': build_absolute_uri(self.order.event, 'presale:event.order', kwargs={
                     'order': self.order.code,
                     'secret': self.order.secret
                 }),
             },
             self.order.event, locale=self.order.locale
         )
Esempio n. 24
0
def send_mails(event: int, user: int, subject: dict, message: dict, orders: list) -> None:
    failures = []
    event = Event.objects.get(pk=event)
    user = User.objects.get(pk=user) if user else None
    orders = Order.objects.filter(pk__in=orders)
    subject = LazyI18nString(subject)
    message = LazyI18nString(message)
    tz = pytz.timezone(event.settings.timezone)

    for o in orders:
        try:
            invoice_name = o.invoice_address.name
            invoice_company = o.invoice_address.company
        except InvoiceAddress.DoesNotExist:
            invoice_name = ""
            invoice_company = ""
        try:
            with language(o.locale):
                email_context = {
                    'event': o.event,
                    'code': o.code,
                    'date': date_format(o.datetime.astimezone(tz), 'SHORT_DATETIME_FORMAT'),
                    'expire_date': date_format(o.expires, 'SHORT_DATE_FORMAT'),
                    'url': build_absolute_uri(event, 'presale:event.order', kwargs={
                        'order': o.code,
                        'secret': o.secret
                    }),
                    'invoice_name': invoice_name,
                    'invoice_company': invoice_company,
                }
                mail(
                    o.email,
                    subject,
                    message,
                    email_context,
                    event,
                    locale=o.locale,
                    order=o
                )
                o.log_action(
                    'pretix.plugins.sendmail.order.email.sent',
                    user=user,
                    data={
                        'subject': subject.localize(o.locale).format_map(email_context),
                        'message': message.localize(o.locale).format_map(email_context),
                        'recipient': o.email
                    }
                )
        except SendMailException:
            failures.append(o.email)
Esempio n. 25
0
def _perform_order(event: str, payment_provider: str, position_ids: List[str],
                   email: str, locale: str, address: int):

    event = Event.objects.get(id=event)
    responses = register_payment_providers.send(event)
    pprov = None
    for rec, response in responses:
        provider = response(event)
        if provider.identifier == payment_provider:
            pprov = provider
    if not pprov:
        raise OrderError(error_messages['internal'])

    with event.lock() as now_dt:
        positions = list(CartPosition.objects.filter(
            id__in=position_ids).select_related('item', 'variation'))
        if len(position_ids) != len(positions):
            raise OrderError(error_messages['internal'])
        _check_positions(event, now_dt, positions)
        order = _create_order(event, email, positions, now_dt, pprov,
                              locale=locale, address=address)

    if event.settings.get('invoice_generate') == 'True' and invoice_qualified(order):
        if not order.invoices.exists():
            generate_invoice(order)

    with language(order.locale):
        if order.total == Decimal('0.00'):
            mailtext = event.settings.mail_text_order_free
        else:
            mailtext = event.settings.mail_text_order_placed
        mail(
            order.email, _('Your order: %(code)s') % {'code': order.code},
            mailtext,
            {
                'total': LazyNumber(order.total),
                'currency': event.currency,
                'date': LazyDate(order.expires),
                'event': event.name,
                'url': build_absolute_uri(event, 'presale:event.order', kwargs={
                    'order': order.code,
                    'secret': order.secret
                }),
                'paymentinfo': str(pprov.order_pending_mail_render(order))
            },
            event, locale=order.locale
        )

    return order.id
Esempio n. 26
0
def generate_order(order: int, provider: str):
    order = Order.objects.select_related('event').get(id=order)

    with language(order.locale):
        responses = register_ticket_outputs.send(order.event)
        for receiver, response in responses:
            prov = response(order.event)
            if prov.identifier == provider:
                filename, ttype, data = prov.generate_order(order)
                path, ext = os.path.splitext(filename)
                for ct in CachedCombinedTicket.objects.filter(order=order, provider=provider):
                    ct.delete()
                ct = CachedCombinedTicket.objects.create(order=order, provider=provider, extension=ext,
                                                         type=ttype, file=None)
                ct.file.save(filename, ContentFile(data))
                return ct.pk
Esempio n. 27
0
    def wrapped_view(request, *args, **kwargs):
        if 'iframe' in request.GET:
            request.session['iframe_session'] = True

        locale = request.GET.get('locale')
        if locale and locale in [lc for lc, ll in settings.LANGUAGES]:
            with language(locale):
                resp = view_func(request, *args, **kwargs)
            max_age = 10 * 365 * 24 * 60 * 60
            resp.set_cookie(settings.LANGUAGE_COOKIE_NAME, locale, max_age=max_age,
                            expires=(datetime.utcnow() + timedelta(seconds=max_age)).strftime('%a, %d-%b-%Y %H:%M:%S GMT'),
                            domain=settings.SESSION_COOKIE_DOMAIN)
            return resp

        resp = view_func(request, *args, **kwargs)
        return resp
Esempio n. 28
0
 def post(self, *args, **kwargs):
     with language(self.order.locale):
         mail(
             self.order.email, _('Your order: %(code)s') % {'code': self.order.code},
             self.order.event.settings.mail_text_resend_link,
             {
                 'event': self.order.event.name,
                 'url': build_absolute_uri(self.order.event, 'presale:event.order', kwargs={
                     'order': self.order.code,
                     'secret': self.order.secret
                 }),
             },
             self.order.event, locale=self.order.locale
         )
     messages.success(self.request, _('The email has been queued to be sent.'))
     self.order.log_action('pretix.event.order.resend', user=self.request.user)
     return redirect(self.get_order_url())
Esempio n. 29
0
def generate_widget_js(lang):
    code = []
    with language(lang):
        # Provide isolation
        code.append('(function (siteglobals) {\n')
        code.append('var module = {}, exports = {};\n')
        code.append('var lang = "%s";\n' % lang)

        c = JavaScriptCatalog()
        c.translation = DjangoTranslation(lang, domain='djangojs')
        catalog, plural = c.get_catalog(), c.get_plural()

        str_wl = (
            'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su',
            'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August',
            'September', 'October', 'November', 'December'
        )
        catalog = dict((k, v) for k, v in catalog.items() if k.startswith('widget\u0004') or k in str_wl)
        template = Engine().from_string(js_catalog_template)
        context = Context({
            'catalog_str': indent(json.dumps(
                catalog, sort_keys=True, indent=2)) if catalog else None,
            'formats_str': indent(json.dumps(
                get_formats(), sort_keys=True, indent=2)),
            'plural': plural,
        })
        code.append(template.render(context))

        files = [
            'vuejs/vue.js' if settings.DEBUG else 'vuejs/vue.min.js',
            'vuejs/vue-resize.min.js',
            'pretixpresale/js/widget/docready.js',
            'pretixpresale/js/widget/floatformat.js',
            'pretixpresale/js/widget/widget.js',
        ]
        for fname in files:
            f = finders.find(fname)
            with open(f, 'r') as fp:
                code.append(fp.read())

        if settings.DEBUG:
            code.append('})(this);\n')
        else:
            # Do not expose debugging variables
            code.append('})({});\n')
    return ''.join(code)
Esempio n. 30
0
def clear_cart(self, event: int, cart_id: str=None, locale='en') -> None:
    """
    Removes a list of items from a user's cart.
    :param event: The event ID in question
    :param session: Session ID of a guest
    """
    with language(locale):
        event = Event.objects.get(id=event)
        try:
            try:
                cm = CartManager(event=event, cart_id=cart_id)
                cm.clear()
                cm.commit()
            except LockTimeoutException:
                self.retry()
        except (MaxRetriesExceededError, LockTimeoutException):
            raise CartError(error_messages['busy'])
Esempio n. 31
0
    def wrapped_view(request, *args, **kwargs):
        if 'iframe' in request.GET:
            request.session['iframe_session'] = True

        locale = request.GET.get('locale')
        if locale and locale in [lc for lc, ll in settings.LANGUAGES]:
            with language(locale):
                resp = view_func(request, *args, **kwargs)
            max_age = 10 * 365 * 24 * 60 * 60
            resp.set_cookie(
                settings.LANGUAGE_COOKIE_NAME,
                locale,
                max_age=max_age,
                expires=(datetime.utcnow() + timedelta(seconds=max_age)
                         ).strftime('%a, %d-%b-%Y %H:%M:%S GMT'),
                domain=settings.SESSION_COOKIE_DOMAIN)
            return resp

        resp = view_func(request, *args, **kwargs)
        return resp
Esempio n. 32
0
def generate_order(order: int, provider: str):
    order = Order.objects.select_related('event').get(id=order)

    with language(order.locale):
        responses = register_ticket_outputs.send(order.event)
        for receiver, response in responses:
            prov = response(order.event)
            if prov.identifier == provider:
                filename, ttype, data = prov.generate_order(order)
                path, ext = os.path.splitext(filename)
                for ct in CachedCombinedTicket.objects.filter(
                        order=order, provider=provider):
                    ct.delete()
                ct = CachedCombinedTicket.objects.create(order=order,
                                                         provider=provider,
                                                         extension=ext,
                                                         type=ttype,
                                                         file=None)
                ct.file.save(filename, ContentFile(data))
                return ct.pk
Esempio n. 33
0
def send_notification(logentry_id: int, action_type: str, user_id: int,
                      method: str):
    logentry = LogEntry.all.get(id=logentry_id)
    if logentry.event:
        sm = lambda: scope(organizer=logentry.event.organizer)  # noqa
    else:
        sm = lambda: scopes_disabled()  # noqa
    with sm():
        user = User.objects.get(id=user_id)
        types = get_all_notification_types(logentry.event)
        notification_type = types.get(action_type)
        if not notification_type:
            return  # Ignore, e.g. plugin not active for this event

        with language(user.locale), override(
                logentry.event.timezone if logentry.event else user.timezone):
            notification = notification_type.build_notification(logentry)

            if method == "mail":
                send_notification_mail(notification, user)
Esempio n. 34
0
    def send_mail(self, subject: str, template: Union[str, LazyI18nString],
                  context: Dict[str, Any]=None, log_entry_type: str='pretix.event.order.email.sent',
                  user: User=None, headers: dict=None, sender: str=None):
        """
        Sends an email to the user that placed this order. Basically, this method does two things:

        * Call ``pretix.base.services.mail.mail`` with useful values for the ``event``, ``locale``, ``recipient`` and
          ``order`` parameters.

        * Create a ``LogEntry`` with the email contents.

        :param subject: Subject of the email
        :param template: LazyI18nString or template filename, see ``pretix.base.services.mail.mail`` for more details
        :param context: Dictionary to use for rendering the template
        :param log_entry_type: Key to be used for the log entry
        :param user: Administrative user who triggered this mail to be sent
        :param headers: Dictionary with additional mail headers
        :param sender: Custom email sender.
        """
        from pretix.base.services.mail import SendMailException, mail, render_mail

        recipient = self.email
        email_content = render_mail(template, context)[0]
        try:
            with language(self.locale):
                mail(
                    recipient, subject, template, context,
                    self.event, self.locale, self, headers, sender
                )
        except SendMailException:
            raise
        else:
            self.log_action(
                log_entry_type,
                user=user,
                data={
                    'subject': subject,
                    'message': email_content,
                    'recipient': recipient
                }
            )
Esempio n. 35
0
def _cancel_order(order, user=None, send_mail: bool=True):
    """
    Mark this order as canceled
    :param order: The order to change
    :param user: The user that performed the change
    """
    if isinstance(order, int):
        order = Order.objects.get(pk=order)
    if isinstance(user, int):
        user = User.objects.get(pk=user)
    with order.event.lock():
        if order.status != Order.STATUS_PENDING:
            raise OrderError(_('You cannot cancel this order.'))
        order.status = Order.STATUS_CANCELED
        order.save()

    order.log_action('pretix.event.order.canceled', user=user)
    i = order.invoices.filter(is_cancellation=False).last()
    if i:
        generate_cancellation(i)

    for position in order.positions.all():
        if position.voucher:
            Voucher.objects.filter(pk=position.voucher.pk).update(redeemed=F('redeemed') - 1)

    if send_mail:
        with language(order.locale):
            mail(
                order.email, _('Order canceled: %(code)s') % {'code': order.code},
                order.event.settings.mail_text_order_canceled,
                {
                    'event': order.event.name,
                    'code': order.code,
                    'url': build_absolute_uri(order.event, 'presale:event.order', kwargs={
                        'order': order.code,
                        'secret': order.secret
                    })
                },
                order.event, locale=order.locale
            )
    return order.pk
Esempio n. 36
0
    def form_valid(self, form):
        self.output = {}

        if self.request.POST.get("action") == "preview":
            for l in self.request.event.settings.locales:
                with language(l, self.request.event.settings.region):
                    context_dict = TolerantDict()
                    for k, v in get_available_placeholders(self.request.event, ['event', 'order',
                                                                                'position_or_address']).items():
                        context_dict[k] = '<span class="placeholder" title="{}">{}</span>'.format(
                            _('This value will be replaced based on dynamic parameters.'),
                            v.render_sample(self.request.event)
                        )

                    subject = bleach.clean(form.cleaned_data['subject'].localize(l), tags=[])
                    preview_subject = subject.format_map(context_dict)
                    template = form.cleaned_data['template'].localize(l)
                    preview_text = markdown_compile_email(template.format_map(context_dict))

                    self.output[l] = {
                        'subject': _('Subject: {subject}').format(subject=preview_subject),
                        'html': preview_text,
                    }

            return self.get(self.request, *self.args, **self.kwargs)

        messages.success(self.request, _('Your rule has been created.'))

        form.instance.event = self.request.event

        with transaction.atomic():
            self.object = form.save()
            form.instance.log_action('pretix.plugins.sendmail.rule.added', user=self.request.user,
                                     data=dict(form.cleaned_data))

        return redirect(
            'plugins:sendmail:rule.update',
            event=self.request.event.slug,
            organizer=self.request.event.organizer.slug,
            rule=self.object.pk,
        )
Esempio n. 37
0
File: order.py Progetto: ligi/pretix
    def to_representation(self, instance: OrderPosition):
        res = {}

        ev = instance.subevent or instance.order.event
        with language(instance.order.locale):
            # This needs to have some extra performance improvements to avoid creating hundreds of queries when
            # we serialize a list.

            if 'vars' not in self.context:
                self.context['vars'] = get_variables(self.context['request'].event)

            for k, f in self.context['vars'].items():
                res[k] = f['evaluate'](instance, instance.order, ev)

            if not hasattr(ev, '_cached_meta_data'):
                ev._cached_meta_data = ev.meta_data

            for k, v in ev._cached_meta_data.items():
                res['meta:' + k] = v

        return res
Esempio n. 38
0
    def dispatch(self, request, *args, **kwargs):
        self.subevent = None
        if request.event.has_subevents:
            if 'subevent' in kwargs:
                self.subevent = request.event.subevents.filter(
                    pk=kwargs['subevent'], active=True).first()
                if not self.subevent:
                    raise Http404()
            else:
                raise Http404()
        else:
            if 'subevent' in kwargs:
                raise Http404()

        if 'lang' in request.GET and request.GET.get('lang') in [
                lc for lc, ll in settings.LANGUAGES
        ]:
            with language(request.GET.get('lang')):
                return super().dispatch(request, *args, **kwargs)
        else:
            return super().dispatch(request, *args, **kwargs)
Esempio n. 39
0
    def generate_order(self, order: Order):
        merger = PdfFileMerger()
        with language(order.locale):
            for op in order.positions_with_tickets:
                layout = override_layout.send_chained(
                    order.event,
                    'layout',
                    orderposition=op,
                    layout=self.layout_map.get(
                        (op.item_id, order.sales_channel),
                        self.layout_map.get((op.item_id, 'web'),
                                            self.default_layout)))
                outbuffer = self._draw_page(layout, op, order)
                merger.append(ContentFile(outbuffer.read()))

        outbuffer = BytesIO()
        merger.write(outbuffer)
        merger.close()
        outbuffer.seek(0)
        return 'order%s%s.pdf' % (
            self.event.slug, order.code), 'application/pdf', outbuffer.read()
Esempio n. 40
0
def multiexport(organizer: Organizer, user: User, fileid: str, provider: str,
                form_data: Dict[str, Any]) -> None:
    file = CachedFile.objects.get(id=fileid)
    with language(user.locale), override(user.timezone):
        allowed_events = user.get_events_with_permission('can_view_orders')

        events = allowed_events.filter(pk__in=form_data.get('events'))
        responses = register_multievent_data_exporters.send(organizer)

        for receiver, response in responses:
            ex = response(events)
            if ex.identifier == provider:
                d = ex.render(form_data)
                if d is None:
                    raise ExportError(
                        gettext('Your export did not contain any data.'))
                file.filename, file.type, data = d
                file.file.save(cachedfile_name(file, file.filename),
                               ContentFile(data))
                file.save()
    return file.pk
Esempio n. 41
0
def export(self, event: Event, fileid: str, provider: str,
           form_data: Dict[str, Any]) -> None:
    def set_progress(val):
        if not self.request.called_directly:
            self.update_state(state='PROGRESS', meta={'value': val})

    file = CachedFile.objects.get(id=fileid)
    with language(event.settings.locale), override(event.settings.timezone):
        responses = register_data_exporters.send(event)
        for receiver, response in responses:
            ex = response(event, set_progress)
            if ex.identifier == provider:
                d = ex.render(form_data)
                if d is None:
                    raise ExportError(
                        gettext('Your export did not contain any data.'))
                file.filename, file.type, data = d
                file.file.save(cachedfile_name(file, file.filename),
                               ContentFile(data))
                file.save()
    return file.pk
Esempio n. 42
0
    def _get_text_content(self, op: OrderPosition, order: Order, o: dict, inner=False):
        if o.get('locale', None) and not inner:
            with language(o['locale']):
                return self._get_text_content(op, order, o, True)

        ev = self._get_ev(op, order)
        if not o['content']:
            return '(error)'
        if o['content'] == 'other':
            return o['text']
        elif o['content'].startswith('itemmeta:'):
            return op.item.meta_data.get(o['content'][9:]) or ''
        elif o['content'].startswith('meta:'):
            return ev.meta_data.get(o['content'][5:]) or ''
        elif o['content'] in self.variables:
            try:
                return self.variables[o['content']]['evaluate'](op, order, ev)
            except:
                logger.exception('Failed to process variable.')
                return '(error)'
        return ''
Esempio n. 43
0
    def send_security_notice(self, messages, email=None):
        from pretix.base.services.mail import mail, SendMailException

        try:
            with language(self.locale):
                msg = '- ' + '\n- '.join(str(m) for m in messages)

            mail(
                email or self.email,
                _('Account information changed'),
                'pretixcontrol/email/security_notice.txt',
                {
                    'user': self,
                    'messages': msg,
                    'url': build_absolute_uri('control:user.settings')
                },
                event=None,
                locale=self.locale
            )
        except SendMailException:
            pass  # Already logged
Esempio n. 44
0
def generate_widget_js(lang):
    code = []
    with language(lang):
        # Provide isolation
        code.append('(function (siteglobals) {\n')
        code.append('var module = {}, exports = {};\n')
        code.append('var lang = "%s";\n' % lang)

        catalog, plural = get_javascript_catalog(lang, 'djangojs', ['pretix'])
        catalog = dict(
            (k, v) for k, v in catalog.items() if k.startswith('widget\u0004'))
        template = Engine().from_string(js_catalog_template)
        context = Context({
            'catalog_str':
            indent(json.dumps(catalog, sort_keys=True, indent=2))
            if catalog else None,
            'formats_str':
            indent(json.dumps(get_formats(), sort_keys=True, indent=2)),
            'plural':
            plural,
        })
        code.append(template.render(context))

        files = [
            'vuejs/vue.js' if settings.DEBUG else 'vuejs/vue.min.js',
            'pretixpresale/js/widget/docready.js',
            'pretixpresale/js/widget/floatformat.js',
            'pretixpresale/js/widget/widget.js',
        ]
        for fname in files:
            f = finders.find(fname)
            with open(f, 'r') as fp:
                code.append(fp.read())

        if settings.DEBUG:
            code.append('})(this);\n')
        else:
            # Do not expose debugging variables
            code.append('})({});\n')
    return ''.join(code)
Esempio n. 45
0
    def post(self, *args, **kwargs):
        with language(self.order.locale):
            try:
                try:
                    invoice_name = self.order.invoice_address.name
                    invoice_company = self.order.invoice_address.company
                except InvoiceAddress.DoesNotExist:
                    invoice_name = ""
                    invoice_company = ""
                mail(self.order.email,
                     _('Your order: %(code)s') % {'code': self.order.code},
                     self.order.event.settings.mail_text_resend_link, {
                         'event':
                         self.order.event.name,
                         'url':
                         build_absolute_uri(self.order.event,
                                            'presale:event.order',
                                            kwargs={
                                                'order': self.order.code,
                                                'secret': self.order.secret
                                            }),
                         'invoice_name':
                         invoice_name,
                         'invoice_company':
                         invoice_company,
                     },
                     self.order.event,
                     locale=self.order.locale)
            except SendMailException:
                messages.error(
                    self.request,
                    _('There was an error sending the mail. Please try again later.'
                      ))
                return redirect(self.get_order_url())

        messages.success(self.request,
                         _('The email has been queued to be sent.'))
        self.order.log_action('pretix.event.order.resend',
                              user=self.request.user)
        return redirect(self.get_order_url())
Esempio n. 46
0
def preview(event: int, provider: str):
    event = Event.objects.get(id=event)

    with rolledback_transaction(), language(event.settings.locale):
        item = event.items.create(name=_("Sample product"),
                                  default_price=42.23,
                                  description=_("Sample product description"))
        item2 = event.items.create(name=_("Sample workshop"),
                                   default_price=23.40)

        from pretix.base.models import Order
        order = event.orders.create(status=Order.STATUS_PENDING,
                                    datetime=now(),
                                    email='*****@*****.**',
                                    locale=event.settings.locale,
                                    expires=now(),
                                    code="PREVIEW1234",
                                    total=119)

        p = order.positions.create(item=item,
                                   attendee_name=_("John Doe"),
                                   price=item.default_price)
        order.positions.create(item=item2,
                               attendee_name=_("John Doe"),
                               price=item.default_price,
                               addon_to=p)
        order.positions.create(item=item2,
                               attendee_name=_("John Doe"),
                               price=item.default_price,
                               addon_to=p)

        InvoiceAddress.objects.create(order=order,
                                      name=_("John Doe"),
                                      company=_("Sample company"))

        responses = register_ticket_outputs.send(event)
        for receiver, response in responses:
            prov = response(event)
            if prov.identifier == provider:
                return prov.generate(p)
Esempio n. 47
0
def generate_order(order: int, provider: str):
    order = Order.objects.select_related('event').get(id=order)
    try:
        ct = CachedCombinedTicket.objects.get(order=order, provider=provider)
    except CachedCombinedTicket.MultipleObjectsReturned:
        CachedCombinedTicket.objects.filter(order=order, provider=provider).delete()
        ct = CachedCombinedTicket.objects.create(order=order, provider=provider, extension='',
                                                 type='', file=None)
    except CachedCombinedTicket.DoesNotExist:
        ct = CachedCombinedTicket.objects.create(order=order, provider=provider, extension='',
                                                 type='', file=None)

    with language(order.locale):
        responses = register_ticket_outputs.send(order.event)
        for receiver, response in responses:
            prov = response(order.event)
            if prov.identifier == provider:
                filename, ct.type, data = prov.generate_order(order)
                path, ext = os.path.splitext(filename)
                ct.extension = ext
                ct.save()
                ct.file.save(filename, ContentFile(data))
Esempio n. 48
0
    def handle(self, *args, **options):
        try:
            o = Organizer.objects.get(slug=options['organizer_slug'][0])
        except Organizer.DoesNotExist:
            self.stderr.write(self.style.ERROR('Organizer not found.'))
            sys.exit(1)

        with scope(organizer=o):
            try:
                e = o.events.get(slug=options['event_slug'][0])
            except Event.DoesNotExist:
                self.stderr.write(self.style.ERROR('Event not found.'))
                sys.exit(1)

            with language(e.settings.locale), override(e.settings.timezone):
                responses = register_data_exporters.send(e)
                for receiver, response in responses:
                    ex = response(e)
                    if ex.identifier == options['export_provider'][0]:
                        params = json.loads(options.get('parameters') or '{}')
                        with open(options['output_file'][0], 'wb') as f:
                            try:
                                ex.render(form_data=params, output_file=f)
                            except TypeError:
                                self.stderr.write(
                                    self.style.WARNING(
                                        'Provider does not support direct file writing, need to buffer export in memory.'
                                    ))
                                d = ex.render(form_data=params)
                                if d is None:
                                    self.stderr.write(
                                        self.style.ERROR('Empty export.'))
                                    sys.exit(2)
                                f.write(d[2])

                            sys.exit(0)

            self.stderr.write(self.style.ERROR('Export provider not found.'))
            sys.exit(1)
Esempio n. 49
0
    def generate_order(self, order: Order):
        merger = PdfFileMerger()
        with language(order.locale):
            for op in order.positions.all():
                if op.addon_to_id and not self.event.settings.ticket_download_addons:
                    continue
                if not op.item.admission and not self.event.settings.ticket_download_nonadm:
                    continue

                buffer = BytesIO()
                p = self._create_canvas(buffer)
                layout = self.layout_map.get(op.item_id, self.default_layout)
                self._draw_page(layout, p, op, order)
                p.save()
                outbuffer = self._render_with_background(layout, buffer)
                merger.append(ContentFile(outbuffer.read()))

        outbuffer = BytesIO()
        merger.write(outbuffer)
        merger.close()
        outbuffer.seek(0)
        return 'order%s%s.pdf' % (self.event.slug, order.code), 'application/pdf', outbuffer.read()
Esempio n. 50
0
def set_cart_addons(self,
                    event: int,
                    addons: List[dict],
                    cart_id: str = None,
                    locale='en') -> None:
    """
    Removes a list of items from a user's cart.
    :param event: The event ID in question
    :param addons: A list of dicts with the keys addon_to, item, variation
    :param session: Session ID of a guest
    """
    with language(locale):
        event = Event.objects.get(id=event)
        try:
            try:
                cm = CartManager(event=event, cart_id=cart_id)
                cm.set_addons(addons)
                cm.commit()
            except LockTimeoutException:
                self.retry()
        except (MaxRetriesExceededError, LockTimeoutException):
            raise CartError(error_messages['busy'])
Esempio n. 51
0
def notify_incomplete_payment(o: Order):
    with language(o.locale):
        tz = pytz.timezone(o.event.settings.get('timezone',
                                                settings.TIME_ZONE))
        try:
            invoice_name = o.invoice_address.name
            invoice_company = o.invoice_address.company
        except InvoiceAddress.DoesNotExist:
            invoice_name = ""
            invoice_company = ""
        email_template = o.event.settings.mail_text_order_expire_warning
        email_context = {
            'event':
            o.event.name,
            'url':
            build_absolute_uri(o.event,
                               'presale:event.order.open',
                               kwargs={
                                   'order': o.code,
                                   'secret': o.secret,
                                   'hash': o.email_confirm_hash()
                               }),
            'expire_date':
            date_format(o.expires.astimezone(tz), 'SHORT_DATE_FORMAT'),
            'invoice_name':
            invoice_name,
            'invoice_company':
            invoice_company,
        }
        email_subject = ugettext(
            'Your order received an incomplete payment: %(code)s') % {
                'code': o.code
            }

        try:
            o.send_mail(email_subject, email_template, email_context,
                        'pretix.event.order.email.expire_warning_sent')
        except SendMailException:
            logger.exception('Reminder email could not be sent')
Esempio n. 52
0
    def get(self, request, *args, **kwargs):
        events = list(
            filter_qs_by_attr(
                self.request.organizer.events.filter(is_public=True, live=True, has_subevents=False),
                request
            ).order_by(
                'date_from'
            ).prefetch_related(
                '_settings_objects', 'organizer___settings_objects'
            )
        )
        events += list(
            filter_qs_by_attr(
                SubEvent.objects.filter(
                    event__organizer=self.request.organizer,
                    event__is_public=True,
                    event__live=True,
                    is_public=True,
                    active=True
                ),
                request
            ).prefetch_related(
                'event___settings_objects', 'event__organizer___settings_objects'
            ).order_by(
                'date_from'
            )
        )

        if 'locale' in request.GET and request.GET.get('locale') in dict(settings.LANGUAGES):
            with language(request.GET.get('locale')):
                cal = get_ical(events)
        else:
            cal = get_ical(events)

        resp = HttpResponse(cal.serialize(), content_type='text/calendar')
        resp['Content-Disposition'] = 'attachment; filename="{}.ics"'.format(
            request.organizer.slug
        )
        return resp
Esempio n. 53
0
def remove_cart_position(self,
                         event: int,
                         position: int,
                         cart_id: str = None,
                         locale='en') -> None:
    """
    Removes a list of items from a user's cart.
    :param event: The event ID in question
    :param position: A cart position ID
    :param session: Session ID of a guest
    """
    with language(locale):
        event = Event.objects.get(id=event)
        try:
            try:
                cm = CartManager(event=event, cart_id=cart_id)
                cm.remove_item(position)
                cm.commit()
            except LockTimeoutException:
                self.retry()
        except (MaxRetriesExceededError, LockTimeoutException):
            raise CartError(error_messages['busy'])
Esempio n. 54
0
 def post(self, *args, **kwargs):
     with language(self.order.locale):
         mail(self.order.email,
              _('Your order: %(code)s') % {'code': self.order.code},
              self.order.event.settings.mail_text_resend_link, {
                  'event':
                  self.order.event.name,
                  'url':
                  build_absolute_uri(self.order.event,
                                     'presale:event.order',
                                     kwargs={
                                         'order': self.order.code,
                                         'secret': self.order.secret
                                     }),
              },
              self.order.event,
              locale=self.order.locale)
     messages.success(self.request,
                      _('The email has been queued to be sent.'))
     self.order.log_action('pretix.event.order.resend',
                           user=self.request.user)
     return redirect(self.get_order_url())
Esempio n. 55
0
 def _notify_user(self):
     with language(self.order.locale):
         try:
             invoice_name = self.order.invoice_address.name
             invoice_company = self.order.invoice_address.company
         except InvoiceAddress.DoesNotExist:
             invoice_name = ""
             invoice_company = ""
         mail(
             self.order.email, _('Your order has been changed: %(code)s') % {'code': self.order.code},
             self.order.event.settings.mail_text_order_changed,
             {
                 'event': self.order.event.name,
                 'url': build_absolute_uri(self.order.event, 'presale:event.order', kwargs={
                     'order': self.order.code,
                     'secret': self.order.secret
                 }),
                 'invoice_name': invoice_name,
                 'invoice_company': invoice_company,
             },
             self.order.event, locale=self.order.locale
         )
Esempio n. 56
0
def add_items_to_cart(self,
                      event: int,
                      items: List[dict],
                      cart_id: str = None,
                      locale='en',
                      invoice_address: int = None,
                      widget_data=None,
                      sales_channel='web') -> None:
    """
    Adds a list of items to a user's cart.
    :param event: The event ID in question
    :param items: A list of dicts with the keys item, variation, number, custom_price, voucher
    :param cart_id: Session ID of a guest
    :raises CartError: On any error that occured
    """
    with language(locale):
        event = Event.objects.get(id=event)

        ia = False
        if invoice_address:
            try:
                ia = InvoiceAddress.objects.get(pk=invoice_address)
            except InvoiceAddress.DoesNotExist:
                pass

        try:
            try:
                cm = CartManager(event=event,
                                 cart_id=cart_id,
                                 invoice_address=ia,
                                 widget_data=widget_data,
                                 sales_channel=sales_channel)
                cm.add_new_items(items)
                cm.commit()
            except LockTimeoutException:
                self.retry()
        except (MaxRetriesExceededError, LockTimeoutException):
            raise CartError(error_messages['busy'])
Esempio n. 57
0
def send_mails(event: Event, user: int, recipients: list, vouchers: dict,
               subject: dict, message: dict) -> None:
    failures = []
    user = User.objects.get(pk=user) if user else None
    subject = LazyI18nString(subject)
    message = LazyI18nString(message)

    # Some hacks to reverse the JSON serialization
    vouchers[None] = vouchers['null']
    vouchers.pop('null')
    for l, vs in vouchers.items():
        tmp = []
        for d in vs:
            for t, d2 in d.items():
                d[t] = DictHelper(d2)
            tmp.append(DictHelper(d))
        vouchers[l] = tmp

    for r in recipients:
        if isinstance(r, tuple):
            locale, email_address = r
        else:
            locale = None
            email_address = r
        try:
            with language(locale):
                email_context = {
                    'event': event,
                    'voucher': vouchers[locale].pop()
                }
                mail(email_address,
                     subject,
                     message,
                     email_context,
                     event,
                     locale=locale)
        except SendMailException:
            failures.append(email_address)
Esempio n. 58
0
def send_invoices_to_organizer(sender, **kwargs):
    from pretix.base.services.mail import mail

    batch_size = 50
    # this adds some rate limiting on the number of invoices to send at the same time. If there's more, the next
    # cronjob will handle them
    max_number_of_batches = 10

    for i in range(max_number_of_batches):
        with transaction.atomic():
            qs = Invoice.objects.filter(
                sent_to_organizer__isnull=True).prefetch_related(
                    'event').select_for_update(skip_locked=True)
            for i in qs[:batch_size]:
                if i.event.settings.invoice_email_organizer:
                    with language(i.event.settings.locale):
                        mail(
                            email=i.event.settings.invoice_email_organizer,
                            subject=_('New invoice: {number}').format(
                                number=i.number),
                            template=LazyI18nString.from_gettext(
                                _('Hello,\n\n'
                                  'a new invoice for {event} has been created, see attached.\n\n'
                                  'We are sending this email because you configured us to do so in your event settings.'
                                  )),
                            context={
                                'event': str(i.event),
                            },
                            locale=i.event.settings.locale,
                            event=i.event,
                            invoices=[i],
                            auto_email=True,
                        )
                    i.sent_to_organizer = True
                    i.save(update_fields=['sent_to_organizer'])
                else:
                    i.sent_to_organizer = False
                i.save(update_fields=['sent_to_organizer'])
Esempio n. 59
0
def render_pdf(event, positions):
    Renderer._register_fonts()

    renderermap = {
        bi.item_id: _renderer(event, bi.layout)
        for bi in BadgeItem.objects.select_related('layout').filter(
            item__event=event)
    }
    try:
        default_renderer = _renderer(event,
                                     event.badge_layouts.get(default=True))
    except BadgeLayout.DoesNotExist:
        default_renderer = None
    merger = PdfFileMerger()

    any = False
    for op in positions:
        r = renderermap.get(op.item_id, default_renderer)
        if not r:
            continue
        any = True

        with language(op.order.locale):
            buffer = BytesIO()
            p = canvas.Canvas(buffer, pagesize=pagesizes.A4)
            r.draw_page(p, op.order, op)
            p.save()
            outbuffer = r.render_background(buffer, 'Badge')
            merger.append(ContentFile(outbuffer.read()))

    outbuffer = BytesIO()
    merger.write(outbuffer)
    merger.close()
    outbuffer.seek(0)
    if not any:
        raise OrderError(
            _("None of the selected products is configured to print badges."))
    return outbuffer
Esempio n. 60
0
def preview(event: int, provider: str):
    event = Event.objects.get(id=event)

    with rolledback_transaction(), language(event.settings.locale):
        item = event.items.create(name=_("Sample product"),
                                  default_price=42.23)

        order = event.orders.create(status=Order.STATUS_PENDING,
                                    datetime=now(),
                                    email='*****@*****.**',
                                    expires=now(),
                                    code="PREVIEW1234",
                                    total=119)

        p = order.positions.create(item=item,
                                   attendee_name=_("John Doe"),
                                   price=item.default_price)

        responses = register_ticket_outputs.send(event)
        for receiver, response in responses:
            prov = response(event)
            if prov.identifier == provider:
                return prov.generate(p)