class CampaignEventReadSerializer(ReadSerializer): UNITS = extract_constants(CampaignEvent.UNIT_CONFIG) campaign = fields.CampaignField() flow = serializers.SerializerMethodField() relative_to = fields.ContactFieldField() unit = serializers.SerializerMethodField() created_on = serializers.DateTimeField(default_timezone=pytz.UTC) def get_flow(self, obj): if obj.event_type == CampaignEvent.TYPE_FLOW: return {"uuid": obj.flow.uuid, "name": obj.flow.name} else: return None def get_unit(self, obj): return self.UNITS.get(obj.unit) class Meta: model = CampaignEvent fields = ( "uuid", "campaign", "relative_to", "offset", "unit", "delivery_hour", "flow", "message", "created_on", )
class ContactFieldWriteSerializer(WriteSerializer): VALUE_TYPES = extract_constants(Value.TYPE_CONFIG, reverse=True) label = serializers.CharField( required=True, max_length=ContactField.MAX_LABEL_LEN, validators=[ UniqueForOrgValidator( ContactField.user_fields.filter(is_active=True), ignore_case=True) ], ) value_type = serializers.ChoiceField(required=True, choices=list(VALUE_TYPES.keys())) def validate_label(self, value): if not ContactField.is_valid_label(value): raise serializers.ValidationError( "Can only contain letters, numbers and hypens.") key = ContactField.make_key(value) if not ContactField.is_valid_key(key): raise serializers.ValidationError( 'Generated key "%s" is invalid or a reserved name.' % key) return value def validate_value_type(self, value): return self.VALUE_TYPES.get(value) def validate(self, data): field_count = ContactField.user_fields.count_active_for_org( org=self.context["org"]) if not self.instance and field_count >= settings.MAX_ACTIVE_CONTACTFIELDS_PER_ORG: raise serializers.ValidationError( "This org has %s contact fields and the limit is %s. " "You must delete existing ones before you can " "create new ones." % (field_count, settings.MAX_ACTIVE_CONTACTFIELDS_PER_ORG)) return data def save(self): label = self.validated_data.get("label") value_type = self.validated_data.get("value_type") if self.instance: key = self.instance.key else: key = ContactField.make_key(label) return ContactField.get_or_create(self.context["org"], self.context["user"], key, label, value_type=value_type)
class ContactFieldReadSerializer(ReadSerializer): VALUE_TYPES = extract_constants(Value.TYPE_CONFIG) value_type = serializers.SerializerMethodField() def get_value_type(self, obj): return self.VALUE_TYPES.get(obj.value_type) class Meta: model = ContactField fields = ("key", "label", "value_type")
class ContactGroupReadSerializer(ReadSerializer): status = serializers.SerializerMethodField() count = serializers.SerializerMethodField() STATUSES = extract_constants(ContactGroup.STATUS_CONFIG) def get_status(self, obj): return self.STATUSES[obj.status] def get_count(self, obj): # count may be cached on the object return obj.count if hasattr(obj, "count") else obj.get_member_count() class Meta: model = ContactGroup fields = ("uuid", "name", "query", "status", "count")
class ChannelEventReadSerializer(ReadSerializer): TYPES = extract_constants(ChannelEvent.TYPE_CONFIG) type = serializers.SerializerMethodField() contact = fields.ContactField() channel = fields.ChannelField() extra = serializers.SerializerMethodField() def get_type(self, obj): return self.TYPES.get(obj.event_type) def get_extra(self, obj): return obj.extra class Meta: model = ChannelEvent fields = ("id", "type", "contact", "channel", "extra", "occurred_on", "created_on")
class CampaignEventWriteSerializer(WriteSerializer): UNITS = extract_constants(CampaignEvent.UNIT_CONFIG, reverse=True) campaign = fields.CampaignField(required=True) offset = serializers.IntegerField(required=True) unit = serializers.ChoiceField(required=True, choices=list(UNITS.keys())) delivery_hour = serializers.IntegerField(required=True, min_value=-1, max_value=23) relative_to = fields.ContactFieldField(required=True) message = fields.TranslatableField(required=False, max_length=Msg.MAX_TEXT_LEN) flow = fields.FlowField(required=False) new_expressions = serializers.BooleanField(required=False, default=False) def validate_unit(self, value): return self.UNITS[value] def validate_campaign(self, value): if self.instance and value and self.instance.campaign != value: raise serializers.ValidationError( "Cannot change campaign for existing events") return value def validate(self, data): message = data.get("message") flow = data.get("flow") if message and not flow: translations, base_language = message if not translations[base_language]: raise serializers.ValidationError("Message text is required") if (message and flow) or (not message and not flow): raise serializers.ValidationError( "Flow UUID or a message text required.") return data def save(self): """ Create or update our campaign event """ campaign = self.validated_data.get("campaign") offset = self.validated_data.get("offset") unit = self.validated_data.get("unit") delivery_hour = self.validated_data.get("delivery_hour") relative_to = self.validated_data.get("relative_to") message = self.validated_data.get("message") flow = self.validated_data.get("flow") if self.instance: # we dont update, we only create self.instance = self.instance.deactivate_and_copy() # we are being set to a flow if flow: self.instance.flow = flow self.instance.event_type = CampaignEvent.TYPE_FLOW self.instance.message = None # we are being set to a message else: translations, base_language = message if not self.validated_data["new_expressions"]: translations = migrate_translations(translations) self.instance.message = translations # if we aren't currently a message event, we need to create our hidden message flow if self.instance.event_type != CampaignEvent.TYPE_MESSAGE: self.instance.flow = Flow.create_single_message( self.context["org"], self.context["user"], translations, base_language) self.instance.event_type = CampaignEvent.TYPE_MESSAGE # otherwise, we can just update that flow else: # set our single message on our flow self.instance.flow.update_single_message_flow( self.context["user"], translations, base_language) # update our other attributes self.instance.offset = offset self.instance.unit = unit self.instance.delivery_hour = delivery_hour self.instance.relative_to = relative_to self.instance.save() self.instance.update_flow_name() else: if flow: self.instance = CampaignEvent.create_flow_event( self.context["org"], self.context["user"], campaign, relative_to, offset, unit, flow, delivery_hour) else: translations, base_language = message if not self.validated_data["new_expressions"]: translations = migrate_translations(translations) self.instance = CampaignEvent.create_message_event( self.context["org"], self.context["user"], campaign, relative_to, offset, unit, translations, delivery_hour, base_language, ) self.instance.update_flow_name() # create our event fires for this event in the background EventFire.create_eventfires_for_event(self.instance) return self.instance