def test_invoice_create_duplicate(self): self.event.settings.set('invoice_generate', 'user') generate_invoice(self.order) response = self.client.post( '/%s/%s/order/%s/%s/invoice' % (self.orga.slug, self.event.slug, self.order.code, self.order.secret), {}, follow=True) assert 'alert-danger' in response.rendered_content
def test_invoice_create_wrong_secret(self): self.event.settings.set('invoice_generate', 'user') generate_invoice(self.order) response = self.client.post( '/%s/%s/order/%s/%s/invoice' % (self.orga.slug, self.event.slug, self.order.code, '1234'), {}) assert 404 == response.status_code
def post(self, request, *args, **kwargs): self.request = request for p in self.provider_forms: if p['provider'].identifier == request.POST.get('payment', ''): request.session['payment'] = p['provider'].identifier request.session['payment_change_{}'.format(self.order.pk)] = '1' resp = p['provider'].order_prepare(request, self.order) if resp: with transaction.atomic(): new_fee = p['provider'].calculate_fee(self._total_order_value) self.order.log_action('pretix.event.order.payment.changed', { 'old_fee': self.order.payment_fee, 'new_fee': new_fee, 'old_provider': self.order.payment_provider, 'new_provider': p['provider'].identifier }) self.order.payment_provider = p['provider'].identifier self.order.payment_fee = new_fee self.order.total = self._total_order_value + new_fee self.order._calculate_tax() self.order.save() i = self.order.invoices.filter(is_cancellation=False).last() if i: generate_cancellation(i) generate_invoice(self.order) if isinstance(resp, str): return redirect(resp) elif resp is True: return redirect(self.get_confirm_url()) else: return self.get(request, *args, **kwargs) messages.error(self.request, _("Please select a payment method.")) return self.get(request, *args, **kwargs)
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 post(self, *args, **kwargs): if self.request.event.settings.get('invoice_generate') not in ('admin', 'user'): messages.error(self.request, _('You cannot generate an invoice for this order.')) elif self.order.invoices.exists(): messages.error(self.request, _('An invoice for this order already exists.')) else: generate_invoice(self.order) self.order.log_action('pretix.event.order.invoice.generate', user=self.request.user) messages.success(self.request, _('The invoice has been generated.')) return redirect(self.get_order_url())
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 create_invoice(self, request, **kwargs): order = self.get_object() has_inv = order.invoices.exists() and not ( order.status in (Order.STATUS_PAID, Order.STATUS_PENDING) and order.invoices.filter(is_cancellation=True).count() >= order.invoices.filter(is_cancellation=False).count() ) if self.request.event.settings.get('invoice_generate') not in ('admin', 'user', 'paid', 'True') or not invoice_qualified(order): return Response( {'detail': _('You cannot generate an invoice for this order.')}, status=status.HTTP_400_BAD_REQUEST ) elif has_inv: return Response( {'detail': _('An invoice for this order already exists.')}, status=status.HTTP_400_BAD_REQUEST ) inv = generate_invoice(order) order.log_action( 'pretix.event.order.invoice.generated', user=self.request.user, auth=self.request.auth, data={ 'invoice': inv.pk } ) return Response( InvoiceSerializer(inv).data, status=status.HTTP_201_CREATED )
def test_address(env): event, order = env event.settings.set('invoice_language', 'en') InvoiceAddress.objects.create(company='Acme Company', street='221B Baker Street', zipcode='12345', city='London', country='UK', order=order) inv = generate_invoice(order) assert inv.invoice_to == "Acme Company\n\n221B Baker Street\n12345 London\nUK"
def test_pdf_generation_custom_text(env): event, order = env event.settings.set('invoice_introductory_text', 'introductory invoice text') # set a really long additional text, to make the invoice span two pages event.settings.set('invoice_additional_text', 'additional invoice text\n' * 100) event.settings.set('show_date_to', False) inv = generate_invoice(order) assert invoice_pdf_task(inv.pk)
def test_address_vat_id(env): event, order = env event.settings.set('invoice_language', 'en') InvoiceAddress.objects.create(company='Acme Company', street='221B Baker Street', name='Sherlock Holmes', zipcode='12345', city='London', country='UK', vat_id='UK1234567', order=order) inv = generate_invoice(order) assert inv.invoice_to == "Acme Company\nSherlock Holmes\n221B Baker Street\n12345 London\nUK\nVAT-ID: UK1234567"
def test_positions_skip_free(env): event, order = env event.settings.invoice_include_free = False op1 = order.positions.first() op1.price = Decimal('0.00') op1.save() inv = generate_invoice(order) assert inv.lines.count() == 2
def test_rebuilding(env): event, order = env inv = generate_invoice(order) inv2 = regenerate_invoice(inv) assert inv.order == inv2.order inv3 = generate_cancellation(inv) inv4 = regenerate_invoice(inv3) assert inv3.order == inv4.order
def post(self, request, *args, **kwargs): if self.request.event.settings.get("invoice_generate") != "user" or not invoice_qualified(self.order): messages.error(self.request, _("You cannot generate an invoice for this order.")) elif self.order.invoices.exists(): messages.error(self.request, _("An invoice for this order already exists.")) else: i = generate_invoice(self.order) self.order.log_action("pretix.event.order.invoice.generated", data={"invoice": i.pk}) messages.success(self.request, _("The invoice has been generated.")) return redirect(self.get_order_url())
def test_order_invoice_regenerate(client, env): client.login(email='*****@*****.**', password='******') i = generate_invoice(env[2]) InvoiceAddress.objects.create(name='Foo', order=env[2]) env[0].settings.set('invoice_generate', 'admin') response = client.post('/control/event/dummy/dummy/orders/FOO/invoices/%d/regenerate' % i.pk, {}, follow=True) assert 'alert-success' in response.rendered_content i.refresh_from_db() assert 'Foo' in i.invoice_to assert env[2].invoices.exists()
def test_change_paymentmethod_available(self): self.event.settings.set('payment_banktransfer__enabled', True) self.event.settings.set('payment_testdummy__enabled', True) self.event.settings.set('payment_testdummy__fee_abs', '12.00') generate_invoice(self.order) response = self.client.get( '/%s/%s/order/%s/%s/pay/change' % (self.orga.slug, self.event.slug, self.order.code, self.order.secret), ) assert 'Test dummy' in response.rendered_content assert '+ 12.00' in response.rendered_content response = self.client.post( '/%s/%s/order/%s/%s/pay/change' % (self.orga.slug, self.event.slug, self.order.code, self.order.secret), { 'payment': 'testdummy' } ) self.order.refresh_from_db() assert self.order.payment_provider == 'testdummy' assert self.order.payment_fee == Decimal('12.00') assert self.order.total == Decimal('23.00') + self.order.payment_fee assert self.order.invoices.count() == 3
def post(self, request, *args, **kwargs): if self.request.event.settings.get('invoice_generate') != 'user' or not invoice_qualified(self.order): messages.error(self.request, _('You cannot generate an invoice for this order.')) elif self.order.invoices.exists(): messages.error(self.request, _('An invoice for this order already exists.')) else: i = generate_invoice(self.order) self.order.log_action('pretix.event.order.invoice.generated', data={ 'invoice': i.pk }) messages.success(self.request, _('The invoice has been generated.')) return redirect(self.get_order_url())
def post(self, request, *args, **kwargs): self.request = request oldtotal = self.order.total for p in self.provider_forms: if p['provider'].identifier == request.POST.get('payment', ''): request.session['payment'] = p['provider'].identifier request.session['payment_change_{}'.format(self.order.pk)] = '1' with transaction.atomic(): old_fee, new_fee, fee = change_payment_provider(self.order, p['provider'], None) newpayment = self.order.payments.create( state=OrderPayment.PAYMENT_STATE_CREATED, provider=p['provider'].identifier, amount=self.order.pending_sum, fee=fee ) self.order.log_action( 'pretix.event.order.payment.changed' if self.open_payment else 'pretix.event.order.payment.started', { 'fee': new_fee, 'old_fee': old_fee, 'provider': newpayment.provider, 'payment': newpayment.pk, 'local_id': newpayment.local_id, } ) i = self.order.invoices.filter(is_cancellation=False).last() if i and self.order.total != oldtotal: generate_cancellation(i) generate_invoice(self.order) resp = p['provider'].payment_prepare(request, newpayment) if isinstance(resp, str): return redirect(resp) elif resp is True: return redirect(self.get_confirm_url(newpayment)) else: return self.get(request, *args, **kwargs) messages.error(self.request, _("Please select a payment method.")) return self.get(request, *args, **kwargs)
def test_positions(env): event, order = env inv = generate_invoice(order) assert inv.lines.count() == 2 first = inv.lines.first() assert 'Early-bird' in first.description assert first.gross_value == Decimal('23.00') last = inv.lines.last() assert 'Payment' in last.description assert last.gross_value == order.payment_fee assert last.tax_rate == order.payment_fee_tax_rate assert last.tax_value == order.payment_fee_tax_value assert inv.invoice_to == ""
def create(self, request, *args, **kwargs): serializer = OrderCreateSerializer(data=request.data, context=self.get_serializer_context()) serializer.is_valid(raise_exception=True) with transaction.atomic(): self.perform_create(serializer) order = serializer.instance serializer = OrderSerializer(order, context=serializer.context) order.log_action( 'pretix.event.order.placed', user=request.user if request.user.is_authenticated else None, auth=request.auth, ) order_placed.send(self.request.event, order=order) gen_invoice = invoice_qualified(order) and ( (order.event.settings.get('invoice_generate') == 'True') or (order.event.settings.get('invoice_generate') == 'paid' and order.status == Order.STATUS_PAID) ) and not order.invoices.last() if gen_invoice: generate_invoice(order, trigger_pdf=True) headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def post(self, *args, **kwargs): try: inv = self.order.invoices.get(pk=kwargs.get('id')) except Order.DoesNotExist: messages.error(self.request, _('Unknown invoice.')) else: if inv.canceled: messages.error(self.request, _('The invoice has already been canceled.')) else: generate_cancellation(inv) inv = generate_invoice(self.order) self.order.log_action('pretix.event.order.invoice.reissued', user=self.request.user, data={ 'invoice': inv.pk }) messages.success(self.request, _('The invoice has been reissued.')) return redirect(self.get_order_url())
def post(self, *args, **kwargs): try: inv = self.order.invoices.get(pk=kwargs.get('id')) except Invoice.DoesNotExist: messages.error(self.request, _('Unknown invoice.')) else: if inv.canceled: messages.error(self.request, _('The invoice has already been canceled.')) else: generate_cancellation(inv) inv = generate_invoice(self.order) self.order.log_action('pretix.event.order.invoice.reissued', user=self.request.user, data={'invoice': inv.pk}) messages.success(self.request, _('The invoice has been reissued.')) return redirect(self.get_order_url())
def post(self, request, *args, **kwargs): failed = not self.save() or not self.invoice_form.is_valid() if failed: messages.error( self.request, _("We had difficulties processing your input. Please review the errors below." )) return self.get(request, *args, **kwargs) if hasattr(self.invoice_form, 'save'): self.invoice_form.save() self.order.log_action( 'pretix.event.order.modified', { 'invoice_data': self.invoice_form.cleaned_data, 'data': [{ k: (f.cleaned_data.get(k).name if isinstance( f.cleaned_data.get(k), File) else f.cleaned_data.get(k)) for k in f.changed_data } for f in self.forms] }) order_modified.send(sender=self.request.event, order=self.order) if request.GET.get('generate_invoice') == 'true': if not can_generate_invoice(self.request.event, self.order): messages.error( self.request, _('You cannot generate an invoice for this order.')) elif self.order.invoices.exists(): messages.error(self.request, _('An invoice for this order already exists.')) else: i = generate_invoice(self.order) self.order.log_action('pretix.event.order.invoice.generated', data={'invoice': i.pk}) messages.success(self.request, _('The invoice has been generated.')) invalidate_cache.apply_async(kwargs={ 'event': self.request.event.pk, 'order': self.order.pk }) CachedTicket.objects.filter(order_position__order=self.order).delete() CachedCombinedTicket.objects.filter(order=self.order).delete() return redirect(self.get_order_url())
def post(self, request, *args, **kwargs): can_generate_invoice = ( self.request.event.settings.get('invoice_generate') in ('user', 'True') or (self.request.event.settings.get('invoice_generate') == 'paid' and self.order.status == Order.STATUS_PAID)) if not can_generate_invoice or not invoice_qualified(self.order): messages.error(self.request, _('You cannot generate an invoice for this order.')) elif self.order.invoices.exists(): messages.error(self.request, _('An invoice for this order already exists.')) else: i = generate_invoice(self.order) self.order.log_action('pretix.event.order.invoice.generated', data={'invoice': i.pk}) messages.success(self.request, _('The invoice has been generated.')) return redirect(self.get_order_url())
def test_positions(env): event, order = env inv = generate_invoice(order) assert inv.lines.count() == 3 first = inv.lines.first() assert 'Early-bird' in first.description assert first.gross_value == Decimal('23.00') second = inv.lines.all()[1] assert 'T-Shirt' in second.description assert 'M' in second.description assert second.gross_value == Decimal('42.00') last = inv.lines.last() assert 'Payment' in last.description assert last.gross_value == order.payment_fee assert last.tax_rate == order.payment_fee_tax_rate assert last.tax_value == order.payment_fee_tax_value assert inv.invoice_to == ""
def reissue(self, request, **kwarts): inv = self.get_object() if inv.canceled: raise ValidationError('The invoice has already been canceled.') else: c = generate_cancellation(inv) if inv.order.status not in (Order.STATUS_CANCELED, Order.STATUS_REFUNDED): inv = generate_invoice(inv.order) else: inv = c inv.order.log_action( 'pretix.event.order.invoice.reissued', data={'invoice': inv.pk}, user=self.request.user, api_token=(self.request.auth if isinstance( self.request.auth, TeamAPIToken) else None), ) return Response(status=204)
def post(self, request, *args, **kwargs): can_generate_invoice = ( self.request.event.settings.get('invoice_generate') in ('user', 'True') or ( self.request.event.settings.get('invoice_generate') == 'paid' and self.order.status == Order.STATUS_PAID ) ) if not can_generate_invoice or not invoice_qualified(self.order): messages.error(self.request, _('You cannot generate an invoice for this order.')) elif self.order.invoices.exists(): messages.error(self.request, _('An invoice for this order already exists.')) else: i = generate_invoice(self.order) self.order.log_action('pretix.event.order.invoice.generated', data={ 'invoice': i.pk }) messages.success(self.request, _('The invoice has been generated.')) return redirect(self.get_order_url())
def test_invoice_numbers(env): event, order = env order2 = Order.objects.create( code='BAR', event=event, email='*****@*****.**', status=Order.STATUS_PENDING, datetime=now(), expires=now() + timedelta(days=10), total=0, locale='en' ) order2.fees.create(fee_type=OrderFee.FEE_TYPE_PAYMENT, value=Decimal('0.25'), tax_rate=Decimal('0.00'), tax_value=Decimal('0.00')) inv1 = generate_invoice(order) inv2 = generate_invoice(order) event.settings.set('invoice_numbers_consecutive', False) inv3 = generate_invoice(order) inv4 = generate_invoice(order) inv21 = generate_invoice(order2) inv22 = generate_invoice(order2) event.settings.set('invoice_numbers_consecutive', True) inv5 = generate_invoice(order) inv23 = generate_invoice(order2) # expected behaviour for switching between numbering formats assert inv1.invoice_no == '00001' assert inv2.invoice_no == '00002' assert inv3.invoice_no == '{}-3'.format(order.code) assert inv4.invoice_no == '{}-4'.format(order.code) assert inv5.invoice_no == '00003' # test that separate orders are counted separately in this mode assert inv21.invoice_no == '{}-1'.format(order2.code) assert inv22.invoice_no == '{}-2'.format(order2.code) # but consecutively in this mode assert inv23.invoice_no == '00004' # test Invoice.number, too assert inv1.number == '{}-00001'.format(event.slug.upper()) assert inv3.number == '{}-{}-3'.format(event.slug.upper(), order.code)
def test_positions(env): event, order = env inv = generate_invoice(order) assert inv.lines.count() == 3 first = inv.lines.first() assert 'Early-bird' in first.description assert first.gross_value == Decimal('23.00') second = inv.lines.all()[1] assert 'T-Shirt' in second.description assert 'M' in second.description assert second.gross_value == Decimal('42.00') last = inv.lines.last() assert 'Payment' in last.description fee = order.fees.get(fee_type=OrderFee.FEE_TYPE_PAYMENT) assert last.gross_value == fee.value assert last.tax_rate == fee.tax_rate assert last.tax_value == fee.tax_value assert inv.invoice_to == ""
def test_invoice_numbers(env): event, order = env order2 = Order.objects.create( code='BAR', event=event, email='*****@*****.**', status=Order.STATUS_PENDING, datetime=now(), expires=now() + timedelta(days=10), total=0, payment_provider='banktransfer', payment_fee=Decimal('0.25'), payment_fee_tax_rate=0, payment_fee_tax_value=0, locale='en' ) inv1 = generate_invoice(order) inv2 = generate_invoice(order) event.settings.set('invoice_numbers_consecutive', False) inv3 = generate_invoice(order) inv4 = generate_invoice(order) inv21 = generate_invoice(order2) inv22 = generate_invoice(order2) event.settings.set('invoice_numbers_consecutive', True) inv5 = generate_invoice(order) inv23 = generate_invoice(order2) # expected behaviour for switching between numbering formats assert inv1.invoice_no == '00001' assert inv2.invoice_no == '00002' assert inv3.invoice_no == '{}-3'.format(order.code) assert inv4.invoice_no == '{}-4'.format(order.code) assert inv5.invoice_no == '00003' # test that separate orders are counted separately in this mode assert inv21.invoice_no == '{}-1'.format(order2.code) assert inv22.invoice_no == '{}-2'.format(order2.code) # but consecutively in this mode assert inv23.invoice_no == '00004' # test Invoice.number, too assert inv1.number == '{}-00001'.format(event.slug.upper()) assert inv3.number == '{}-{}-3'.format(event.slug.upper(), order.code)
def reissue(self, request, **kwarts): inv = self.get_object() if inv.canceled: raise ValidationError('The invoice has already been canceled.') elif inv.shredded: raise PermissionDenied( 'The invoice file is no longer stored on the server.') else: c = generate_cancellation(inv) if inv.order.status != Order.STATUS_CANCELED: inv = generate_invoice(inv.order) else: inv = c inv.order.log_action( 'pretix.event.order.invoice.reissued', data={'invoice': inv.pk}, user=self.request.user, auth=self.request.auth, ) return Response(status=204)
def test_positions(env): event, order = env inv = generate_invoice(order) assert inv.lines.count() == 3 first = inv.lines.first() assert 'Early-bird' in first.description assert first.gross_value == Decimal('23.00') second = inv.lines.all()[1] assert 'T-Shirt' in second.description assert 'M' in second.description assert second.gross_value == Decimal('42.00') last = inv.lines.last() assert 'Payment' in last.description fee = order.fees.get(fee_type=OrderFee.FEE_TYPE_PAYMENT) assert last.gross_value == fee.value assert last.tax_rate == fee.tax_rate assert last.tax_value == fee.tax_value assert last.fee_type == 'payment' assert inv.invoice_to == ""
def test_invoice_shredder(event, order): InvoiceAddress.objects.create(company='Acme Company', street='221B Baker Street', zipcode='12345', city='London', country='UK', order=order) inv = generate_invoice(order) invoice_pdf_task.apply(args=(inv.pk,)) inv.refresh_from_db() assert inv.invoice_to == "Acme Company\n\n221B Baker Street\n12345 London" assert inv.file fname = inv.file.path assert os.path.exists(fname) s = InvoiceShredder(event) f = list(s.generate_files()) assert len(f) == 1 s.shred_data() inv.refresh_from_db() assert "Acme" not in inv.invoice_to assert "icket" not in inv.lines.first().description assert not inv.file assert not os.path.exists(fname)
def reissue(self, request, **kwarts): inv = self.get_object() if inv.canceled: raise ValidationError('The invoice has already been canceled.') elif inv.shredded: raise PermissionDenied('The invoice file is no longer stored on the server.') else: c = generate_cancellation(inv) if inv.order.status != Order.STATUS_CANCELED: inv = generate_invoice(inv.order) else: inv = c inv.order.log_action( 'pretix.event.order.invoice.reissued', data={ 'invoice': inv.pk }, user=self.request.user, auth=self.request.auth, ) return Response(status=204)
def test_invoice_shredder(event, order): InvoiceAddress.objects.create(company='Acme Company', street='221B Baker Street', zipcode='12345', city='London', country='UK', order=order) inv = generate_invoice(order) invoice_pdf_task.apply(args=(inv.pk,)) inv.refresh_from_db() assert inv.invoice_to == "Acme Company\n\n221B Baker Street\n12345 London" assert inv.file fname = inv.file.path assert os.path.exists(fname) s = InvoiceShredder(event) f = list(s.generate_files()) assert len(f) == 1 s.shred_data() inv.refresh_from_db() assert "Acme" not in inv.invoice_to assert "icket" not in inv.lines.first().description assert not inv.file assert not os.path.exists(fname)
def test_reverse_charge_note(env): event, order = env tr = event.tax_rules.first() tr.eu_reverse_charge = True tr.home_country = Country('DE') tr.save() event.settings.set('invoice_language', 'en') InvoiceAddress.objects.create(company='Acme Company', street='221B Baker Street', zipcode='12345', city='Warsaw', country=Country('PL'), vat_id='PL123456780', vat_id_validated=True, order=order, is_business=True) ocm = OrderChangeManager(order, None) ocm.recalculate_taxes() ocm.commit() assert not order.positions.filter(tax_value__gt=0).exists() inv = generate_invoice(order) assert "reverse charge" in inv.additional_text.lower() assert inv.foreign_currency_display == "PLN" assert inv.foreign_currency_rate == Decimal("4.2408") assert inv.foreign_currency_rate_date == date.today()
def test_reverse_charge_note(env): event, order = env tr = event.tax_rules.first() tr.eu_reverse_charge = True tr.home_country = Country('DE') tr.save() event.settings.set('invoice_language', 'en') InvoiceAddress.objects.create(company='Acme Company', street='221B Baker Street', zipcode='12345', city='Warsaw', country=Country('PL'), vat_id='PL123456780', vat_id_validated=True, order=order, is_business=True) ocm = OrderChangeManager(order, None) ocm.recalculate_taxes() ocm.commit() assert not order.positions.filter(tax_value__gt=0).exists() inv = generate_invoice(order) assert "reverse charge" in inv.additional_text.lower() assert inv.foreign_currency_display == "PLN" assert inv.foreign_currency_rate == Decimal("4.2408") assert inv.foreign_currency_rate_date == date.today()
def post(self, request, *args, **kwargs): self.request = request oldtotal = self.order.total for p in self.provider_forms: if p['provider'].identifier == request.POST.get('payment', ''): request.session['payment'] = p['provider'].identifier request.session['payment_change_{}'.format( self.order.pk)] = '1' fees = list(self.open_fees) if fees: fee = fees[0] if len(fees) > 1: for f in fees[1:]: f.delete() else: fee = OrderFee(fee_type=OrderFee.FEE_TYPE_PAYMENT, value=Decimal('0.00'), order=self.order) old_fee = fee.value new_fee = p['provider'].calculate_fee(self.order.pending_sum - old_fee) if new_fee: fee.value = new_fee fee.internal_type = p['provider'].identifier fee._calculate_tax() fee.save() else: if fee.pk: fee.delete() fee = None if self.open_payment and self.open_payment.state in ( OrderPayment.PAYMENT_STATE_PENDING, OrderPayment.PAYMENT_STATE_CREATED): self.open_payment.state = OrderPayment.PAYMENT_STATE_CANCELED self.open_payment.save(update_fields=['state']) self.order.total = self._position_sum + ( self.order.fees.aggregate(sum=Sum('value'))['sum'] or 0) newpayment = self.order.payments.create( state=OrderPayment.PAYMENT_STATE_CREATED, provider=p['provider'].identifier, amount=self.order.pending_sum, fee=fee) resp = p['provider'].payment_prepare(request, newpayment) if resp: with transaction.atomic(): if self.open_payment and self.open_payment.provider != p[ 'provider'].identifier: self.order.log_action( 'pretix.event.order.payment.changed', { 'old_fee': old_fee, 'new_fee': new_fee, 'old_provider': self.open_payment.provider, 'new_provider': p['provider'].identifier, 'payment': newpayment.pk, 'local_id': newpayment.local_id, }) else: self.order.log_action( 'pretix.event.order.payment.started', { 'fee': new_fee, 'provider': p['provider'].identifier, 'payment': newpayment.pk, 'local_id': newpayment.local_id, }) self.order.save() i = self.order.invoices.filter( is_cancellation=False).last() if i and self.order.total != oldtotal: generate_cancellation(i) generate_invoice(self.order) if isinstance(resp, str): return redirect(resp) elif resp is True: return redirect(self.get_confirm_url(newpayment)) else: return self.get(request, *args, **kwargs) messages.error(self.request, _("Please select a payment method.")) return self.get(request, *args, **kwargs)
def test_order_invoice_reissue_canceled(client, env): client.login(email='*****@*****.**', password='******') i = generate_invoice(env[2]) generate_cancellation(i) response = client.post('/control/event/dummy/dummy/orders/FOO/invoices/%d/reissue' % i.pk, {}, follow=True) assert 'alert-danger' in response.rendered_content
def _perform_order(event: str, payment_provider: str, position_ids: List[str], email: str, locale: str, address: int, meta_info: dict=None): event = Event.objects.get(id=event) pprov = event.get_payment_providers().get(payment_provider) if not pprov: raise OrderError(error_messages['internal']) addr = None if address is not None: try: addr = InvoiceAddress.objects.get(pk=address) except InvoiceAddress.DoesNotExist: pass with event.lock() as now_dt: positions = list(CartPosition.objects.filter( id__in=position_ids).select_related('item', 'variation', 'subevent')) if len(positions) == 0: raise OrderError(error_messages['empty']) if len(position_ids) != len(positions): raise OrderError(error_messages['internal']) _check_positions(event, now_dt, positions, address=addr) order = _create_order(event, email, positions, now_dt, pprov, locale=locale, address=addr, meta_info=meta_info) if event.settings.get('invoice_generate') == 'True' and invoice_qualified(order): if not order.invoices.exists(): generate_invoice(order) if order.total == Decimal('0.00'): email_template = event.settings.mail_text_order_free log_entry = 'pretix.event.order.email.order_free' else: email_template = event.settings.mail_text_order_placed log_entry = 'pretix.event.order.email.order_placed' try: invoice_name = order.invoice_address.name invoice_company = order.invoice_address.company except InvoiceAddress.DoesNotExist: invoice_name = "" invoice_company = "" email_context = { '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 }), 'payment_info': str(pprov.order_pending_mail_render(order)), 'invoice_name': invoice_name, 'invoice_company': invoice_company, } email_subject = _('Your order: %(code)s') % {'code': order.code} try: order.send_mail( email_subject, email_template, email_context, log_entry ) except SendMailException: logger.exception('Order received email could not be sent') return order.id
def test_invoice_numbers(env): event, order = env order2 = Order.objects.create(code='BAR', event=event, email='*****@*****.**', status=Order.STATUS_PENDING, datetime=now(), expires=now() + timedelta(days=10), total=0, locale='en') order2.fees.create(fee_type=OrderFee.FEE_TYPE_PAYMENT, value=Decimal('0.25'), tax_rate=Decimal('0.00'), tax_value=Decimal('0.00')) testorder = Order.objects.create(code='BAR', event=event, email='*****@*****.**', status=Order.STATUS_PENDING, datetime=now(), expires=now() + timedelta(days=10), total=0, testmode=True, locale='en') inv1 = generate_invoice(order) inv2 = generate_invoice(order) invt1 = generate_invoice(testorder) event.settings.set('invoice_numbers_consecutive', False) inv3 = generate_invoice(order) inv4 = generate_invoice(order) inv21 = generate_invoice(order2) invt2 = generate_invoice(testorder) inv22 = generate_invoice(order2) event.settings.set('invoice_numbers_consecutive', True) inv5 = generate_invoice(order) inv6 = generate_invoice(order) invt3 = generate_invoice(testorder) inv7 = generate_invoice(order) Invoice.objects.filter(pk=inv6.pk).delete( ) # This should never ever happen, but what if it happens anyway? inv8 = generate_invoice(order) inv23 = generate_invoice(order2) event.settings.set('invoice_numbers_counter_length', 6) inv24 = generate_invoice(order) event.settings.set('invoice_numbers_counter_length', 1) inv25 = generate_invoice(order) inv26 = generate_invoice(order) # expected behaviour for switching between numbering formats or dealing with gaps assert inv1.invoice_no == '00001' assert inv2.invoice_no == '00002' assert inv3.invoice_no == '{}-3'.format(order.code) assert inv4.invoice_no == '{}-4'.format(order.code) assert inv5.invoice_no == '00003' assert inv6.invoice_no == '00004' assert inv7.invoice_no == '00005' assert inv8.invoice_no == '00006' # test that separate orders are counted separately in this mode assert inv21.invoice_no == '{}-1'.format(order2.code) assert inv22.invoice_no == '{}-2'.format(order2.code) # but consecutively in this mode assert inv23.invoice_no == '00007' assert inv24.invoice_no == '000008' assert inv25.invoice_no == '9' assert inv26.invoice_no == '10' # test Invoice.number, too assert inv1.number == '{}-00001'.format(event.slug.upper()) assert inv3.number == '{}-{}-3'.format(event.slug.upper(), order.code) assert invt1.number == '{}-TEST-00001'.format(event.slug.upper()) assert invt2.number == '{}-TEST-{}-2'.format(event.slug.upper(), testorder.code) assert invt3.number == '{}-TEST-00002'.format(event.slug.upper())
def test_cannot_delete_invoice(env): event, order = env inv = generate_invoice(order) with pytest.raises(Exception): inv.delete()
def test_locale_setting(env): event, order = env event.settings.set('invoice_language', 'de') with scopes_disabled(): inv = generate_invoice(order) assert inv.locale == 'de'
def import_orders(event: Event, fileid: str, settings: dict, locale: str, user) -> None: # TODO: quotacheck? cf = CachedFile.objects.get(id=fileid) user = User.objects.get(pk=user) with language(locale, event.settings.region): cols = get_all_columns(event) parsed = parse_csv(cf.file) orders = [] order = None data = [] # Run validation for i, record in enumerate(parsed): if not any(record.values()): continue values = {} for c in cols: val = c.resolve(settings, record) if isinstance(val, str): val = val.strip() try: values[c.identifier] = c.clean(val, values) except ValidationError as e: raise DataImportError( _('Error while importing value "{value}" for column "{column}" in line "{line}": {message}' ).format(value=val if val is not None else '', column=c.verbose_name, line=i + 1, message=e.message)) data.append(values) # Prepare model objects. Yes, this might consume lots of RAM, but allows us to make the actual SQL transaction # shorter. We'll see what works better in reality… for i, record in enumerate(data): try: if order is None or settings['orders'] == 'many': order = Order( event=event, testmode=settings['testmode'], ) order.meta_info = {} order._positions = [] order._address = InvoiceAddress() order._address.name_parts = { '_scheme': event.settings.name_scheme } orders.append(order) position = OrderPosition(positionid=len(order._positions) + 1) position.attendee_name_parts = { '_scheme': event.settings.name_scheme } position.meta_info = {} order._positions.append(position) position.assign_pseudonymization_id() for c in cols: c.assign(record.get(c.identifier), order, position, order._address) except ImportError as e: raise ImportError( _('Invalid data in row {row}: {message}').format( row=i, message=str(e))) # quota check? with event.lock(): with transaction.atomic(): save_transactions = [] for o in orders: o.total = sum([c.price for c in o._positions ]) # currently no support for fees if o.total == Decimal('0.00'): o.status = Order.STATUS_PAID o.save() OrderPayment.objects.create( local_id=1, order=o, amount=Decimal('0.00'), provider='free', info='{}', payment_date=now(), state=OrderPayment.PAYMENT_STATE_CONFIRMED) elif settings['status'] == 'paid': o.status = Order.STATUS_PAID o.save() OrderPayment.objects.create( local_id=1, order=o, amount=o.total, provider='manual', info='{}', payment_date=now(), state=OrderPayment.PAYMENT_STATE_CONFIRMED) else: o.status = Order.STATUS_PENDING o.save() for p in o._positions: p.order = o p.save() o._address.order = o o._address.save() for c in cols: c.save(o) o.log_action('pretix.event.order.placed', user=user, data={'source': 'import'}) save_transactions += o.create_transactions( is_new=True, fees=[], positions=o._positions, save=False) Transaction.objects.bulk_create(save_transactions) for o in orders: with language(o.locale, event.settings.region): order_placed.send(event, order=o) if o.status == Order.STATUS_PAID: order_paid.send(event, order=o) gen_invoice = invoice_qualified(o) and ( (event.settings.get('invoice_generate') == 'True') or (event.settings.get('invoice_generate') == 'paid' and o.status == Order.STATUS_PAID)) and not o.invoices.last() if gen_invoice: generate_invoice(o, trigger_pdf=True) cf.delete()
def test_locale_user(env): event, order = env order.locale = 'en' event.settings.set('invoice_language', '__user__') inv = generate_invoice(order) assert inv.locale == order.locale
def test_locale_setting(env): event, order = env event.settings.set('invoice_language', 'de') inv = generate_invoice(order) assert inv.locale == 'de'
def test_order_invoice_reissue_canceled(client, env): client.login(email='*****@*****.**', password='******') i = generate_invoice(env[2]) generate_cancellation(i) response = client.post('/control/event/dummy/dummy/orders/FOO/invoices/%d/reissue' % i.pk, {}, follow=True) assert 'alert-danger' in response.rendered_content
def test_invoice_number_prefixes(env): event, order = env event2 = Event.objects.create( organizer=event.organizer, name='Dummy', slug='dummy2', date_from=now(), plugins='pretix.plugins.banktransfer' ) order2 = Order.objects.create( event=event2, email='*****@*****.**', status=Order.STATUS_PENDING, datetime=now(), expires=now() + timedelta(days=10), total=0, payment_provider='banktransfer', payment_fee=Decimal('0.25'), payment_fee_tax_rate=0, payment_fee_tax_value=0, locale='en' ) event.settings.set('invoice_numbers_consecutive', False) event2.settings.set('invoice_numbers_consecutive', False) assert generate_invoice(order).number == 'DUMMY-{}-1'.format(order.code) assert generate_invoice(order2).number == 'DUMMY2-{}-1'.format(order2.code) event.settings.set('invoice_numbers_consecutive', True) event2.settings.set('invoice_numbers_consecutive', True) event.settings.set('invoice_numbers_prefix', '') event2.settings.set('invoice_numbers_prefix', '') assert generate_invoice(order).number == 'DUMMY-00001' assert generate_invoice(order).number == 'DUMMY-00002' assert generate_invoice(order2).number == 'DUMMY2-00001' assert generate_invoice(order2).number == 'DUMMY2-00002' event.settings.set('invoice_numbers_prefix', 'shared_') event2.settings.set('invoice_numbers_prefix', 'shared_') assert generate_invoice(order).number == 'shared_00001' assert generate_invoice(order2).number == 'shared_00002' assert generate_invoice(order).number == 'shared_00003' assert generate_invoice(order2).number == 'shared_00004' event.settings.set('invoice_numbers_consecutive', False) event2.settings.set('invoice_numbers_consecutive', False) assert generate_invoice(order).number == 'shared_{}-6'.format(order.code) assert generate_invoice(order2).number == 'shared_{}-6'.format(order2.code) # Test database uniqueness check with pytest.raises(DatabaseError): Invoice.objects.create( order=order, event=order.event, organizer=order.event.organizer, date=now().date(), locale='en', invoice_no='00001', )
def _perform_order(event: str, payment_provider: str, position_ids: List[str], email: str, locale: str, address: int, meta_info: dict = None): 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(positions) == 0: raise OrderError(error_messages['empty']) 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, meta_info=meta_info) 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 try: invoice_name = order.invoice_address.name invoice_company = order.invoice_address.company except InvoiceAddress.DoesNotExist: invoice_name = "" invoice_company = "" 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)), 'invoice_name': invoice_name, 'invoice_company': invoice_company, }, event, locale=order.locale) return order.id
def _reissue_invoice(self): i = self.order.invoices.filter(is_cancellation=False).last() if i: generate_cancellation(i) generate_invoice(self.order)
def create(self, request, *args, **kwargs): serializer = OrderCreateSerializer( data=request.data, context=self.get_serializer_context()) serializer.is_valid(raise_exception=True) with transaction.atomic(): self.perform_create(serializer) send_mail = serializer._send_mail order = serializer.instance serializer = OrderSerializer(order, context=serializer.context) order.log_action( 'pretix.event.order.placed', user=request.user if request.user.is_authenticated else None, auth=request.auth, ) order_placed.send(self.request.event, order=order) gen_invoice = invoice_qualified(order) and ( (order.event.settings.get('invoice_generate') == 'True') or (order.event.settings.get('invoice_generate') == 'paid' and order.status == Order.STATUS_PAID)) and not order.invoices.last() invoice = None if gen_invoice: invoice = generate_invoice(order, trigger_pdf=True) if send_mail: payment = order.payments.last() free_flow = (payment and order.total == Decimal('0.00') and order.status == Order.STATUS_PAID and not order.require_approval and payment.provider == "free") if free_flow: email_template = request.event.settings.mail_text_order_free log_entry = 'pretix.event.order.email.order_free' email_attendees = request.event.settings.mail_send_order_free_attendee email_attendees_template = request.event.settings.mail_text_order_free_attendee else: email_template = request.event.settings.mail_text_order_placed log_entry = 'pretix.event.order.email.order_placed' email_attendees = request.event.settings.mail_send_order_placed_attendee email_attendees_template = request.event.settings.mail_text_order_placed_attendee _order_placed_email(request.event, order, payment.payment_provider if payment else None, email_template, log_entry, invoice, payment) if email_attendees: for p in order.positions.all(): if p.addon_to_id is None and p.attendee_email and p.attendee_email != order.email: _order_placed_email_attendee(request.event, order, p, email_attendees_template, log_entry) if not free_flow and order.status == Order.STATUS_PAID and payment: payment._send_paid_mail(invoice, None, '') if self.request.event.settings.mail_send_order_paid_attendee: for p in order.positions.all(): if p.addon_to_id is None and p.attendee_email and p.attendee_email != order.email: payment._send_paid_mail_attendee(p, None) headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def test_locale_user(env): event, order = env order.locale = 'en' event.settings.set('invoice_language', '__user__') inv = generate_invoice(order) assert inv.locale == order.locale
def test_reissue_invoice(self): generate_invoice(self.order) assert self.order.invoices.count() == 1 self.ocm.add_position(self.ticket, None, Decimal('0.00')) self.ocm.commit() assert self.order.invoices.count() == 3
def test_pdf_generation(env): event, order = env inv = generate_invoice(order) cancellation = generate_cancellation(inv) assert invoice_pdf_task(inv.pk) assert invoice_pdf_task(cancellation.pk)
def invoice(order): testtime = datetime.datetime(2017, 12, 10, 10, 0, 0, tzinfo=UTC) with mock.patch('django.utils.timezone.now') as mock_now: mock_now.return_value = testtime return generate_invoice(order)
def test_invoice_number_prefixes(env): event, order = env event2 = Event.objects.create(organizer=event.organizer, name='Dummy', slug='dummy2', date_from=now(), plugins='pretix.plugins.banktransfer') order2 = Order.objects.create(event=event2, email='*****@*****.**', status=Order.STATUS_PENDING, datetime=now(), expires=now() + timedelta(days=10), total=0, locale='en') order2.fees.create(fee_type=OrderFee.FEE_TYPE_PAYMENT, value=Decimal('0.25'), tax_rate=Decimal('0.00'), tax_value=Decimal('0.00')) event.settings.set('invoice_numbers_consecutive', False) event2.settings.set('invoice_numbers_consecutive', False) assert generate_invoice(order).number == 'DUMMY-{}-1'.format(order.code) assert generate_invoice(order2).number == 'DUMMY2-{}-1'.format(order2.code) event.settings.set('invoice_numbers_consecutive', True) event2.settings.set('invoice_numbers_consecutive', True) event.settings.set('invoice_numbers_prefix', '') event2.settings.set('invoice_numbers_prefix', '') assert generate_invoice(order).number == 'DUMMY-00001' assert generate_invoice(order).number == 'DUMMY-00002' assert generate_invoice(order2).number == 'DUMMY2-00001' assert generate_invoice(order2).number == 'DUMMY2-00002' event.settings.set('invoice_numbers_prefix', 'shared_') event2.settings.set('invoice_numbers_prefix', 'shared_') assert generate_invoice(order).number == 'shared_00001' assert generate_invoice(order2).number == 'shared_00002' assert generate_invoice(order).number == 'shared_00003' assert generate_invoice(order2).number == 'shared_00004' event.settings.set('invoice_numbers_consecutive', False) event2.settings.set('invoice_numbers_consecutive', False) assert generate_invoice(order).number == 'shared_{}-6'.format(order.code) assert generate_invoice(order2).number == 'shared_{}-6'.format(order2.code) event2.settings.set('invoice_numbers_prefix', 'inv_') event2.settings.set('invoice_numbers_prefix_cancellations', 'crd_') event2.settings.set('invoice_numbers_consecutive', True) event2.settings.set('invoice_numbers_counter_length', 4) i = generate_invoice(order2) assert i.number == 'inv_0001' assert generate_cancellation(i).number == 'crd_0001' event2.settings.set('invoice_numbers_prefix', 'inv_%Y%m%d_') i = generate_invoice(order2) assert i.number == 'inv_%s_0001' % now().date().strftime('%Y%m%d') # Test database uniqueness check with pytest.raises(DatabaseError): with transaction.atomic(): Invoice.objects.create( order=order, event=order.event, organizer=order.event.organizer, date=now().date(), locale='en', invoice_no='00001', )
def test_locale_setting(env): event, order = env event.settings.set('invoice_language', 'de') inv = generate_invoice(order) assert inv.locale == 'de'
def _reissue_invoice(self): i = self.order.invoices.filter(is_cancellation=False).last() if i: generate_cancellation(i) generate_invoice(self.order)
def test_order_invoice_create_duplicate(client, env): client.login(email='*****@*****.**', password='******') generate_invoice(env[2]) env[0].settings.set('invoice_generate', 'admin') response = client.post('/control/event/dummy/dummy/orders/FOO/invoice', {}, follow=True) assert 'alert-danger' in response.rendered_content
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, mail_text='') -> 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 :param mail_text: Additional text to be included in the email :type mail_text: str :raises Quota.QuotaExceededException: if the quota is exceeded and ``force`` is ``False`` """ if order.status == Order.STATUS_PAID: return order with order.event.lock() as now_dt: 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_dt 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 or now_dt, 'manual': manual, 'force': force }, user=user) order_paid.send(order.event, order=order) if order.event.settings.get('invoice_generate') in ('True', 'paid') and invoice_qualified(order): if not order.invoices.exists(): generate_invoice(order) if send_mail: with language(order.locale): try: invoice_name = order.invoice_address.name invoice_company = order.invoice_address.company except InvoiceAddress.DoesNotExist: invoice_name = "" invoice_company = "" 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), 'invoice_name': invoice_name, 'invoice_company': invoice_company, 'payment_info': mail_text }, order.event, locale=order.locale ) return order
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 receiver, 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'): 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