Esempio n. 1
0
    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
Esempio n. 2
0
    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, [])
Esempio n. 3
0
    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
Esempio n. 4
0
    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")
Esempio n. 5
0
    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",
        )
Esempio n. 6
0
    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),
        )
Esempio n. 7
0
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"],
            )
Esempio n. 8
0
    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")
Esempio n. 9
0
    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()))
Esempio n. 10
0
    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")
Esempio n. 11
0
    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
Esempio n. 12
0
    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
Esempio n. 13
0
 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()))
Esempio n. 14
0
    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