text: import copy
  from django.dispatch import receiver
  from django.urls import resolve, reverse
  from django.utils.safestring import mark_safe
  from django.utils.translation import gettext_noop, ugettext_lazy as _
  from i18nfield.rest_framework import I18nField
  from i18nfield.strings import LazyI18nString
  from pretix.base.settings import settings_hierarkey
  from pretix.base.signals import (
      api_event_settings_fields,
      checkin_created,
      event_copy_data,
      item_copy_data,
      logentry_display,
  )
  from pretix.control.signals import item_forms, nav_event_settings
  from rest_framework import serializers
  
  from pretix_vacc_autosched.tasks import schedule_second_dose
  
  from .forms import ItemConfigForm
  from .models import ItemConfig
  
  
  @receiver(nav_event_settings, dispatch_uid="vacc_autosched_nav")
  def navbar_info(sender, request, **kwargs):
      url = resolve(request.path_info)
      if not request.user.has_event_permission(
          request.organizer, request.event, "can_change_event_settings", request=request
      ):
          return []
      return [
          {
              "label": _("Vaccination scheduling"),
              "url": reverse(
                  "plugins:pretix_vacc_autosched:settings",
                  kwargs={
                      "event": request.event.slug,
                      "organizer": request.organizer.slug,
                  },
              ),
              "active": url.namespace == "plugins:pretix_vacc_autosched",
          }
      ]
  
  
  @receiver(item_forms, dispatch_uid="vacc_autosched_item_forms")
  def control_item_forms(sender, request, item, **kwargs):
      try:
          inst = ItemConfig.objects.get(item=item)
      except ItemConfig.DoesNotExist:
          inst = ItemConfig(item=item)
      return ItemConfigForm(
          instance=inst,
          event=sender,
          data=(request.POST if request.method == "POST" else None),
          prefix="vacc_autosched_conf",
      )
  
  
  @receiver(item_copy_data, dispatch_uid="vacc_autosched_item_copy")
  def copy_item(sender, source, target, **kwargs):
      try:
          inst = ItemConfig.objects.get(item=source)
          inst = copy.copy(inst)
          inst.pk = None
          inst.item = target
          inst.save()
      except ItemConfig.DoesNotExist:
          pass
  
  
  @receiver(signal=event_copy_data, dispatch_uid="vacc_autosched_copy_data")
  def event_copy_data_receiver(sender, other, question_map, item_map, **kwargs):
      for ip in ItemConfig.objects.filter(item__event=other):
          ip = copy.copy(ip)
          ip.pk = None
          ip.item = item_map[ip.item_id]
          ip.save()
  
  
  @receiver(signal=checkin_created, dispatch_uid="vacc_autosched_checkin_created")
  def checkin_created_receiver(sender, checkin, **kwargs):
      if checkin.list.name.startswith("Print"):
          return  # ignore, not a "real" check-in
      if not sender.settings.vacc_autosched_checkin:
          return  # ignore, handled manually
  
      try:
          ItemConfig.objects.get(item=checkin.position.item)
      except ItemConfig.DoesNotExist:
          return  # ignore, not configured
  
      schedule_second_dose.apply_async(
          args=(
              sender.pk,
              checkin.position.pk,
          )
      )
  
  
  @receiver(
      signal=api_event_settings_fields,
      dispatch_uid="vacc_autosched_api_event_settings_fields",
  )
  def recv_api_event_settings_fields(sender, **kwargs):
      return {
          "vacc_autosched_checkin": serializers.BooleanField(required=False),
          "vacc_autosched_mail": serializers.BooleanField(required=False),
          "vacc_autosched_subject": I18nField(required=False),
          "vacc_autosched_body": I18nField(required=False),
          "vacc_autosched_sms": serializers.BooleanField(required=False),
          "vacc_autosched_sms_text": I18nField(required=False),
          "vacc_autosched_self_service": serializers.BooleanField(required=False),
          "vacc_autosched_self_service_info": I18nField(required=False),
          "vacc_autosched_self_service_order_info": I18nField(required=False),
      }
  
  
  @receiver(signal=logentry_display, dispatch_uid="vacc_autosched_logentry_display")
  def badges_logentry_display(sender, logentry, **kwargs):
      if not logentry.action_type.startswith("pretix_vacc_autosched."):
          return
  
      d = logentry.parsed_data
      if logentry.action_type == "pretix_vacc_autosched.failed":
          return _("Automatic scheduling of second dose failed: {reason}").format(
              reason=d.get("reason")
          )
      if logentry.action_type == "pretix_vacc_autosched.scheduled":
          url = reverse(
              "control:event.order",
              kwargs={
                  "event": d.get("event_slug"),
                  "organizer": logentry.organizer.slug,
                  "code": d.get("order"),
              },
          )
          return mark_safe(
              _("Second dose scheduled automatically: {order}").format(
                  order='<a href="{}">{}</a>'.format(url, d.get("order")),
              )
          )
      if logentry.action_type == "pretix_vacc_autosched.created":
          url = reverse(
              "control:event.order",
              kwargs={
                  "event": d.get("event_slug"),
                  "organizer": logentry.organizer.slug,
                  "code": d.get("order"),
              },
          )
          return mark_safe(
              _(
                  "This order has been scheduled as the second dose for order {order}"
              ).format(
                  order='<a href="{}">{}</a>'.format(url, d.get("order")),
              )
          )
  
  
  settings_hierarkey.add_default("vacc_autosched_mail", False, bool)
  settings_hierarkey.add_default("vacc_autosched_self_service", False, bool)
  settings_hierarkey.add_default(
      "vacc_autosched_self_service_info",
      "",
      LazyI18nString,
  )
  settings_hierarkey.add_default(
      "vacc_autosched_self_service_order_info",
      "",
      LazyI18nString,
  )
  settings_hierarkey.add_default(
      "vacc_autosched_subject",
      LazyI18nString.from_gettext(gettext_noop("Your second dose: {scheduled_datetime}")),
      LazyI18nString,
  )
  settings_hierarkey.add_default(
      "vacc_autosched_body",
      LazyI18nString.from_gettext(
          gettext_noop(
              "Hello,\n\n"
              "we scheduled your second dose for {scheduled_datetime}.\n\n"
              "Please find additional information in your ticket attached.\n\n"
              "Best regards,\n"
              "Your {event} team"
          )
      ),
      LazyI18nString,
  )
  settings_hierarkey.add_default("vacc_autosched_sms", False, bool)
  settings_hierarkey.add_default(
      "vacc_autosched_sms_text",
      LazyI18nString.from_gettext(
          gettext_noop(
              "Hello,\n\n"
              "we scheduled your second dose for {scheduled_datetime}.\n\n"
              "Please find additional information here: {url}.\n\n"
          )
      ),
      LazyI18nString,
  )
  settings_hierarkey.add_default("vacc_autosched_checkin", True, bool)
  