# # This file is part of pretix (Community Edition). # # Copyright (C) 2014-2020 Raphael Michel and contributors # Copyright (C) 2020-2021 rami.io GmbH and contributors # # This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General # Public License as published by the Free Software Foundation in version 3 of the License. # # ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are # applicable granting you additional permissions and placing additional restrictions on your usage of this software. # Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive # this file, see . # # This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more # details. # # You should have received a copy of the GNU Affero General Public License along with this program. If not, see # . # import logging from functools import cached_property from django.db import models from django.utils.translation import ( gettext as _, gettext_lazy, ngettext_lazy, pgettext_lazy, ) from pretix.base.models import Event, Order, OrderPosition logger = logging.getLogger(__name__) MODE_OVERWRITE = "overwrite" MODE_SET_IF_NEW = "if_new" MODE_SET_IF_EMPTY = "if_empty" MODE_APPEND_LIST = "append" class OrderSyncQueue(models.Model): order = models.ForeignKey( Order, on_delete=models.CASCADE, related_name="queued_sync_jobs" ) event = models.ForeignKey( Event, on_delete=models.CASCADE, related_name="queued_sync_jobs" ) sync_provider = models.CharField(blank=False, null=False, max_length=128) triggered_by = models.CharField(blank=False, null=False, max_length=128) triggered = models.DateTimeField(blank=False, null=False, auto_now_add=True) failed_attempts = models.PositiveIntegerField(default=0) not_before = models.DateTimeField(blank=False, null=False, db_index=True) need_manual_retry = models.CharField(blank=True, null=True, choices=[ ('recoverable', _('Temporary error, auto-retry limit exceeded')), ('unrecoverable', _('Misconfiguration, please check provider settings')), ('unhandled', _('System error, needs manual intervention')) ]) class Meta: unique_together = (("order", "sync_provider"),) ordering = ("triggered",) @cached_property def _provider_class_info(self): from pretix.base.datasync.datasync import sync_targets return sync_targets.get(identifier=self.sync_provider) @property def provider_class(self): return self._provider_class_info[0] @property def is_provider_active(self): return self._provider_class_info[1] @property def max_retry_attempts(self): return self.provider_class.max_attempts class OrderSyncResult(models.Model): order = models.ForeignKey( Order, on_delete=models.CASCADE, related_name="sync_results" ) sync_provider = models.CharField(blank=False, null=False, max_length=128) order_position = models.ForeignKey( OrderPosition, on_delete=models.CASCADE, related_name="sync_results", blank=True, null=True, ) external_object_type = models.CharField(blank=False, null=False, max_length=128) external_id_field = models.CharField(blank=False, null=False, max_length=128) id_value = models.CharField(blank=False, null=False, max_length=128) external_link_href = models.CharField(blank=True, null=True, max_length=255) external_link_display_name = models.CharField(blank=True, null=True, max_length=255) transmitted = models.DateTimeField(blank=False, null=False, auto_now_add=True) class Meta: indexes = [ models.Index(fields=("order", "sync_provider")), ] def external_link_html(self): if not self.external_link_display_name: return None from pretix.base.datasync.datasync import sync_targets prov, meta = sync_targets.get(identifier=self.sync_provider) if prov: return prov.get_external_link_html(self.order.event, self.external_link_href, self.external_link_display_name)