class Survey(models.Model): """ The Labour Manager may have their Workers fill in a Survey some time after signing up. The driving use case for these Surveys is to ask for shift wishes some time before the event. A Survey requires a Model and a Form. The Model is requested to return an instance via Model.for_signup(signup) and it is passed to the Form via initialize_form(Form, request, instance=instance, event=event). """ event = models.ForeignKey('core.Event', on_delete=models.CASCADE) slug = models.CharField(**NONUNIQUE_SLUG_FIELD_PARAMS) title = models.CharField( max_length=255, verbose_name=_('Title'), help_text=_('Will be displayed at the top of the survey page.'), ) description = models.TextField( verbose_name=_('Description'), help_text=_('Will be displayed at the top of the survey page.'), ) active_from = models.DateTimeField( null=True, blank=True, verbose_name=_('Active from'), ) active_until = models.DateTimeField( null=True, blank=True, verbose_name=_('Active until'), ) form_class_path = models.CharField( max_length=255, verbose_name=_('Form path'), help_text=_( 'A reference to the form that is used as the survey form.'), ) form_class = code_property('form_class_path') override_does_not_apply_message = models.TextField( default='', verbose_name=_('Message when denied access'), help_text=_( "This message will be shown to the user when they attempt to access a query they don't" "have access to."), ) def __str__(self): return self.title @property def is_active(self): return is_within_period(self.active_from, self.active_until) @property def does_not_apply_message(self): if self.override_does_not_apply_message: return self.override_does_not_apply_message else: return _('This survey does not apply to you.') def admin_is_active(self): return self.is_active admin_is_active.short_description = _('Active') admin_is_active.boolean = True class Meta: verbose_name = _('Survey') verbose_name_plural = _('Surveys') unique_together = [ ('event', 'slug'), ]
class Subscription(models.Model): """ Channels: * `email` - e-mail will be sent to `user` * `callback` - the callback specified in `callback_code` will be called (for testing mostly). """ user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) entry_type = models.CharField(max_length=255) channel = models.CharField( max_length=max(len(key) for (key, label) in CHANNEL_CHOICES), default='email', choices=CHANNEL_CHOICES, ) active = models.BooleanField(default=True) event_filter = models.ForeignKey( 'core.Event', on_delete=models.CASCADE, null=True, blank=True, verbose_name=_('Event filter'), help_text= _('When specified, only entries related to this event will match the subscription.' ), ) event_survey_filter = models.ForeignKey( 'surveys.EventSurvey', on_delete=models.CASCADE, null=True, blank=True, verbose_name=_('Event survey filter'), help_text= _('When specified, only entries related to this EventSurvey will match the subscription.' ), ) job_category_filter = models.ForeignKey( 'labour.JobCategory', on_delete=models.CASCADE, null=True, blank=True, verbose_name=_('Job category filter'), help_text= _('When specified, only entries related to this JobCategory will match the subscription.' ), ) callback_code = models.CharField( max_length=255, blank=True, default='', verbose_name=_('Callback function'), help_text= _('Code path to a callback function. Only used when channel=callback. Eg. event_log.tests:test_callback.' ), ) callback = code_property('callback_code') def send_update_for_entry(self, entry): assert self.active if 'background_tasks' in settings.INSTALLED_APPS: from ..tasks import subscription_send_update_for_entry subscription_send_update_for_entry.delay(self.id, entry.id) else: self._send_update_for_entry(entry) def _send_update_for_entry(self, entry): channels[self.channel].send_update_for_entry(self, entry) def clean(self): if self.callback_code and self.channel != 'callback': raise ValidationError( _('The callback field must only be used when the channel is "callback".' )) @property def recipient_name_and_email(self): full_name = self.user.get_full_name() if full_name: return '{full_name} <{email}>'.format( full_name=full_name, email=self.user.email, ) else: return self.user.email @classmethod def get_or_create_dummy(cls, entry_type=None, **kwargs): from .entry_type_metadata import EntryTypeMetadata from core.models import Person if entry_type is None: entry_type, unused = EntryTypeMetadata.get_or_create_dummy() entry_type = entry_type.name person, unused = Person.get_or_create_dummy() attrs = dict( entry_type=entry_type, user=person.user, ) attrs.update(kwargs) return cls.objects.get_or_create(**attrs) class Meta: verbose_name = _('subscription') verbose_name_plural = _('subscriptions') index_together = [ ('entry_type', 'active'), ]