def pre_save(self, request, obj): # if it's before, negate the offset if self.cleaned_data['direction'] == 'B': obj.offset = -obj.offset if self.cleaned_data['unit'] == 'H' or self.cleaned_data[ 'unit'] == 'M': # pragma: needs cover obj.delivery_hour = -1 # if its a message flow, set that accordingly if self.cleaned_data['event_type'] == CampaignEvent.TYPE_MESSAGE: message_dict = {} for language in self.languages: iso_code = language.language['iso_code'] message_dict[iso_code] = self.cleaned_data.get(iso_code, '') if not obj.flow_id or not obj.flow.is_active or obj.flow.flow_type != Flow.MESSAGE: obj.flow = Flow.create_single_message(request.user.get_org(), request.user, message_dict) # set our single message on our flow obj.flow.update_single_message_flow(message_dict) obj.message = json.dumps(message_dict) # otherwise, it's an event that runs an existing flow else: obj.flow = Flow.objects.get(pk=self.cleaned_data['flow_to_start'])
def pre_save(self, request, obj): org = self.user.get_org() # if it's before, negate the offset if self.cleaned_data["direction"] == "B": obj.offset = -obj.offset if self.cleaned_data["unit"] == "H" or self.cleaned_data["unit"] == "M": # pragma: needs cover obj.delivery_hour = -1 # if its a message flow, set that accordingly if self.cleaned_data["event_type"] == CampaignEvent.TYPE_MESSAGE: if self.instance.id: base_language = self.instance.flow.base_language else: base_language = org.primary_language.iso_code if org.primary_language else "base" translations = {} for language in self.languages: iso_code = language.language["iso_code"] translations[iso_code] = self.cleaned_data.get(iso_code, "") if not obj.flow_id or not obj.flow.is_active or not obj.flow.is_system: obj.flow = Flow.create_single_message(org, request.user, translations, base_language=base_language) else: # set our single message on our flow obj.flow.update_single_message_flow(translations, base_language) obj.message = translations obj.full_clean() # otherwise, it's an event that runs an existing flow else: obj.flow = Flow.objects.get(org=org, id=self.cleaned_data["flow_to_start"])
def create_message_event(cls, org, user, campaign, relative_to, offset, unit, message, delivery_hour=-1, base_language=None): if campaign.org != org: # pragma: no cover raise ValueError("Org mismatch") if isinstance(message, six.string_types): base_language = org.primary_language.iso_code if org.primary_language else 'base' message = {base_language: message} flow = Flow.create_single_message(org, user, message, base_language) return cls.objects.create(campaign=campaign, relative_to=relative_to, offset=offset, unit=unit, event_type=cls.TYPE_MESSAGE, message=message, flow=flow, delivery_hour=delivery_hour, created_by=user, modified_by=user)
def create_message_event( cls, org, user, campaign, relative_to, offset, unit, message, delivery_hour=-1, base_language=None ): if campaign.org != org: raise ValueError("Org mismatch") if relative_to.value_type != Value.TYPE_DATETIME: raise ValueError( f"Contact fields for CampaignEvents must have a datetime type, got {relative_to.value_type}." ) if isinstance(message, str): base_language = org.primary_language.iso_code if org.primary_language else "base" message = {base_language: message} flow = Flow.create_single_message(org, user, message, base_language) return cls.objects.create( campaign=campaign, relative_to=relative_to, offset=offset, unit=unit, event_type=cls.TYPE_MESSAGE, message=message, flow=flow, delivery_hour=delivery_hour, created_by=user, modified_by=user, )
def pre_save(self, request, obj): org = self.user.get_org() # if it's before, negate the offset if self.cleaned_data["direction"] == "B": obj.offset = -obj.offset if self.cleaned_data["unit"] == "H" or self.cleaned_data["unit"] == "M": # pragma: needs cover obj.delivery_hour = -1 # if its a message flow, set that accordingly if self.cleaned_data["event_type"] == CampaignEvent.TYPE_MESSAGE: if self.instance.id: base_language = self.instance.flow.base_language else: base_language = org.primary_language.iso_code if org.primary_language else "base" translations = {} for language in self.languages: iso_code = language.language["iso_code"] translations[iso_code] = self.cleaned_data.get(iso_code, "") if not obj.flow_id or not obj.flow.is_active or obj.flow.flow_type != Flow.MESSAGE: obj.flow = Flow.create_single_message(org, request.user, translations, base_language=base_language) else: # set our single message on our flow obj.flow.update_single_message_flow(translations, base_language) obj.message = translations obj.full_clean() # otherwise, it's an event that runs an existing flow else: obj.flow = Flow.objects.get(org=org, id=self.cleaned_data["flow_to_start"])
def create_message_event(cls, org, user, campaign, relative_to, offset, unit, message, delivery_hour=-1): if campaign.org != org: # pragma: no cover raise ValueError("Org mismatch") flow = Flow.create_single_message(org, user, message) if isinstance(message, dict): message = json.dumps(message) return cls.objects.create(campaign=campaign, relative_to=relative_to, offset=offset, unit=unit, event_type=cls.TYPE_MESSAGE, message=message, flow=flow, delivery_hour=delivery_hour, created_by=user, modified_by=user)
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 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 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( 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 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() return self.instance
def create_message_event(cls, org, user, campaign, relative_to, offset, unit, message, delivery_hour=-1): if campaign.org != org: # pragma: no cover raise ValueError("Org mismatch") flow = Flow.create_single_message(org, user, message) return cls.objects.create(campaign=campaign, relative_to=relative_to, offset=offset, unit=unit, event_type=MESSAGE_EVENT, message=message, flow=flow, delivery_hour=delivery_hour, created_by=user, modified_by=user)
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 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: self.instance.message = message # 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'], message) 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(message=message) # 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: self.instance = CampaignEvent.create_message_event(self.context['org'], self.context['user'], campaign, relative_to, offset, unit, message, delivery_hour) self.instance.update_flow_name() return self.instance
def pre_save(self, request, obj): org = self.user.get_org() # if it's before, negate the offset if self.cleaned_data["direction"] == "B": obj.offset = -obj.offset if self.cleaned_data["unit"] == "H" or self.cleaned_data["unit"] == "M": # pragma: needs cover obj.delivery_hour = -1 # if its a message flow, set that accordingly if self.cleaned_data["event_type"] == CampaignEvent.TYPE_MESSAGE: if self.instance.id: base_language = self.instance.flow.base_language else: base_language = org.flow_languages[0] if org.flow_languages else "base" translations = {} for language in self.languages: iso_code = language.language["iso_code"] if iso_code in self.cleaned_data and self.cleaned_data.get(iso_code, "").strip(): translations[iso_code] = self.cleaned_data.get(iso_code, "").strip() if not obj.flow_id or not obj.flow.is_active or not obj.flow.is_system: obj.flow = Flow.create_single_message(org, request.user, translations, base_language=base_language) else: # set our single message on our flow obj.flow.update_single_message_flow(self.user, translations, base_language) obj.message = translations obj.full_clean() obj.start_mode = self.cleaned_data["message_start_mode"] # otherwise, it's an event that runs an existing flow else: obj.flow = self.cleaned_data["flow_to_start"] obj.start_mode = self.cleaned_data["flow_start_mode"] # force passive mode for user-selected background flows if obj.flow.flow_type == Flow.TYPE_BACKGROUND: obj.start_mode = CampaignEvent.MODE_PASSIVE
def create_message_event( cls, org, user, campaign, relative_to, offset, unit, message, delivery_hour=-1, base_language=None, start_mode=MODE_INTERRUPT, ): if campaign.org != org: raise ValueError("Org mismatch") if relative_to.value_type != ContactField.TYPE_DATETIME: raise ValueError( f"Contact fields for CampaignEvents must have a datetime type, got {relative_to.value_type}." ) if isinstance(message, str): base_language = org.flow_languages[ 0] if org.flow_languages else "base" message = {base_language: message} flow = Flow.create_single_message(org, user, message, base_language) return cls.objects.create( campaign=campaign, relative_to=relative_to, offset=offset, unit=unit, event_type=cls.TYPE_MESSAGE, message=message, flow=flow, delivery_hour=delivery_hour, start_mode=start_mode, created_by=user, modified_by=user, )
def pre_save(self, request, obj): # if it's before, negate the offset if self.cleaned_data['direction'] == 'B': obj.offset = -obj.offset if self.cleaned_data['unit'] == 'H' or self.cleaned_data['unit'] == 'M': obj.delivery_hour = -1 # if its a message flow, set that accordingly if self.cleaned_data['event_type'] == 'M': if not obj.flow_id or not obj.flow.is_active or obj.flow.flow_type != Flow.MESSAGE: obj.flow = Flow.create_single_message(request.user.get_org(), request.user, self.cleaned_data['message']) # set our single message on our flow obj.flow.update_single_message_flow(message=self.cleaned_data['message']) obj.message = self.cleaned_data['message'] # otherwise, it's an event that runs an existing flow else: obj.flow = Flow.objects.get(pk=self.cleaned_data['flow_to_start'])
def pre_save(self, request, obj): # if it's before, negate the offset if self.cleaned_data['direction'] == 'B': obj.offset = -obj.offset if self.cleaned_data['unit'] == 'H' or self.cleaned_data['unit'] == 'M': obj.delivery_hour = -1 # if its a message flow, set that accordingly if self.cleaned_data['event_type'] == 'M': if not obj.flow_id or not obj.flow.is_active or obj.flow.flow_type != Flow.MESSAGE: obj.flow = Flow.create_single_message(request.user.get_org(), request.user, self.cleaned_data['message']) # set our single message on our flow obj.flow.update_single_message_flow(message=self.cleaned_data['message']) obj.message = self.cleaned_data['message'] # otherwise, it's an event that runs an existing flow else: obj.flow = Flow.objects.get(pk=self.cleaned_data['flow_to_start'])
def import_campaigns(cls, exported_json, org, user, site=None): """ Import campaigns from our export file """ from temba.orgs.models import EARLIEST_IMPORT_VERSION if exported_json.get('version', 0) < EARLIEST_IMPORT_VERSION: raise ValueError( _("Unknown version (%s)" % exported_json.get('version', 0))) if 'campaigns' in exported_json: for campaign_spec in exported_json['campaigns']: name = campaign_spec['name'] campaign = None group = None # first check if we have the objects by id if site and site == exported_json.get('site', None): group = ContactGroup.user_groups.filter( id=campaign_spec['group']['id'], org=org, is_active=True).first() if group: group.name = campaign_spec['group']['name'] group.save() campaign = Campaign.objects.filter( org=org, id=campaign_spec['id']).first() if campaign: campaign.name = Campaign.get_unique_name( name, org, ignore=campaign) campaign.save() # fall back to lookups by name if not group: group = ContactGroup.user_groups.filter( name=campaign_spec['group']['name'], org=org).first() if not campaign: campaign = Campaign.objects.filter(org=org, name=name).first() # all else fails, create the objects from scratch if not group: group = ContactGroup.create(org, user, campaign_spec['group']['name']) if not campaign: campaign = Campaign.objects.create( name=Campaign.get_unique_name(name, org), org=org, group=group, created_by=user, modified_by=user) else: campaign.group = group campaign.save() # we want to nuke old single message flows for event in campaign.events.all(): if event.flow.flow_type == Flow.MESSAGE: event.flow.delete() # and all of the events, we'll recreate these campaign.events.all().delete() # fill our campaign with events for event_spec in campaign_spec['events']: relative_to = ContactField.get_or_create( org, key=event_spec['relative_to']['key'], label=event_spec['relative_to']['label']) # create our message flow for message events if event_spec['event_type'] == MESSAGE_EVENT: flow = Flow.create_single_message( org, user, event_spec['message']) else: flow = Flow.objects.filter( org=org, id=event_spec['flow']['id']).first() if flow: event = campaign.events.create( created_by=user, modified_by=user, offset=event_spec['offset'], unit=event_spec['unit'], event_type=event_spec['event_type'], delivery_hour=event_spec['delivery_hour'], message=event_spec['message'], flow=flow, relative_to=relative_to) event.update_flow_name() # update our scheduled events for this campaign EventFire.update_campaign_events(campaign)
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 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(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 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
def import_campaigns(cls, exported_json, org, user, site=None): """ Import campaigns from our export file """ from temba.orgs.models import EARLIEST_IMPORT_VERSION if exported_json.get('version', 0) < EARLIEST_IMPORT_VERSION: raise ValueError(_("Unknown version (%s)" % exported_json.get('version', 0))) if 'campaigns' in exported_json: for campaign_spec in exported_json['campaigns']: name = campaign_spec['name'] campaign = None group = None # first check if we have the objects by id if site and site == exported_json.get('site', None): group = ContactGroup.user_groups.filter(id=campaign_spec['group']['id'], org=org, is_active=True).first() if group: group.name = campaign_spec['group']['name'] group.save() campaign = Campaign.objects.filter(org=org, id=campaign_spec['id']).first() if campaign: campaign.name = Campaign.get_unique_name(name, org, ignore=campaign) campaign.save() # fall back to lookups by name if not group: group = ContactGroup.user_groups.filter(name=campaign_spec['group']['name'], org=org).first() if not campaign: campaign = Campaign.objects.filter(org=org, name=name).first() # all else fails, create the objects from scratch if not group: group = ContactGroup.create(org, user, campaign_spec['group']['name']) if not campaign: campaign = Campaign.objects.create(name=Campaign.get_unique_name(name, org), org=org, group=group, created_by=user, modified_by=user) else: campaign.group = group campaign.save() # we want to nuke old single message flows for event in campaign.events.all(): if event.flow.flow_type == Flow.MESSAGE: event.flow.delete() # and all of the events, we'll recreate these campaign.events.all().delete() # fill our campaign with events for event_spec in campaign_spec['events']: relative_to = ContactField.get_or_create(org, key=event_spec['relative_to']['key'], label=event_spec['relative_to']['label']) # create our message flow for message events if event_spec['event_type'] == MESSAGE_EVENT: flow = Flow.create_single_message(org, user, event_spec['message']) else: flow = Flow.objects.filter(org=org, id=event_spec['flow']['id']).first() if flow: event = campaign.events.create(created_by=user, modified_by=user, offset=event_spec['offset'], unit=event_spec['unit'], event_type=event_spec['event_type'], delivery_hour=event_spec['delivery_hour'], message=event_spec['message'], flow=flow, relative_to=relative_to) event.update_flow_name() # update our scheduled events for this campaign EventFire.update_campaign_events(campaign)
def restore_object(self, attrs, instance=None): """ Create or update our campaign """ if instance: # pragma: no cover raise ValidationError("Invalid operation") org = self.user.get_org() # parse our arguments message = attrs.get('message', None) flow = attrs.get('flow', None) if not message and not flow: raise ValidationError("Must specify either a flow or a message for the event") if message and flow: raise ValidationError("You cannot set both a flow and a message on an event, it must be only one") campaign_id = attrs.get('campaign', None) event_id = attrs.get('event', None) if not campaign_id and not event_id: raise ValidationError("You must specify either a campaign to create a new event, or an event to update") offset = attrs.get('offset') unit = attrs.get('unit') delivery_hour = attrs.get('delivery_hour') relative_to = attrs.get('relative_to') # load our contact field existing_field = ContactField.objects.filter(label=relative_to, org=org, is_active=True) if not existing_field: relative_to_field = ContactField.get_or_create(org, ContactField.make_key(relative_to), relative_to) else: relative_to_field = existing_field[0] if 'event' in attrs: event = CampaignEvent.objects.get(pk=attrs['event'], is_active=True, campaign__org=org) # we are being set to a flow if 'flow' in attrs: flow = Flow.objects.get(pk=attrs['flow'], is_active=True, org=org) event.flow = flow event.event_type = FLOW_EVENT event.message = None # we are being set to a message else: event.message = attrs['message'] # if we aren't currently a message event, we need to create our hidden message flow if event.event_type != MESSAGE_EVENT: event.flow = Flow.create_single_message(org, self.user, event.message) event.event_type = MESSAGE_EVENT # otherwise, we can just update that flow else: # set our single message on our flow event.flow.update_single_message_flow(message=attrs['message']) # update our other attributes event.offset = offset event.unit = unit event.delivery_hour = delivery_hour event.relative_to = relative_to_field event.save() event.update_flow_name() else: campaign = Campaign.objects.get(pk=attrs['campaign'], is_active=True, org=org) event_type = MESSAGE_EVENT if 'flow' in attrs: flow = Flow.objects.get(pk=attrs['flow'], is_active=True, org=org) event_type = FLOW_EVENT else: flow = Flow.create_single_message(org, self.user, message) event = CampaignEvent.objects.create(campaign=campaign, relative_to=relative_to_field, offset=offset, unit=unit, event_type=event_type, flow=flow, message=message, created_by=self.user, modified_by=self.user) event.update_flow_name() return event
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
def restore_object(self, attrs, instance=None): """ Create or update our campaign """ if instance: # pragma: no cover raise ValidationError("Invalid operation") org = self.user.get_org() # parse our arguments message = attrs.get('message', None) flow = attrs.get('flow', None) if not message and not flow: raise ValidationError( "Must specify either a flow or a message for the event") if message and flow: raise ValidationError( "You cannot set both a flow and a message on an event, it must be only one" ) campaign_id = attrs.get('campaign', None) event_id = attrs.get('event', None) if not campaign_id and not event_id: raise ValidationError( "You must specify either a campaign to create a new event, or an event to update" ) offset = attrs.get('offset') unit = attrs.get('unit') delivery_hour = attrs.get('delivery_hour') relative_to = attrs.get('relative_to') # load our contact field existing_field = ContactField.objects.filter(label=relative_to, org=org, is_active=True) if not existing_field: relative_to_field = ContactField.get_or_create( org, ContactField.make_key(relative_to), relative_to) else: relative_to_field = existing_field[0] if 'event' in attrs: event = CampaignEvent.objects.get(pk=attrs['event'], is_active=True, campaign__org=org) # we are being set to a flow if 'flow' in attrs: flow = Flow.objects.get(pk=attrs['flow'], is_active=True, org=org) event.flow = flow event.event_type = FLOW_EVENT event.message = None # we are being set to a message else: event.message = attrs['message'] # if we aren't currently a message event, we need to create our hidden message flow if event.event_type != MESSAGE_EVENT: event.flow = Flow.create_single_message( org, self.user, event.message) event.event_type = MESSAGE_EVENT # otherwise, we can just update that flow else: # set our single message on our flow event.flow.update_single_message_flow( message=attrs['message']) # update our other attributes event.offset = offset event.unit = unit event.delivery_hour = delivery_hour event.relative_to = relative_to_field event.save() event.update_flow_name() else: campaign = Campaign.objects.get(pk=attrs['campaign'], is_active=True, org=org) event_type = MESSAGE_EVENT if 'flow' in attrs: flow = Flow.objects.get(pk=attrs['flow'], is_active=True, org=org) event_type = FLOW_EVENT else: flow = Flow.create_single_message(org, self.user, message) event = CampaignEvent.objects.create(campaign=campaign, relative_to=relative_to_field, offset=offset, unit=unit, event_type=event_type, flow=flow, message=message, created_by=self.user, modified_by=self.user) event.update_flow_name() return event