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 test_campaign_events(self): url = reverse('api.v2.campaign_events') self.assertEndpointAccess(url) flow = self.create_flow() reporters = self.create_group("Reporters", [self.joe, self.frank]) registration = ContactField.get_or_create(self.org, self.admin, 'registration', "Registration") campaign1 = Campaign.create(self.org, self.admin, "Reminders", reporters) event1 = CampaignEvent.create_message_event(self.org, self.admin, campaign1, registration, 1, CampaignEvent.UNIT_DAYS, "Don't forget to brush your teeth") campaign2 = Campaign.create(self.org, self.admin, "Notifications", reporters) event2 = CampaignEvent.create_flow_event(self.org, self.admin, campaign2, registration, 6, CampaignEvent.UNIT_HOURS, flow, delivery_hour=12) # create event for another org joined = ContactField.get_or_create(self.org2, self.admin2, 'joined', "Joined On") spammers = ContactGroup.get_or_create(self.org2, self.admin2, "Spammers") spam = Campaign.create(self.org2, self.admin2, "Cool stuff", spammers) CampaignEvent.create_flow_event(self.org2, self.admin2, spam, joined, 6, CampaignEvent.UNIT_HOURS, flow, delivery_hour=12) # no filtering with self.assertNumQueries(NUM_BASE_REQUEST_QUERIES + 4): response = self.fetchJSON(url) self.assertEqual(response.status_code, 200) self.assertEqual(response.json['next'], None) self.assertResultsByUUID(response, [event2, event1]) self.assertEqual(response.json['results'][0], { 'uuid': event2.uuid, 'campaign': {'uuid': campaign2.uuid, 'name': "Notifications"}, 'relative_to': {'key': "registration", 'label': "Registration"}, 'offset': 6, 'unit': 'hours', 'delivery_hour': 12, 'flow': {'uuid': flow.uuid, 'name': "Color Flow"}, 'message': None, 'created_on': format_datetime(event2.created_on) }) # filter by UUID response = self.fetchJSON(url, 'uuid=%s' % event1.uuid) self.assertResultsByUUID(response, [event1]) # filter by campaign name response = self.fetchJSON(url, 'campaign=Reminders') self.assertResultsByUUID(response, [event1]) # filter by campaign UUID response = self.fetchJSON(url, 'campaign=%s' % campaign1.uuid) self.assertResultsByUUID(response, [event1]) # filter by invalid campaign response = self.fetchJSON(url, 'campaign=invalid') self.assertResultsByUUID(response, [])
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 create_campaigns(self, spec, org, user): self._log(f"Creating {len(spec['campaigns'])} campaigns... ") for c in spec["campaigns"]: group = ContactGroup.all_groups.get(org=org, name=c["group"]) campaign = Campaign.objects.create( name=c["name"], group=group, is_archived=False, org=org, created_by=user, modified_by=user, uuid=c["uuid"], ) for e in c.get("events", []): field = ContactField.all_fields.get(org=org, key=e["offset_field"]) if "flow" in e: flow = Flow.objects.get(org=org, name=e["flow"]) CampaignEvent.create_flow_event( org, user, campaign, field, e["offset"], e["offset_unit"], flow, delivery_hour=e.get("delivery_hour", -1), start_mode=e["start_mode"], ) else: evt = CampaignEvent.create_message_event( org, user, campaign, field, e["offset"], e["offset_unit"], e["message"], delivery_hour=e.get("delivery_hour", -1), base_language=e["base_language"], start_mode=e["start_mode"], ) evt.flow.uuid = e["uuid"] evt.flow.save() self._log(self.style.SUCCESS("OK") + "\n")
def setUp(self): super().setUp() self.planting_date = ContactField.get_or_create( self.org, self.admin, "planting_date", "Planting Date", value_type=Value.TYPE_DATETIME ) self.contact = self.create_contact("Ben Haggerty", number="+12065552020") self.contact.set_field(self.admin, "planting_date", "2018-06-23T13:48:12.123456Z") # create a campaign with a message event 1 day after planting date self.farmers = self.create_group("Farmers", [self.contact]) self.campaign = Campaign.create(self.org, self.admin, "Planting Reminders", self.farmers) self.event = CampaignEvent.create_message_event( self.org, self.admin, self.campaign, relative_to=self.planting_date, offset=1, unit="D", message={ "eng": "Hi @(upper(contact.name)) don't forget to plant on @(format_date(contact.planting_date))" }, base_language="eng", )
def test_from_event_fire(self): flow = self.get_flow("color_v13") group = self.create_group("Reporters", contacts=[]) registered = self.create_field("registered", "Registered", value_type="D") campaign = Campaign.create(self.org, self.admin, "Welcomes", group) event = CampaignEvent.create_flow_event( self.org, self.user, campaign, registered, offset=1, unit="W", flow=flow ) contact = self.create_contact("Jim", phone="0979111111") fire = EventFire.objects.create( event=event, contact=contact, scheduled=timezone.now(), fired=timezone.now(), fired_result=EventFire.RESULT_FIRED, ) self.assertEqual( { "type": "campaign_fired", "created_on": fire.fired.isoformat(), "campaign": {"id": campaign.id, "name": "Welcomes", "uuid": campaign.uuid}, "campaign_event": { "id": event.id, "offset_display": "1 week after", "relative_to": {"key": "registered", "name": "Registered"}, }, "fired_result": "F", }, Event.from_event_fire(self.org, self.admin, fire), )
def create_event(event_spec, notification, campaign): org = notification.org_dest user = notification.created_by relative_to = ContactField.get_or_create( org, user, key=event_spec["relative_to"]["key"], label=event_spec["relative_to"]["label"], value_type="D", ) # create our message flow for message events if event_spec["event_type"] == CampaignEvent.TYPE_MESSAGE: message = event_spec["message"] base_language = event_spec.get("base_language") if not isinstance(message, dict): try: message = json.loads(message) except ValueError: # if it's not a language dict, turn it into one message = dict(base=message) base_language = "base" event = CampaignEvent.create_message_event( org, user, campaign, relative_to, event_spec["offset"], event_spec["unit"], message, event_spec["delivery_hour"], base_language=base_language, ) event.update_flow_name() else: flow = Flow.objects.filter(org=org, is_active=True, name=event_spec["flow"]["name"]).last() if flow: CampaignEvent.create_flow_event( org, user, campaign, relative_to, event_spec["offset"], event_spec["unit"], flow, event_spec["delivery_hour"], )
def create_campaigns(self, orgs): """ Creates the campaigns for each org """ self._log("Creating %d campaigns... " % (len(orgs) * len(CAMPAIGNS))) for org in orgs: user = org.cache["users"][0] for c in CAMPAIGNS: group = ContactGroup.all_groups.get(org=org, name=c["group"]) campaign = Campaign.objects.create(name=c["name"], group=group, is_archived=False, org=org, created_by=user, modified_by=user) for e in c.get("events", []): field = ContactField.all_fields.get(org=org, key=e["offset_field"]) if "flow" in e: flow = Flow.objects.get(org=org, name=e["flow"]) CampaignEvent.create_flow_event( org, user, campaign, field, e["offset"], e["offset_unit"], flow, delivery_hour=e.get("delivery_hour", -1), ) else: CampaignEvent.create_message_event( org, user, campaign, field, e["offset"], e["offset_unit"], e["message"], delivery_hour=e.get("delivery_hour", -1), base_language=e["base_language"], ) self._log(self.style.SUCCESS("OK") + "\n")
def test_verbose_name_plural(self): flow = self.create_flow() group = self.create_group("Testers", contacts=[]) self.assertEqual("Flows", verbose_name_plural(flow)) self.assertEqual("Groups", verbose_name_plural(group)) self.assertEqual("Campaigns", verbose_name_plural(Campaign())) self.assertEqual("Campaign Events", verbose_name_plural(CampaignEvent()))
def create_campaigns(self, orgs): """ Creates the campaigns for each org """ self._log("Creating %d campaigns... " % (len(orgs) * len(CAMPAIGNS))) for org in orgs: user = org.cache["users"][0] for c in CAMPAIGNS: group = ContactGroup.all_groups.get(org=org, name=c["group"]) campaign = Campaign.objects.create( name=c["name"], group=group, is_archived=False, org=org, created_by=user, modified_by=user ) for e in c.get("events", []): field = ContactField.all_fields.get(org=org, key=e["offset_field"]) if "flow" in e: flow = Flow.objects.get(org=org, name=e["flow"]) CampaignEvent.create_flow_event( org, user, campaign, field, e["offset"], e["offset_unit"], flow, delivery_hour=e.get("delivery_hour", -1), ) else: CampaignEvent.create_message_event( org, user, campaign, field, e["offset"], e["offset_unit"], e["message"], delivery_hour=e.get("delivery_hour", -1), base_language=e["base_language"], ) self._log(self.style.SUCCESS("OK") + "\n")
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 = CampaignEvent.create_single_message_flow(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 = CampaignEvent.create_single_message_flow(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 test_object_class_plural(self): self.assertEqual("Flow", object_class_name(Flow())) self.assertEqual("Campaign", object_class_name(Campaign())) self.assertEqual("CampaignEvent", object_class_name(CampaignEvent())) self.assertEqual("Trigger", object_class_name(Trigger()))
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