def _cancel_order(order, user=None): """ Mark this order as canceled :param order: The order to change :param user: The user that performed the change """ if isinstance(order, int): order = Order.objects.get(pk=order) if isinstance(user, int): user = User.objects.get(pk=user) with order.event.lock(): if order.status != Order.STATUS_PENDING: raise OrderError(_('You cannot cancel this order.')) order.status = Order.STATUS_CANCELED order.save() order.log_action('pretix.event.order.canceled', user=user) i = order.invoices.filter(is_cancellation=False).last() if i: generate_cancellation(i) for position in order.positions.all(): if position.voucher: position.voucher.redeemed = False position.voucher.save() return order
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 _cancel_order(order, user=None): """ Mark this order as canceled :param order: The order to change :param user: The user that performed the change """ if isinstance(order, int): order = Order.objects.get(pk=order) if isinstance(user, int): user = User.objects.get(pk=user) with order.event.lock(): if order.status != Order.STATUS_PENDING: raise OrderError(_('You cannot cancel this order.')) order.status = Order.STATUS_CANCELED order.save() order.log_action('pretix.event.order.canceled', user=user) i = order.invoices.filter(is_cancellation=False).last() if i: generate_cancellation(i) for position in order.positions.all(): if position.voucher: Voucher.objects.filter(pk=position.voucher.pk).update(redeemed=F('redeemed') - 1) return order.pk
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 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' new_fee = p['provider'].calculate_fee(self._total_order_value) if new_fee: fee = self.order.fees.get_or_create( fee_type=OrderFee.FEE_TYPE_PAYMENT, defaults={'value': 0})[0] old_fee = fee.value fee.value = new_fee fee.internal_type = p['provider'].identifier fee._calculate_tax() fee.save() else: try: fee = self.order.fees.get( fee_type=OrderFee.FEE_TYPE_PAYMENT) old_fee = fee.value fee.delete() except OrderFee.DoesNotExist: old_fee = Decimal('0.00') self.order.payment_provider = p['provider'].identifier self.order.total = self._total_order_value + ( self.order.fees.aggregate(sum=Sum('value'))['sum'] or 0) resp = p['provider'].order_prepare(request, self.order) if resp: with transaction.atomic(): self.order.log_action( 'pretix.event.order.payment.changed', { 'old_fee': old_fee, 'new_fee': new_fee, 'old_provider': self.order.payment_provider, 'new_provider': p['provider'].identifier }) 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 _cancel_order(order, user=None, send_mail: bool = True): """ Mark this order as canceled :param order: The order to change :param user: The user that performed the change """ if isinstance(order, int): order = Order.objects.get(pk=order) if isinstance(user, int): user = User.objects.get(pk=user) with order.event.lock(): if order.status != Order.STATUS_PENDING: raise OrderError(_('You cannot cancel this order.')) order.status = Order.STATUS_CANCELED order.save() order.log_action('pretix.event.order.canceled', user=user) i = order.invoices.filter(is_cancellation=False).last() if i: generate_cancellation(i) for position in order.positions.all(): if position.voucher: Voucher.objects.filter(pk=position.voucher.pk).update( redeemed=F('redeemed') - 1) if send_mail: email_template = order.event.settings.mail_text_order_canceled email_context = { 'event': order.event.name, 'code': order.code, 'url': build_absolute_uri(order.event, 'presale:event.order', kwargs={ 'order': order.code, 'secret': order.secret }) } email_subject = _('Order canceled: %(code)s') % {'code': order.code} with language(order.locale): try: order.send_mail(email_subject, email_template, email_context, 'pretix.event.order.email.order_canceled', user) except SendMailException: logger.exception('Order canceled email could not be sent') return order.pk
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, *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.')) elif inv.shredded: messages.error( self.request, _('The invoice has been cleaned of personal data.')) else: c = generate_cancellation(inv) if self.order.status not in (Order.STATUS_CANCELED, Order.STATUS_REFUNDED): inv = generate_invoice(self.order) else: inv = c 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.')) elif self.request.event.settings.invoice_reissue_after_modify: if self.invoice_form.changed_data: inv = self.order.invoices.last() if inv and not inv.canceled and not inv.shredded: c = generate_cancellation(inv) if self.order.status != Order.STATUS_CANCELED: inv = generate_invoice(self.order) else: inv = c self.order.log_action( 'pretix.event.order.invoice.reissued', data={'invoice': inv.pk}) messages.success(self.request, _('The invoice has been reissued.')) 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 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 test_invoice_list(token_client, organizer, event, order, invoice): res = dict(TEST_INVOICE_RES) resp = token_client.get('/api/v1/organizers/{}/events/{}/invoices/'.format( organizer.slug, event.slug)) assert resp.status_code == 200 assert [res] == resp.data['results'] resp = token_client.get( '/api/v1/organizers/{}/events/{}/invoices/?order=FOO'.format( organizer.slug, event.slug)) assert [res] == resp.data['results'] resp = token_client.get( '/api/v1/organizers/{}/events/{}/invoices/?order=BAR'.format( organizer.slug, event.slug)) assert [] == resp.data['results'] resp = token_client.get( '/api/v1/organizers/{}/events/{}/invoices/?number={}'.format( organizer.slug, event.slug, invoice.number)) assert [res] == resp.data['results'] resp = token_client.get( '/api/v1/organizers/{}/events/{}/invoices/?number=XXX'.format( organizer.slug, event.slug)) assert [] == resp.data['results'] resp = token_client.get( '/api/v1/organizers/{}/events/{}/invoices/?locale=en'.format( organizer.slug, event.slug)) assert [res] == resp.data['results'] resp = token_client.get( '/api/v1/organizers/{}/events/{}/invoices/?locale=de'.format( organizer.slug, event.slug)) assert [] == resp.data['results'] ic = generate_cancellation(invoice) resp = token_client.get( '/api/v1/organizers/{}/events/{}/invoices/?is_cancellation=false'. format(organizer.slug, event.slug)) assert [res] == resp.data['results'] resp = token_client.get( '/api/v1/organizers/{}/events/{}/invoices/?is_cancellation=true'. format(organizer.slug, event.slug)) assert len(resp.data['results']) == 1 assert resp.data['results'][0]['number'] == ic.number resp = token_client.get( '/api/v1/organizers/{}/events/{}/invoices/?refers={}'.format( organizer.slug, event.slug, invoice.number)) assert len(resp.data['results']) == 1 assert resp.data['results'][0]['number'] == ic.number resp = token_client.get( '/api/v1/organizers/{}/events/{}/invoices/?refers={}'.format( organizer.slug, event.slug, ic.number)) assert [] == resp.data['results']
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 mark_order_refunded(order, user=None): """ Mark this order as refunded. This sets the payment status and returns the order object. :param order: The order to change :param user: The user that performed the change """ if isinstance(order, int): order = Order.objects.get(pk=order) if isinstance(user, int): user = User.objects.get(pk=user) with order.event.lock(): order.status = Order.STATUS_REFUNDED order.save() order.log_action('pretix.event.order.refunded', user=user) i = order.invoices.filter(is_cancellation=False).last() if i: generate_cancellation(i) return order
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 cancel_order(order, user=None): """ Mark this order as canceled :param order: The order to change :param user: The user that performed the change """ if isinstance(order, int): order = Order.objects.get(pk=order) if isinstance(user, int): user = User.objects.get(pk=user) with order.event.lock(): if order.status not in (Order.STATUS_PENDING, Order.STATUS_EXPIRED): raise OrderError(_('You cannot cancel this order')) order.status = Order.STATUS_CANCELLED order.save() order.log_action('pretix.event.order.cancelled', user=user) i = order.invoices.filter(is_cancellation=False).last() if i: generate_cancellation(i) return order
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 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 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 _reissue_invoice(self): i = self.order.invoices.filter(is_cancellation=False).last() if i: generate_cancellation(i) generate_invoice(self.order)
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 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) with transaction.atomic(): 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) self.order.save(update_fields=['total']) 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_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, 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 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)