def issues(self): issues = [] has_paid_things = (Item.objects.filter(event=self.request.event, default_price__gt=0).exists() or ItemVariation.objects.filter( item__event=self.request.event, default_price__gt=0).exists()) has_payment_provider = False responses = register_payment_providers.send(self.request.event) for receiver, response in responses: provider = response(self.request.event) if provider.is_enabled and provider.identifier != 'free': has_payment_provider = True break if has_paid_things and not has_payment_provider: issues.append( _('You have configured at least one paid product but have not enabled any payment methods.' )) if not self.request.event.quotas.exists(): issues.append( _('You need to configure at least one quota to sell anything.') ) return issues
def get_all_payment_providers(): global PAYMENT_PROVIDERS if PAYMENT_PROVIDERS: return PAYMENT_PROVIDERS with rolledback_transaction(): event = Event.objects.create( plugins=",".join([app.name for app in apps.get_app_configs()]), name="INTERNAL", date_from=now(), organizer=Organizer.objects.create(name="INTERNAL") ) provs = register_payment_providers.send( sender=event ) choices = [] for recv, prov in provs: if isinstance(prov, list): for p in prov: p = p(event) if not p.is_meta: choices.append((p.identifier, p.verbose_name)) else: prov = prov(event) if not prov.is_meta: choices.append((prov.identifier, prov.verbose_name)) PAYMENT_PROVIDERS = choices return choices
def generate_invoice(order: Order): locale = order.event.settings.get('invoice_language') if locale: if locale == '__user__': locale = order.locale with language(locale): i = Invoice(order=order, event=order.event) i.invoice_from = order.event.settings.get('invoice_address_from') i.additional_text = order.event.settings.get('invoice_additional_text') try: addr_template = pgettext( "invoice", """{i.company} {i.name} {i.street} {i.zipcode} {i.city} {i.country}""") i.invoice_to = addr_template.format( i=order.invoice_address).strip() if order.invoice_address.vat_id: i.invoice_to += "\n" + pgettext( "invoice", "VAT-ID: %s") % order.invoice_address.vat_id except InvoiceAddress.DoesNotExist: i.invoice_to = "" i.date = date.today() i.locale = locale i.save() responses = register_payment_providers.send(order.event) for receiver, response in responses: provider = response(order.event) if provider.identifier == order.payment_provider: payment_provider = provider break for p in order.positions.all(): desc = str(p.item.name) if p.variation: desc += " - " + str(p.variation.value) InvoiceLine.objects.create(invoice=i, description=desc, gross_value=p.price, tax_value=p.tax_value, tax_rate=p.tax_rate) if order.payment_fee: InvoiceLine.objects.create( invoice=i, description=_('Payment via {method}').format( method=str(payment_provider.verbose_name)), gross_value=order.payment_fee, tax_value=order.payment_fee_tax_value, tax_rate=order.payment_fee_tax_rate) invoice_pdf(i.pk) return i
def _get_payment_provider(self): responses = register_payment_providers.send(self.order.event) pprov = None for rec, response in responses: provider = response(self.order.event) if provider.identifier == self.order.payment_provider: return provider if not pprov: raise OrderError(error_messages['internal'])
def _perform_order(event: str, payment_provider: str, position_ids: List[str], email: str, locale: str, address: int): event = Event.objects.get(id=event) responses = register_payment_providers.send(event) pprov = None for rec, response in responses: provider = response(event) if provider.identifier == payment_provider: pprov = provider if not pprov: raise OrderError(error_messages['internal']) dt = now() with event.lock(): positions = list(CartPosition.objects.filter( id__in=position_ids).select_related('item', 'variation')) if len(position_ids) != len(positions): raise OrderError(error_messages['internal']) _check_positions(event, dt, positions) order = _create_order(event, email, positions, dt, pprov, locale=locale) if address is not None: try: addr = InvoiceAddress.objects.get( pk=address ) if addr.order is not None: addr.pk = None addr.order = order addr.save() except InvoiceAddress.DoesNotExist: pass if event.settings.get('invoice_generate') == 'True': generate_invoice(order) with language(order.locale): mail( order.email, _('Your order: %(code)s') % {'code': order.code}, event.settings.mail_text_order_placed, { 'total': LazyNumber(order.total), 'currency': event.currency, 'date': LazyDate(order.expires), 'event': event.name, 'url': build_absolute_uri(event, 'presale:event.order', kwargs={ 'order': order.code, 'secret': order.secret }), 'paymentinfo': str(pprov.order_pending_mail_render(order)) }, event, locale=order.locale ) return order.id
def get_payment_fee(self, total): payment_fee = 0 if 'payment' in self.request.session: responses = register_payment_providers.send(self.request.event) for receiver, response in responses: provider = response(self.request.event) if provider.identifier == self.request.session['payment']: payment_fee = provider.calculate_fee(total) return payment_fee
def get_payment_providers(self): providers = [] responses = register_payment_providers.send(self.request.event) for receiver, response in responses: provider = response(self.request.event) providers.append({ 'name': provider.identifier, 'verbose_name': provider.verbose_name }) return providers
def build_invoice(invoice: Invoice) -> Invoice: with language(invoice.locale): responses = register_payment_providers.send(invoice.event) for receiver, response in responses: provider = response(invoice.event) if provider.identifier == invoice.order.payment_provider: payment_provider = provider break invoice.invoice_from = invoice.event.settings.get('invoice_address_from') introductory = invoice.event.settings.get('invoice_introductory_text', as_type=LazyI18nString) additional = invoice.event.settings.get('invoice_additional_text', as_type=LazyI18nString) footer = invoice.event.settings.get('invoice_footer_text', as_type=LazyI18nString) payment = payment_provider.render_invoice_text(invoice.order) invoice.introductory_text = str(introductory).replace('\n', '<br />') invoice.additional_text = str(additional).replace('\n', '<br />') invoice.footer_text = str(footer) invoice.payment_provider_text = str(payment).replace('\n', '<br />') try: addr_template = pgettext("invoice", """{i.company} {i.name} {i.street} {i.zipcode} {i.city} {i.country}""") invoice.invoice_to = addr_template.format(i=invoice.order.invoice_address).strip() if invoice.order.invoice_address.vat_id: invoice.invoice_to += "\n" + pgettext("invoice", "VAT-ID: %s") % invoice.order.invoice_address.vat_id except InvoiceAddress.DoesNotExist: invoice.invoice_to = "" invoice.file = None invoice.save() invoice.lines.all().delete() for p in invoice.order.positions.all(): desc = str(p.item.name) if p.variation: desc += " - " + str(p.variation.value) InvoiceLine.objects.create( invoice=invoice, description=desc, gross_value=p.price, tax_value=p.tax_value, tax_rate=p.tax_rate ) if invoice.order.payment_fee: InvoiceLine.objects.create( invoice=invoice, description=_('Payment via {method}').format(method=str(payment_provider.verbose_name)), gross_value=invoice.order.payment_fee, tax_value=invoice.order.payment_fee_tax_value, tax_rate=invoice.order.payment_fee_tax_rate ) return invoice
def get_payment_fee(self, total): if total == 0: return Decimal("0.00") payment_fee = 0 if "payment" in self.request.session: responses = register_payment_providers.send(self.request.event) for receiver, response in responses: provider = response(self.request.event) if provider.identifier == self.request.session["payment"]: payment_fee = provider.calculate_fee(total) return payment_fee
def generate_invoice(order: Order): locale = order.event.settings.get('invoice_language') if locale: if locale == '__user__': locale = order.locale with language(locale): i = Invoice(order=order, event=order.event) i.invoice_from = order.event.settings.get('invoice_address_from') i.additional_text = order.event.settings.get('invoice_additional_text') try: addr_template = pgettext("invoice", """{i.company} {i.name} {i.street} {i.zipcode} {i.city} {i.country}""") i.invoice_to = addr_template.format(i=order.invoice_address).strip() if order.invoice_address.vat_id: i.invoice_to += "\n" + pgettext("invoice", "VAT-ID: %s") % order.invoice_address.vat_id except InvoiceAddress.DoesNotExist: i.invoice_to = "" i.date = date.today() i.locale = locale i.save() responses = register_payment_providers.send(order.event) for receiver, response in responses: provider = response(order.event) if provider.identifier == order.payment_provider: payment_provider = provider break for p in order.positions.all(): desc = str(p.item.name) if p.variation: desc += " - " + str(p.variation.value) InvoiceLine.objects.create( invoice=i, description=desc, gross_value=p.price, tax_value=p.tax_value, tax_rate=p.tax_rate ) if order.payment_fee: InvoiceLine.objects.create( invoice=i, description=_('Payment via {method}').format(method=str(payment_provider.verbose_name)), gross_value=order.payment_fee, tax_value=order.payment_fee_tax_value, tax_rate=order.payment_fee_tax_rate ) invoice_pdf(i.pk) return i
def _perform_order(event: str, payment_provider: str, position_ids: List[str], email: str, locale: str): 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) mail(order.email, _('Your order: %(code)s') % {'code': order.code}, event.settings.mail_text_order_placed, { 'total': LazyNumber(order.total), 'currency': event.currency, 'date': LazyDate(order.expires), 'event': event.name, 'url': build_absolute_uri(event, 'presale:event.order', kwargs={ 'order': order.code, 'secret': order.secret }), 'paymentinfo': str(pprov.order_pending_mail_render(order)) }, event, locale=order.locale) return order.id
def provider_forms(self): providers = [] responses = register_payment_providers.send(self.request.event) for receiver, response in responses: provider = response(self.request.event) if not provider.is_enabled or not provider.is_allowed(self.request): continue fee = provider.calculate_fee(self._total_order_value) providers.append({ 'provider': provider, 'fee': fee, 'form': provider.payment_form_render(self.request), }) return providers
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(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 mail( order.email, _('Your order: %(code)s') % {'code': order.code}, mailtext, { 'total': LazyNumber(order.total), 'currency': event.currency, 'date': LazyDate(order.expires), 'event': event.name, 'url': build_absolute_uri(event, 'presale:event.order', kwargs={ 'order': order.code, 'secret': order.secret }), 'paymentinfo': str(pprov.order_pending_mail_render(order)) }, event, locale=order.locale ) return order.id
def _perform_order(event: str, payment_provider: str, position_ids: List[str], email: str, locale: str, address: int): event = Event.objects.get(id=event) responses = register_payment_providers.send(event) pprov = None for rec, response in responses: provider = response(event) if provider.identifier == payment_provider: pprov = provider if not pprov: raise OrderError(error_messages['internal']) with event.lock() as now_dt: positions = list(CartPosition.objects.filter( id__in=position_ids).select_related('item', 'variation')) if len(position_ids) != len(positions): raise OrderError(error_messages['internal']) _check_positions(event, now_dt, positions) order = _create_order(event, email, positions, now_dt, pprov, locale=locale, address=address) if event.settings.get('invoice_generate') == 'True' and invoice_qualified(order): if not order.invoices.exists(): generate_invoice(order) with language(order.locale): if order.total == Decimal('0.00'): mailtext = event.settings.mail_text_order_free else: mailtext = event.settings.mail_text_order_placed mail( order.email, _('Your order: %(code)s') % {'code': order.code}, mailtext, { 'total': LazyNumber(order.total), 'currency': event.currency, 'date': LazyDate(order.expires), 'event': event.name, 'url': build_absolute_uri(event, 'presale:event.order', kwargs={ 'order': order.code, 'secret': order.secret }), 'paymentinfo': str(pprov.order_pending_mail_render(order)) }, event, locale=order.locale ) return order.id
def provider_forms(self): providers = [] responses = register_payment_providers.send(self.request.event) for receiver, response in responses: provider = response(self.request.event) if not provider.is_enabled or not provider.is_allowed( self.request): continue fee = provider.calculate_fee(self._total_order_value) providers.append({ 'provider': provider, 'fee': fee, 'form': provider.payment_form_render(self.request) }) return providers
def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) ctx["order"] = self.order ctx["can_download"] = ( self.request.event.settings.ticket_download and ( self.request.event.settings.ticket_download_date is None or now() > self.request.event.settings.ticket_download_date ) and self.order.status == Order.STATUS_PAID ) ctx["download_buttons"] = self.download_buttons ctx["cart"] = self.get_cart( answers=True, queryset=OrderPosition.objects.filter(order=self.order), payment_fee=self.order.payment_fee, payment_fee_tax_rate=self.order.payment_fee_tax_rate, ) ctx["invoices"] = list(self.order.invoices.all()) ctx["can_generate_invoice"] = invoice_qualified(self.order) and ( self.request.event.settings.invoice_generate == "user" ) if self.order.status == Order.STATUS_PENDING: ctx["payment"] = self.payment_provider.order_pending_render(self.request, self.order) ctx["can_retry"] = ( self.payment_provider.order_can_retry(self.order) and self.payment_provider.is_enabled and self.order._can_be_paid() ) ctx["can_change_method"] = False responses = register_payment_providers.send(self.request.event) for receiver, response in responses: provider = response(self.request.event) if ( provider.identifier != self.order.payment_provider and provider.is_enabled and provider.order_change_allowed(self.order) ): ctx["can_change_method"] = True break elif self.order.status == Order.STATUS_PAID: ctx["payment"] = self.payment_provider.order_paid_render(self.request, self.order) ctx["can_retry"] = False return ctx
def _perform_order(event: str, payment_provider: str, position_ids: list, email: str, locale: str): event = Event.objects.current.get(identity=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.current.filter( identity__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) mail(order.email, _('Your order: %(code)s') % {'code': order.code}, 'pretixpresale/email/order_placed.txt', { 'order': order, 'event': event, 'url': build_absolute_uri(event, 'presale:event.order', kwargs={ 'order': order.code, 'secret': order.secret }), 'payment': pprov.order_pending_mail_render(order) }, event, locale=order.locale) return order.identity
def provider_forms(self): providers = [] responses = register_payment_providers.send(self.request.event) for receiver, response in responses: provider = response(self.request.event) if provider.identifier == self.order.payment_provider: continue if not provider.is_enabled or not provider.order_change_allowed(self.order): continue fee = provider.calculate_fee(self._total_order_value) providers.append({ 'provider': provider, 'fee': fee, 'fee_diff': fee - self.order.payment_fee, 'fee_diff_abs': abs(fee - self.order.payment_fee), 'total': abs(self._total_order_value + fee), 'form': provider.payment_form_render(self.request) }) return providers
def issues(self): issues = [] has_paid_things = ( Item.objects.filter(event=self.request.event, default_price__gt=0).exists() or ItemVariation.objects.filter(item__event=self.request.event, default_price__gt=0).exists() ) has_payment_provider = False responses = register_payment_providers.send(self.request.event) for receiver, response in responses: provider = response(self.request.event) if provider.is_enabled: has_payment_provider = True break if has_paid_things and not has_payment_provider: issues.append(_('You have configured at least one paid product but have not enabled any payment methods.')) return issues
def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) ctx['order'] = self.order ctx['can_download'] = ( self.request.event.settings.ticket_download and (self.request.event.settings.ticket_download_date is None or now() > self.request.event.settings.ticket_download_date) and self.order.status == Order.STATUS_PAID) ctx['download_buttons'] = self.download_buttons ctx['cart'] = self.get_cart( answers=True, downloads=ctx['can_download'], queryset=OrderPosition.objects.filter(order=self.order), payment_fee=self.order.payment_fee, payment_fee_tax_rate=self.order.payment_fee_tax_rate) ctx['invoices'] = list(self.order.invoices.all()) ctx['can_generate_invoice'] = invoice_qualified( self.order) and (self.request.event.settings.invoice_generate == 'user') if self.order.status == Order.STATUS_PENDING: ctx['payment'] = self.payment_provider.order_pending_render( self.request, self.order) ctx['can_retry'] = (self.payment_provider.order_can_retry( self.order) and self.payment_provider.is_enabled and self.order._can_be_paid()) ctx['can_change_method'] = False responses = register_payment_providers.send(self.request.event) for receiver, response in responses: provider = response(self.request.event) if (provider.identifier != self.order.payment_provider and provider.is_enabled and provider.order_change_allowed(self.order)): ctx['can_change_method'] = True break elif self.order.status == Order.STATUS_PAID: ctx['payment'] = self.payment_provider.order_paid_render( self.request, self.order) ctx['can_retry'] = False return ctx
def provider_forms(self) -> list: providers = [] responses = register_payment_providers.send(self.request.event) for receiver, response in responses: provider = response(self.request.event) provider.form = ProviderForm( obj=self.request.event, settingspref='payment_%s_' % provider.identifier, data=(self.request.POST if self.request.method == 'POST' else None)) provider.form.fields = OrderedDict([ ('payment_%s_%s' % (provider.identifier, k), v) for k, v in provider.settings_form_fields.items() ]) provider.settings_content = provider.settings_content_render( self.request) provider.form.prepare_fields() if provider.settings_content or provider.form.fields: # Exclude providers which do not provide any settings providers.append(provider) return providers
def provider_forms(self) -> list: providers = [] responses = register_payment_providers.send(self.request.event) for receiver, response in responses: provider = response(self.request.event) provider.form = ProviderForm( obj=self.request.event, settingspref='payment_%s_' % provider.identifier, data=(self.request.POST if self.request.method == 'POST' else None) ) provider.form.fields = OrderedDict( [ ('payment_%s_%s' % (provider.identifier, k), v) for k, v in provider.settings_form_fields.items() ] ) provider.settings_content = provider.settings_content_render(self.request) provider.form.prepare_fields() if provider.settings_content or provider.form.fields: # Exclude providers which do not provide any settings providers.append(provider) return providers
def _perform_order(event: Event, payment_provider: BasePaymentProvider, position_ids: list, email: str, locale: str): event = Event.objects.current.get(identity=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.current.filter( identity__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) mail( order.email, _('Your order: %(code)s') % {'code': order.code}, 'pretixpresale/email/order_placed.txt', { 'order': order, 'event': event, 'url': build_absolute_uri('presale:event.order', kwargs={ 'event': event.slug, 'organizer': event.organizer.slug, 'order': order.code, 'secret': order.secret }), 'payment': pprov.order_pending_mail_render(order) }, event, locale=order.locale ) return order.identity
def payment_provider(self): responses = register_payment_providers.send(self.request.event) for receiver, response in responses: provider = response(self.request.event) if provider.identifier == self.order.payment_provider: return provider
def order_overview(event: Event) -> Tuple[List[Tuple[ItemCategory, List[Item]]], Dict[str, Tuple[Decimal, Decimal]]]: items = event.items.all().select_related( 'category', # for re-grouping ).order_by('category__position', 'category_id', 'name') num_total = { (p['item'], p['variation']): (p['cnt'], p['price']) for p in (OrderPosition.objects .filter(order__event=event, order__status__in=[Order.STATUS_PENDING, Order.STATUS_EXPIRED, Order.STATUS_PAID]) .values('item', 'variation') .annotate(cnt=Count('id'), price=Sum('price')).order_by()) } num_canceled = { (p['item'], p['variation']): (p['cnt'], p['price']) for p in (OrderPosition.objects .filter(order__event=event, order__status=Order.STATUS_CANCELED) .values('item', 'variation') .annotate(cnt=Count('id'), price=Sum('price')).order_by()) } num_refunded = { (p['item'], p['variation']): (p['cnt'], p['price']) for p in (OrderPosition.objects .filter(order__event=event, order__status=Order.STATUS_REFUNDED) .values('item', 'variation') .annotate(cnt=Count('id'), price=Sum('price')).order_by()) } num_pending = { (p['item'], p['variation']): (p['cnt'], p['price']) for p in (OrderPosition.objects .filter(order__event=event, order__status__in=(Order.STATUS_PENDING, Order.STATUS_EXPIRED)) .values('item', 'variation') .annotate(cnt=Count('id'), price=Sum('price')).order_by()) } num_paid = { (p['item'], p['variation']): (p['cnt'], p['price']) for p in (OrderPosition.objects .filter(order__event=event, order__status=Order.STATUS_PAID) .values('item', 'variation') .annotate(cnt=Count('id'), price=Sum('price')).order_by()) } for item in items: item.all_variations = list(item.variations.all()) item.has_variations = (len(item.all_variations) > 0) if item.has_variations: for var in item.all_variations: variid = var.id var.num_total = num_total.get((item.id, variid), (0, 0)) var.num_pending = num_pending.get((item.id, variid), (0, 0)) var.num_canceled = num_canceled.get((item.id, variid), (0, 0)) var.num_refunded = num_refunded.get((item.id, variid), (0, 0)) var.num_paid = num_paid.get((item.id, variid), (0, 0)) item.num_total = tuplesum(var.num_total for var in item.all_variations) item.num_pending = tuplesum(var.num_pending for var in item.all_variations) item.num_canceled = tuplesum(var.num_canceled for var in item.all_variations) item.num_refunded = tuplesum(var.num_refunded for var in item.all_variations) item.num_paid = tuplesum(var.num_paid for var in item.all_variations) else: item.num_total = num_total.get((item.id, None), (0, 0)) item.num_pending = num_pending.get((item.id, None), (0, 0)) item.num_canceled = num_canceled.get((item.id, None), (0, 0)) item.num_refunded = num_refunded.get((item.id, None), (0, 0)) item.num_paid = num_paid.get((item.id, None), (0, 0)) nonecat = ItemCategory(name=_('Uncategorized')) # Regroup those by category items_by_category = sorted( [ # a group is a tuple of a category and a list of items (cat if cat is not None else nonecat, [i for i in items if i.category == cat]) for cat in set([i.category for i in items]) # insert categories into a set for uniqueness # a set is unsorted, so sort again by category ], key=lambda group: (group[0].position, group[0].id) if ( group[0] is not None and group[0].id is not None) else (0, 0) ) for c in items_by_category: c[0].num_total = tuplesum(item.num_total for item in c[1]) print(c[1], c[0].num_total, [item.num_total for item in c[1]]) c[0].num_pending = tuplesum(item.num_pending for item in c[1]) c[0].num_canceled = tuplesum(item.num_canceled for item in c[1]) c[0].num_refunded = tuplesum(item.num_refunded for item in c[1]) c[0].num_paid = tuplesum(item.num_paid for item in c[1]) # Payment fees payment_cat_obj = DummyObject() payment_cat_obj.name = _('Payment method fees') payment_items = [] num_total = { o['payment_provider']: (o['cnt'], o['payment_fee']) for o in (Order.objects .filter(event=event) .values('payment_provider') .annotate(cnt=Count('id'), payment_fee=Sum('payment_fee')).order_by()) } num_canceled = { o['payment_provider']: (o['cnt'], o['payment_fee']) for o in (Order.objects .filter(event=event, status=Order.STATUS_CANCELED) .values('payment_provider') .annotate(cnt=Count('id'), payment_fee=Sum('payment_fee')).order_by()) } num_refunded = { o['payment_provider']: (o['cnt'], o['payment_fee']) for o in (Order.objects .filter(event=event, status=Order.STATUS_REFUNDED) .values('payment_provider') .annotate(cnt=Count('id'), payment_fee=Sum('payment_fee')).order_by()) } num_pending = { o['payment_provider']: (o['cnt'], o['payment_fee']) for o in (Order.objects .filter(event=event, status__in=(Order.STATUS_PENDING, Order.STATUS_EXPIRED)) .values('payment_provider') .annotate(cnt=Count('id'), payment_fee=Sum('payment_fee')).order_by()) } num_paid = { o['payment_provider']: (o['cnt'], o['payment_fee']) for o in (Order.objects .filter(event=event, status=Order.STATUS_PAID) .values('payment_provider') .annotate(cnt=Count('id'), payment_fee=Sum('payment_fee')).order_by()) } provider_names = {} responses = register_payment_providers.send(event) for receiver, response in responses: provider = response(event) provider_names[provider.identifier] = provider.verbose_name for pprov, total in num_total.items(): ppobj = DummyObject() ppobj.name = provider_names.get(pprov, pprov) ppobj.provider = pprov ppobj.has_variations = False ppobj.num_total = total ppobj.num_canceled = num_canceled.get(pprov, (0, 0)) ppobj.num_refunded = num_refunded.get(pprov, (0, 0)) ppobj.num_pending = num_pending.get(pprov, (0, 0)) ppobj.num_paid = num_paid.get(pprov, (0, 0)) payment_items.append(ppobj) payment_cat_obj.num_total = (Dontsum(''), sum(i.num_total[1] for i in payment_items)) payment_cat_obj.num_canceled = (Dontsum(''), sum(i.num_canceled[1] for i in payment_items)) payment_cat_obj.num_refunded = (Dontsum(''), sum(i.num_refunded[1] for i in payment_items)) payment_cat_obj.num_pending = (Dontsum(''), sum(i.num_pending[1] for i in payment_items)) payment_cat_obj.num_paid = (Dontsum(''), sum(i.num_paid[1] for i in payment_items)) payment_cat = (payment_cat_obj, payment_items) items_by_category.append(payment_cat) total = { 'num_total': tuplesum(c.num_total for c, i in items_by_category), 'num_pending': tuplesum(c.num_pending for c, i in items_by_category), 'num_canceled': tuplesum(c.num_canceled for c, i in items_by_category), 'num_refunded': tuplesum(c.num_refunded for c, i in items_by_category), 'num_paid': tuplesum(c.num_paid for c, i in items_by_category) } return items_by_category, total