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()
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
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)
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'])
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'])
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()
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')
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)
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
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)
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 )
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
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
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
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()
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
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)
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
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()
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()
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()
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 )
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)
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
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
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
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())
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)
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'])
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
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
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)
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 } )
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
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, )
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
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)
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()
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
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
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 ''
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
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)
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())
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)
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))
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)
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()
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'])
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')
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
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'])
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())
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 )
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'])
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)
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'])
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
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)