Пример #1
0
 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
Пример #2
0
 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
Пример #3
0
    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)
Пример #4
0
def _perform_order(event: str, payment_provider: str, position_ids: List[str],
                   email: str, locale: str, address: int):

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

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

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

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

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

    return order.id
Пример #5
0
 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())
Пример #6
0
def _perform_order(event: str, payment_provider: str, position_ids: List[str],
                   email: str, locale: str, address: int):

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

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

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

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

    return order.id
Пример #7
0
    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
        )
Пример #8
0
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"
Пример #9
0
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)
Пример #10
0
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"
Пример #11
0
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
Пример #12
0
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
Пример #13
0
 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())
Пример #14
0
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()
Пример #15
0
 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
Пример #16
0
 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())
Пример #17
0
    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)
Пример #18
0
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 == ""
Пример #19
0
    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)
Пример #20
0
 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())
Пример #21
0
 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())
Пример #22
0
    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())
Пример #23
0
 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())
Пример #24
0
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 == ""
Пример #25
0
 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)
Пример #26
0
 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())
Пример #27
0
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)
Пример #28
0
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 == ""
Пример #29
0
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)
Пример #30
0
 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)
Пример #31
0
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 == ""
Пример #32
0
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)
Пример #33
0
 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)
Пример #34
0
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)
Пример #35
0
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()
Пример #36
0
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()
Пример #37
0
    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)
Пример #38
0
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
Пример #39
0
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
Пример #40
0
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())
Пример #41
0
def test_cannot_delete_invoice(env):
    event, order = env
    inv = generate_invoice(order)
    with pytest.raises(Exception):
        inv.delete()
Пример #42
0
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'
Пример #43
0
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()
Пример #44
0
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
Пример #45
0
def test_locale_setting(env):
    event, order = env
    event.settings.set('invoice_language', 'de')
    inv = generate_invoice(order)
    assert inv.locale == 'de'
Пример #46
0
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
Пример #47
0
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',
        )
Пример #48
0
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
Пример #49
0
 def _reissue_invoice(self):
     i = self.order.invoices.filter(is_cancellation=False).last()
     if i:
         generate_cancellation(i)
         generate_invoice(self.order)
Пример #50
0
    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)
Пример #51
0
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
Пример #52
0
 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
Пример #53
0
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)
Пример #54
0
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)
Пример #55
0
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',
            )
Пример #56
0
def test_locale_setting(env):
    event, order = env
    event.settings.set('invoice_language', 'de')
    inv = generate_invoice(order)
    assert inv.locale == 'de'
Пример #57
0
 def _reissue_invoice(self):
     i = self.order.invoices.filter(is_cancellation=False).last()
     if i:
         generate_cancellation(i)
         generate_invoice(self.order)
Пример #58
0
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
Пример #59
0
def mark_order_paid(order: Order, provider: str=None, info: str=None, date: datetime=None, manual: bool=None,
                    force: bool=False, send_mail: bool=True, user: User=None, 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
Пример #60
0
def _perform_order(event: str, payment_provider: str, position_ids: List[str],
                   email: str, locale: str, address: int):

    event = Event.objects.get(id=event)
    responses = register_payment_providers.send(event)
    pprov = None
    for 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