Beispiel #1
0
    def test_incident_started(self):
        self.org.add_user(self.editor, OrgRole.ADMINISTRATOR)  # upgrade editor to administrator

        Incident.flagged(self.org)

        self.assert_notifications(
            expected_json={
                "type": "incident:started",
                "created_on": matchers.ISODate(),
                "target_url": "/incident/",
                "is_seen": False,
                "incident": {
                    "type": "org:flagged",
                    "started_on": matchers.ISODate(),
                    "ended_on": None,
                },
            },
            expected_users={self.editor, self.admin},
            email=False,
        )

        # if a user visits the incident page, all incident notifications are now read
        self.login(self.editor)
        self.client.get("/incident/")

        self.assertTrue(self.editor.notifications.get().is_seen)
        self.assertFalse(self.admin.notifications.get().is_seen)
Beispiel #2
0
    def test_from_flow_run(self):
        contact = self.create_contact("Jim", phone="0979111111")
        flow = self.get_flow("color_v13")
        nodes = flow.get_definition()["nodes"]
        (MockSessionWriter(contact, flow).visit(nodes[0]).send_msg(
            "What is your favorite color?", self.channel).wait().save())
        run = contact.runs.get()

        self.assertEqual(
            {
                "type": "flow_entered",
                "created_on": matchers.ISODate(),
                "flow": {
                    "uuid": str(flow.uuid),
                    "name": "Colors"
                },
                "logs_url": None,
            },
            Event.from_flow_run(self.org, self.admin, run),
        )

        # customer support get access to logs
        self.assertEqual(
            {
                "type": "flow_entered",
                "created_on": matchers.ISODate(),
                "flow": {
                    "uuid": str(flow.uuid),
                    "name": "Colors"
                },
                "logs_url": f"/flowsession/json/{run.session.uuid}/",
            },
            Event.from_flow_run(self.org, self.customer_support, run),
        )
Beispiel #3
0
    def test_list(self):
        list_url = reverse("notifications.notification_list")

        # simulate an export finishing
        export = ExportContactsTask.create(self.org, self.editor)
        Notification.export_finished(export)

        # not access for anon
        self.assertLoginRedirect(self.client.get(list_url))

        # check for user with no notifications
        self.login(self.user)
        response = self.client.get(list_url)
        self.assertEqual({"results": []}, response.json())

        # check for editor who should have an export completed notification
        self.login(self.editor)
        response = self.client.get(list_url)
        self.assertEqual(
            {
                "results": [{
                    "type": "export:finished",
                    "created_on": matchers.ISODate(),
                    "target_url":
                    f"/assets/download/contact_export/{export.id}/",
                    "is_seen": False,
                    "export": {
                        "type": "contact"
                    },
                }]
            },
            response.json(),
        )
Beispiel #4
0
    def test_queue_interrupt_by_session(self):
        jim = self.create_contact("Jim", "+12065551212")

        flow = self.get_flow("favorites")
        flow_nodes = flow.as_json()["nodes"]
        color_prompt = flow_nodes[0]
        color_split = flow_nodes[2]

        (MockSessionWriter(jim, flow).visit(color_prompt).send_msg(
            "What is your favorite color?",
            self.channel).visit(color_split).wait().save())

        run = FlowRun.objects.get(contact=jim)
        session = run.session
        run.release("U")

        self.assert_org_queued(self.org, "batch")
        self.assert_queued_batch_task(
            self.org,
            {
                "type": "interrupt_sessions",
                "org_id": self.org.id,
                "task": {
                    "session_ids": [session.id]
                },
                "queued_on": matchers.ISODate(),
            },
        )
Beispiel #5
0
    def test_message_export_finished(self):
        export = ExportMessagesTask.create(self.org,
                                           self.editor,
                                           system_label="I")
        export.perform()

        Notification.export_finished(export)

        self.assertFalse(
            self.editor.notifications.get(message_export=export).is_seen)

        # we only notify the user that started the export
        self.assert_notifications(
            after=export.created_on,
            expected_json={
                "type": "export:finished",
                "created_on": matchers.ISODate(),
                "target_url": f"/assets/download/message_export/{export.id}/",
                "is_seen": False,
                "export": {
                    "type": "message"
                },
            },
            expected_users={self.editor},
            email=True,
        )

        send_notification_emails()

        self.assertEqual(1, len(mail.outbox))
        self.assertEqual("[Temba] Your message export is ready",
                         mail.outbox[0].subject)
        self.assertEqual(["*****@*****.**"], mail.outbox[0].recipients())
Beispiel #6
0
    def test_import_finished(self):
        imp = ContactImport.objects.create(
            org=self.org, mappings={}, num_records=5, created_by=self.editor, modified_by=self.editor
        )

        # mailroom will create these notifications when it's complete
        Notification._create_all(
            imp.org, "import:finished", scope=f"contact:{imp.id}", users=[self.editor], contact_import=imp
        )
        self.assertFalse(self.editor.notifications.get(contact_import=imp).is_seen)

        # we only notify the user that started the import
        self.assert_notifications(
            after=imp.created_on,
            expected_json={
                "type": "import:finished",
                "created_on": matchers.ISODate(),
                "target_url": f"/contactimport/read/{imp.id}/",
                "is_seen": False,
                "import": {"type": "contact", "num_records": 5},
            },
            expected_users={self.editor},
            email=False,
        )

        # if a user visits the import read page, their notification for that import is now read
        self.login(self.editor)
        self.client.get(reverse("contacts.contactimport_read", args=[imp.id]))

        self.assertTrue(self.editor.notifications.get(contact_import=imp).is_seen)
Beispiel #7
0
    def test_queue_msg_handling(self):
        with override_settings(TESTING=False):
            msg = Msg.create_relayer_incoming(self.org, self.channel,
                                              "tel:12065551212", "Hello World",
                                              timezone.now())

        self.assert_org_queued(self.org, "handler")
        self.assert_contact_queued(msg.contact)
        self.assert_queued_handler_task(
            msg.contact,
            {
                "type": "msg_event",
                "org_id": self.org.id,
                "task": {
                    "org_id": self.org.id,
                    "channel_id": self.channel.id,
                    "contact_id": msg.contact_id,
                    "msg_id": msg.id,
                    "msg_uuid": str(msg.uuid),
                    "msg_external_id": None,
                    "urn": "tel:+12065551212",
                    "urn_id": msg.contact.urns.get().id,
                    "text": "Hello World",
                    "attachments": None,
                    "new_contact": True,
                },
                "queued_on": matchers.ISODate(),
            },
        )
Beispiel #8
0
    def test_from_ivr_call(self):
        contact = self.create_contact("Jim", phone="0979111111")

        call1 = IVRCall.objects.create(
            org=self.org,
            contact=contact,
            status=IVRCall.STATUS_IN_PROGRESS,
            channel=self.channel,
            contact_urn=contact.urns.all().first(),
            error_count=0,
        )
        call2 = IVRCall.objects.create(
            org=self.org,
            contact=contact,
            status=IVRCall.STATUS_ERRORED,
            error_reason=IVRCall.ERROR_BUSY,
            channel=self.channel,
            contact_urn=contact.urns.all().first(),
            error_count=0,
        )

        self.assertEqual(
            {
                "type": "call_started",
                "status": "I",
                "status_display": "In Progress",
                "created_on": matchers.ISODate(),
                "logs_url": None,
            },
            Event.from_ivr_call(self.org, self.user, call1),
        )

        self.assertEqual(
            {
                "type": "call_started",
                "status": "E",
                "status_display": "Errored (Busy)",
                "created_on": matchers.ISODate(),
                "logs_url": None,
            },
            Event.from_ivr_call(self.org, self.user, call2),
        )
Beispiel #9
0
    def test_queue_interrupt_by_channel(self):
        self.channel.release()

        self.assert_org_queued(self.org, "batch")
        self.assert_queued_batch_task(
            self.org,
            {
                "type": "interrupt_sessions",
                "org_id": self.org.id,
                "task": {"channel_ids": [self.channel.id]},
                "queued_on": matchers.ISODate(),
            },
        )
Beispiel #10
0
    def test_queue_mo_miss_event(self, mr_mocks):
        get_redis_connection("default").flushall()
        event = ChannelEvent.create_relayer_event(self.channel,
                                                  "tel:12065551212",
                                                  ChannelEvent.TYPE_CALL_OUT,
                                                  timezone.now())

        r = get_redis_connection()

        # noop, this event isn't handled by mailroom
        self.assertEqual(0, r.zcard(f"handler:active"))
        self.assertEqual(0, r.zcard(f"handler:{self.org.id}"))
        self.assertEqual(0, r.llen(f"c:{self.org.id}:{event.contact_id}"))

        event = ChannelEvent.create_relayer_event(
            self.channel, "tel:12065551515", ChannelEvent.TYPE_CALL_IN_MISSED,
            timezone.now())

        self.assert_org_queued(self.org, "handler")
        self.assert_contact_queued(event.contact)
        self.assert_queued_handler_task(
            event.contact,
            {
                "type": "mo_miss",
                "org_id": event.contact.org.id,
                "task": {
                    "channel_id": self.channel.id,
                    "contact_id": event.contact.id,
                    "event_type": "mo_miss",
                    "extra": None,
                    "id": event.id,
                    "new_contact": False,
                    "occurred_on": matchers.ISODate(),
                    "org_id": event.contact.org.id,
                    "urn_id": event.contact.urns.get().id,
                },
                "queued_on": matchers.ISODate(),
            },
        )
Beispiel #11
0
    def test_queue_broadcast(self):
        jim = self.create_contact("Jim", phone="+12065551212")
        bobs = self.create_group(
            "Bobs", [self.create_contact("Bob", phone="+12065551313")])
        ticketer = Ticketer.create(self.org, self.admin, "mailgun",
                                   "Support Tickets", {})
        ticket = self.create_ticket(ticketer, jim, "Help!")

        bcast = Broadcast.create(
            self.org,
            self.admin,
            {
                "eng": "Welcome to mailroom!",
                "spa": "¡Bienvenidx a mailroom!"
            },
            groups=[bobs],
            contacts=[jim],
            urns=["tel:+12065556666"],
            base_language="eng",
            ticket=ticket,
        )

        bcast.send_async()

        self.assert_org_queued(self.org, "batch")
        self.assert_queued_batch_task(
            self.org,
            {
                "type": "send_broadcast",
                "org_id": self.org.id,
                "task": {
                    "translations": {
                        "eng": {
                            "text": "Welcome to mailroom!"
                        },
                        "spa": {
                            "text": "\u00a1Bienvenidx a mailroom!"
                        },
                    },
                    "template_state": "legacy",
                    "base_language": "eng",
                    "urns": ["tel:+12065556666"],
                    "contact_ids": [jim.id],
                    "group_ids": [bobs.id],
                    "broadcast_id": bcast.id,
                    "org_id": self.org.id,
                    "ticket_id": ticket.id,
                },
                "queued_on": matchers.ISODate(),
            },
        )
Beispiel #12
0
    def test_queue_contact_import_batch(self):
        imp = self.create_contact_import("media/test_imports/simple.xlsx")
        imp.start()

        self.assert_org_queued(self.org, "batch")
        self.assert_queued_batch_task(
            self.org,
            {
                "type": "import_contact_batch",
                "org_id": self.org.id,
                "task": {"contact_import_batch_id": imp.batches.get().id},
                "queued_on": matchers.ISODate(),
            },
        )
Beispiel #13
0
    def test_queue_interrupt_by_flow(self):
        flow = self.get_flow("favorites")
        flow.archive()

        self.assert_org_queued(self.org, "batch")
        self.assert_queued_batch_task(
            self.org,
            {
                "type": "interrupt_sessions",
                "org_id": self.org.id,
                "task": {"flow_ids": [flow.id]},
                "queued_on": matchers.ISODate(),
            },
        )
Beispiel #14
0
    def test_org_flagged(self):
        self.org.flag()

        incident = Incident.objects.get()
        self.assertEqual("org:flagged", incident.incident_type)
        self.assertEqual({self.admin}, set(n.user for n in incident.notifications.all()))

        self.assertEqual(
            {"type": "org:flagged", "started_on": matchers.ISODate(), "ended_on": None}, incident.as_json()
        )

        self.org.unflag()

        incident = Incident.objects.get()  # still only have 1 incident, but now it has ended
        self.assertEqual("org:flagged", incident.incident_type)
        self.assertIsNotNone(incident.ended_on)
Beispiel #15
0
    def test_queue_interrupt_by_contacts(self):
        jim = self.create_contact("Jim", phone="+12065551212")
        bob = self.create_contact("Bob", phone="+12065551313")

        queue_interrupt(self.org, contacts=[jim, bob])

        self.assert_org_queued(self.org, "batch")
        self.assert_queued_batch_task(
            self.org,
            {
                "type": "interrupt_sessions",
                "org_id": self.org.id,
                "task": {"contact_ids": [jim.id, bob.id]},
                "queued_on": matchers.ISODate(),
            },
        )
Beispiel #16
0
    def test_queue_broadcast(self):
        jim = self.create_contact("Jim", "+12065551212")
        bobs = self.create_group("Bobs",
                                 [self.create_contact("Bob", "+12065551313")])

        bcast = Broadcast.create(
            self.org,
            self.admin,
            {
                "eng": "Welcome to mailroom!",
                "spa": "¡Bienvenidx a mailroom!"
            },
            groups=[bobs],
            contacts=[jim],
            urns=[jim.urns.get()],
            base_language="eng",
        )

        with override_settings(TESTING=False):
            bcast.send()

        self.assert_org_queued(self.org, "batch")
        self.assert_queued_batch_task(
            self.org,
            {
                "type": "send_broadcast",
                "org_id": self.org.id,
                "task": {
                    "translations": {
                        "eng": {
                            "text": "Welcome to mailroom!"
                        },
                        "spa": {
                            "text": "\u00a1Bienvenidx a mailroom!"
                        },
                    },
                    "template_state": "legacy",
                    "base_language": "eng",
                    "urns": ["tel:+12065551212"],
                    "contact_ids": [jim.id],
                    "group_ids": [bobs.id],
                    "broadcast_id": bcast.id,
                    "org_id": self.org.id,
                },
                "queued_on": matchers.ISODate(),
            },
        )
Beispiel #17
0
    def test_queue_flow_start(self):
        flow = self.get_flow("favorites")
        jim = self.create_contact("Jim", phone="+12065551212")
        bobs = self.create_group(
            "Bobs", [self.create_contact("Bob", phone="+12065551313")])

        start = FlowStart.create(
            flow,
            self.admin,
            groups=[bobs],
            contacts=[jim],
            urns=["tel:+1234567890", "twitter:bobby"],
            restart_participants=True,
            extra={"foo": "bar"},
            include_active=True,
        )

        start.async_start()

        self.assert_org_queued(self.org, "batch")
        self.assert_queued_batch_task(
            self.org,
            {
                "type": "start_flow",
                "org_id": self.org.id,
                "task": {
                    "start_id": start.id,
                    "start_type": "M",
                    "org_id": self.org.id,
                    "created_by": self.admin.username,
                    "created_by_id": self.admin.id,
                    "flow_id": flow.id,
                    "flow_type": "M",
                    "contact_ids": [jim.id],
                    "group_ids": [bobs.id],
                    "urns": ["tel:+1234567890", "twitter:bobby"],
                    "query": None,
                    "restart_participants": True,
                    "include_active": True,
                    "extra": {
                        "foo": "bar"
                    },
                },
                "queued_on": matchers.ISODate(),
            },
        )
Beispiel #18
0
    def assert_contact_queued(self, contact):
        r = get_redis_connection()

        # check we have one contact handle event queued for its org
        self.assertEqual(r.zcard(f"handler:{contact.org.id}"), 1)

        # load and check that task
        task = json.loads(r.zrange(f"handler:{contact.org.id}", 0, 1)[0])

        self.assertEqual(
            task,
            {
                "type": "handle_contact_event",
                "org_id": contact.org.id,
                "task": {"contact_id": contact.id},
                "queued_on": matchers.ISODate(),
            },
        )
Beispiel #19
0
    def test_results_export_finished(self):
        flow1 = self.create_flow("Test Flow 1")
        flow2 = self.create_flow("Test Flow 2")
        export = ExportFlowResultsTask.create(
            self.org,
            self.editor,
            flows=[flow1, flow2],
            contact_fields=(),
            responded_only=True,
            include_msgs=True,
            extra_urns=(),
            group_memberships=(),
        )
        export.perform()

        Notification.export_finished(export)

        self.assertFalse(
            self.editor.notifications.get(results_export=export).is_seen)

        # we only notify the user that started the export
        self.assert_notifications(
            after=export.created_on,
            expected_json={
                "type": "export:finished",
                "created_on": matchers.ISODate(),
                "target_url": f"/assets/download/results_export/{export.id}/",
                "is_seen": False,
                "export": {
                    "type": "results"
                },
            },
            expected_users={self.editor},
            email=True,
        )

        send_notification_emails()

        self.assertEqual(1, len(mail.outbox))
        self.assertEqual("[Temba] Your results export is ready",
                         mail.outbox[0].subject)
        self.assertEqual(["*****@*****.**"], mail.outbox[0].recipients())
        self.assertIn("Test Flow 1", mail.outbox[0].body)
        self.assertIn("Test Flow 2", mail.outbox[0].body)
Beispiel #20
0
    def test_contact_export_finished(self):
        export = ExportContactsTask.create(self.org, self.editor)
        export.perform()

        Notification.export_finished(export)

        self.assertFalse(
            self.editor.notifications.get(contact_export=export).is_seen)

        # we only notify the user that started the export
        self.assert_notifications(
            after=export.created_on,
            expected_json={
                "type": "export:finished",
                "created_on": matchers.ISODate(),
                "target_url": f"/assets/download/contact_export/{export.id}/",
                "is_seen": False,
                "export": {
                    "type": "contact"
                },
            },
            expected_users={self.editor},
            email=True,
        )

        send_notification_emails()

        self.assertEqual(1, len(mail.outbox))
        self.assertEqual("[Temba] Your contact export is ready",
                         mail.outbox[0].subject)
        self.assertEqual(["*****@*****.**"], mail.outbox[0].recipients())

        # calling task again won't send more emails
        send_notification_emails()

        self.assertEqual(1, len(mail.outbox))

        # if a user visits the export download page, their notification for that export is now read
        self.login(self.editor)
        self.client.get(export.get_download_url())

        self.assertTrue(
            self.editor.notifications.get(contact_export=export).is_seen)
Beispiel #21
0
    def test_queue_flow_start(self):
        flow = self.get_flow("favorites")
        jim = self.create_contact("Jim", "+12065551212")
        bobs = self.create_group("Bobs",
                                 [self.create_contact("Bob", "+12065551313")])

        start = FlowStart.create(
            flow,
            self.admin,
            groups=[bobs],
            contacts=[jim],
            restart_participants=True,
            extra={"foo": "bar"},
            include_active=True,
        )

        with override_settings(TESTING=False):
            start.async_start()

        self.assert_org_queued(self.org, "batch")
        self.assert_queued_batch_task(
            self.org,
            {
                "type": "start_flow",
                "org_id": self.org.id,
                "task": {
                    "start_id": start.id,
                    "org_id": self.org.id,
                    "flow_id": flow.id,
                    "flow_type": "M",
                    "contact_ids": [jim.id],
                    "group_ids": [bobs.id],
                    "restart_participants": True,
                    "include_active": True,
                    "extra": {
                        "foo": "bar"
                    },
                },
                "queued_on": matchers.ISODate(),
            },
        )
Beispiel #22
0
    def test_tickets_activity(self):
        # mailroom will create these notifications
        Notification._create_all(self.org, "tickets:activity", scope="", users=[self.agent, self.editor])

        self.assert_notifications(
            expected_json={
                "type": "tickets:activity",
                "created_on": matchers.ISODate(),
                "target_url": "/ticket/mine/",
                "is_seen": False,
            },
            expected_users={self.agent, self.editor},
            email=False,
        )

        # if a user visits their assigned tickets page, their notification is now read
        self.login(self.agent)
        self.client.get("/ticket/mine/")

        self.assertTrue(self.agent.notifications.get().is_seen)
        self.assertFalse(self.editor.notifications.get().is_seen)
Beispiel #23
0
    def test_from_ticket_event(self):
        ticketer = Ticketer.create(self.org, self.user, "mailgun",
                                   "Email ([email protected])", {})
        contact = self.create_contact("Jim", phone="0979111111")
        ticket = self.create_ticket(ticketer,
                                    contact,
                                    "Problem",
                                    body="Where my shoes?")

        # event with a user
        event1 = TicketEvent.objects.create(
            org=self.org,
            contact=contact,
            ticket=ticket,
            event_type=TicketEvent.TYPE_NOTE,
            created_by=self.agent,
            note="this is important",
        )

        self.assertEqual(
            {
                "type": "ticket_note_added",
                "note": "this is important",
                "assignee": None,
                "ticket": {
                    "uuid": str(ticket.uuid),
                    "opened_on": matchers.ISODate(),
                    "closed_on": None,
                    "status": "O",
                    "subject": "Problem",
                    "body": "Where my shoes?",
                    "ticketer": {
                        "uuid": str(ticketer.uuid),
                        "name": "Email ([email protected])"
                    },
                },
                "created_on": matchers.ISODate(),
                "created_by": {
                    "id": self.agent.id,
                    "first_name": "",
                    "last_name": "",
                    "email": "*****@*****.**"
                },
            },
            Event.from_ticket_event(self.org, self.user, event1),
        )

        # event without a user
        event2 = TicketEvent.objects.create(org=self.org,
                                            contact=contact,
                                            ticket=ticket,
                                            event_type=TicketEvent.TYPE_CLOSED)

        self.assertEqual(
            {
                "type": "ticket_closed",
                "note": None,
                "assignee": None,
                "ticket": {
                    "uuid": str(ticket.uuid),
                    "opened_on": matchers.ISODate(),
                    "closed_on": None,
                    "status": "O",
                    "subject": "Problem",
                    "body": "Where my shoes?",
                    "ticketer": {
                        "uuid": str(ticketer.uuid),
                        "name": "Email ([email protected])"
                    },
                },
                "created_on": matchers.ISODate(),
                "created_by": None,
            },
            Event.from_ticket_event(self.org, self.user, event2),
        )
Beispiel #24
0
    def test_folder(self, mr_mocks):
        self.login(self.admin)

        contact1 = self.create_contact("Joe",
                                       phone="123",
                                       last_seen_on=timezone.now())
        contact2 = self.create_contact("Frank",
                                       phone="124",
                                       last_seen_on=timezone.now())
        contact3 = self.create_contact("Anne",
                                       phone="125",
                                       last_seen_on=timezone.now())
        self.create_contact("Mary No tickets",
                            phone="126",
                            last_seen_on=timezone.now())
        self.create_contact("Mr Other Org",
                            phone="126",
                            last_seen_on=timezone.now(),
                            org=self.org2)

        open_url = reverse("tickets.ticket_folder",
                           kwargs={
                               "folder": "all",
                               "status": "open"
                           })
        closed_url = reverse("tickets.ticket_folder",
                             kwargs={
                                 "folder": "all",
                                 "status": "closed"
                             })
        mine_url = reverse("tickets.ticket_folder",
                           kwargs={
                               "folder": "mine",
                               "status": "open"
                           })
        unassigned_url = reverse("tickets.ticket_folder",
                                 kwargs={
                                     "folder": "unassigned",
                                     "status": "open"
                                 })

        def assert_tickets(resp, tickets: list):
            actual_tickets = [
                t["ticket"]["uuid"] for t in resp.json()["results"]
            ]
            expected_tickets = [str(t.uuid) for t in tickets]
            self.assertEqual(expected_tickets, actual_tickets)

        # no tickets yet so no contacts returned
        response = self.client.get(open_url)
        assert_tickets(response, [])

        # contact 1 has two open tickets
        c1_t1 = self.create_ticket(self.mailgun, contact1, "Question 1")
        # assign it
        c1_t1.assign(self.admin, assignee=self.admin, note="I've got this")
        c1_t2 = self.create_ticket(self.mailgun, contact1, "Question 2")

        self.create_incoming_msg(contact1, "I have an issue")
        self.create_broadcast(self.admin, "We can help",
                              contacts=[contact1]).msgs.first()

        # contact 2 has an open ticket and a closed ticket
        c2_t1 = self.create_ticket(self.mailgun, contact2, "Question 3")
        c2_t2 = self.create_ticket(self.mailgun,
                                   contact2,
                                   "Question 4",
                                   closed_on=timezone.now())

        self.create_incoming_msg(contact2, "Anyone there?")
        self.create_incoming_msg(contact2, "Hello?")

        # contact 3 has two closed tickets
        c3_t1 = self.create_ticket(self.mailgun,
                                   contact3,
                                   "Question 5",
                                   closed_on=timezone.now())
        c3_t2 = self.create_ticket(self.mailgun,
                                   contact3,
                                   "Question 6",
                                   closed_on=timezone.now())

        # fetching open folder returns all open tickets
        response = self.client.get(open_url)
        assert_tickets(response, [c2_t1, c1_t2, c1_t1])

        joes_open_tickets = contact1.tickets.filter(
            status="O").order_by("-opened_on")

        expected_json = {
            "results": [
                {
                    "uuid": str(contact2.uuid),
                    "name": "Frank",
                    "last_seen_on": matchers.ISODate(),
                    "last_msg": {
                        "text": "Hello?",
                        "direction": "I",
                        "type": "I",
                        "created_on": matchers.ISODate(),
                        "sender": None,
                    },
                    "ticket": {
                        "uuid":
                        str(contact2.tickets.filter(status="O").first().uuid),
                        "assignee":
                        None,
                        "subject":
                        "Question 3",
                        "last_activity_on":
                        matchers.ISODate(),
                        "closed_on":
                        None,
                    },
                },
                {
                    "uuid": str(contact1.uuid),
                    "name": "Joe",
                    "last_seen_on": matchers.ISODate(),
                    "last_msg": {
                        "text": "We can help",
                        "direction": "O",
                        "type": "I",
                        "created_on": matchers.ISODate(),
                        "sender": {
                            "id": self.admin.id,
                            "email": "*****@*****.**"
                        },
                    },
                    "ticket": {
                        "uuid": str(joes_open_tickets[0].uuid),
                        "assignee": None,
                        "subject": "Question 2",
                        "last_activity_on": matchers.ISODate(),
                        "closed_on": None,
                    },
                },
                {
                    "uuid": str(contact1.uuid),
                    "name": "Joe",
                    "last_seen_on": matchers.ISODate(),
                    "last_msg": {
                        "text": "We can help",
                        "direction": "O",
                        "type": "I",
                        "created_on": matchers.ISODate(),
                        "sender": {
                            "id": self.admin.id,
                            "email": "*****@*****.**"
                        },
                    },
                    "ticket": {
                        "uuid": str(joes_open_tickets[1].uuid),
                        "assignee": {
                            "id": self.admin.id,
                            "first_name": "",
                            "last_name": "",
                            "email": "*****@*****.**",
                        },
                        "subject": "Question 1",
                        "last_activity_on": matchers.ISODate(),
                        "closed_on": None,
                    },
                },
            ]
        }
        self.assertEqual(expected_json, response.json())

        # the two unassigned tickets
        response = self.client.get(unassigned_url)
        assert_tickets(response, [c2_t1, c1_t2])

        # one assigned ticket for mine
        response = self.client.get(mine_url)
        assert_tickets(response, [c1_t1])

        # fetching closed folder returns all closed tickets
        response = self.client.get(closed_url)
        assert_tickets(response, [c3_t2, c3_t1, c2_t2])

        # make sure when paging we get a next url
        with patch("temba.tickets.views.TicketCRUDL.Folder.paginate_by", 1):
            response = self.client.get(open_url + "?_format=json")
            self.assertIsNotNone(response.json()["next"])
Beispiel #25
0
    def test_from_msg(self):
        contact1 = self.create_contact("Jim", phone="0979111111")
        contact2 = self.create_contact("Bob", phone="0979222222")

        msg_in = self.create_incoming_msg(contact1,
                                          "Hello",
                                          external_id="12345")

        self.assertEqual(
            {
                "type": "msg_received",
                "created_on": matchers.ISODate(),
                "msg": {
                    "uuid": str(msg_in.uuid),
                    "id": msg_in.id,
                    "urn": "tel:+250979111111",
                    "text": "Hello",
                    "channel": {
                        "uuid": str(self.channel.uuid),
                        "name": "Test Channel"
                    },
                    "external_id": "12345",
                },
                "msg_type": "I",
                "logs_url": None,
            },
            Event.from_msg(self.org, self.admin, msg_in),
        )

        msg_out = self.create_outgoing_msg(contact1,
                                           "Hello",
                                           channel=self.channel,
                                           status="E",
                                           quick_replies=("yes", "no"))
        log = ChannelLog.objects.create(channel=self.channel,
                                        is_error=True,
                                        description="Boom",
                                        msg=msg_out)
        msg_out.refresh_from_db()

        self.assertEqual(
            {
                "type": "msg_created",
                "created_on": matchers.ISODate(),
                "msg": {
                    "uuid": str(msg_out.uuid),
                    "id": msg_out.id,
                    "urn": "tel:+250979111111",
                    "text": "Hello",
                    "channel": {
                        "uuid": str(self.channel.uuid),
                        "name": "Test Channel"
                    },
                    "quick_replies": ["yes", "no"],
                },
                "status": "E",
                "logs_url": f"/channels/channellog/read/{log.id}/",
            },
            Event.from_msg(self.org, self.admin, msg_out),
        )

        ivr_out = self.create_outgoing_msg(contact1, "Hello", msg_type="V")

        self.assertEqual(
            {
                "type": "ivr_created",
                "created_on": matchers.ISODate(),
                "msg": {
                    "uuid": str(ivr_out.uuid),
                    "id": ivr_out.id,
                    "urn": "tel:+250979111111",
                    "text": "Hello",
                    "channel": {
                        "uuid": str(self.channel.uuid),
                        "name": "Test Channel"
                    },
                },
                "status": "S",
                "logs_url": None,
            },
            Event.from_msg(self.org, self.admin, ivr_out),
        )

        bcast = self.create_broadcast(self.admin,
                                      "Hi there",
                                      contacts=[contact1, contact2])
        msg_out2 = bcast.msgs.filter(contact=contact1).get()

        self.assertEqual(
            {
                "type": "broadcast_created",
                "created_on": matchers.ISODate(),
                "translations": {
                    "base": "Hi there"
                },
                "base_language": "base",
                "msg": {
                    "uuid": str(msg_out2.uuid),
                    "id": msg_out2.id,
                    "urn": "tel:+250979111111",
                    "text": "Hi there",
                    "channel": {
                        "uuid": str(self.channel.uuid),
                        "name": "Test Channel"
                    },
                },
                "status": "S",
                "recipient_count": 2,
                "logs_url": None,
            },
            Event.from_msg(self.org, self.admin, msg_out2),
        )
Beispiel #26
0
    def test_flow_event(self, mock_send):
        self.setupChannel()

        org = self.channel.org
        org.save()

        flow = self.get_flow('color')

        # replace our uuid of 4 with the right thing
        actionset = ActionSet.objects.get(x=4)
        actionset.actions = [
            WebhookAction(str(uuid4()), org.get_webhook_url()).as_json()
        ]
        actionset.save()

        # run a user through this flow
        flow.start([], [self.joe])

        # have joe reply with mauve, which will put him in the other category that triggers the API Action
        sms = self.create_msg(contact=self.joe,
                              direction='I',
                              status='H',
                              text="Mauve",
                              attachments=[
                                  "image/jpeg:http://s3.com/text.jpg",
                                  "audio/mp4:http://s3.com/text.mp4"
                              ])

        mock_send.return_value = MockResponse(200, "{}")
        Flow.find_and_handle(sms)

        # should have one event created
        event = WebHookEvent.objects.get()

        self.assertEqual('C', event.status)
        self.assertEqual(1, event.try_count)
        self.assertFalse(event.next_attempt)

        result = WebHookResult.objects.get()
        self.assertIn("successfully", result.message)
        self.assertEqual(200, result.status_code)
        self.assertEqual(self.joe, result.contact)

        self.assertTrue(mock_send.called)

        args = mock_send.call_args_list[0][0]
        prepared_request = args[0]
        self.assertIn(self.channel.org.get_webhook_url(), prepared_request.url)

        data = json.loads(prepared_request.body)

        self.assertEqual(data['channel'], {
            'uuid': str(self.channel.uuid),
            'name': self.channel.name
        })
        self.assertEqual(
            data['contact'], {
                'uuid': str(self.joe.uuid),
                'name': self.joe.name,
                'urn': six.text_type(self.joe.get_urn('tel'))
            })
        self.assertEqual(data['flow'], {
            'uuid': str(flow.uuid),
            'name': flow.name
        })
        self.assertEqual(
            data['input'], {
                'urn':
                'tel:+250788123123',
                'text':
                "Mauve",
                'attachments': [
                    "image/jpeg:http://s3.com/text.jpg",
                    "audio/mp4:http://s3.com/text.mp4"
                ]
            })
        self.assertEqual(
            data['results'], {
                'color': {
                    'category':
                    'Other',
                    'node_uuid':
                    matchers.UUID4String(),
                    'name':
                    'color',
                    'value':
                    'Mauve',
                    'created_on':
                    matchers.ISODate(),
                    'input':
                    'Mauve\nhttp://s3.com/text.jpg\nhttp://s3.com/text.mp4'
                }
            })
Beispiel #27
0
    def test_channel_alert(self):
        self.org.add_user(
            self.editor,
            OrgRole.ADMINISTRATOR)  # upgrade editor to administrator

        alert1 = Alert.create_and_send(self.channel, Alert.TYPE_POWER)

        self.assert_notifications(
            after=alert1.created_on,
            expected_json={
                "type": "channel:alert",
                "created_on": matchers.ISODate(),
                "target_url": f"/channels/channel/read/{self.channel.uuid}/",
                "is_seen": False,
                "channel": {
                    "uuid": str(self.channel.uuid),
                    "name": "Test Channel"
                },
            },
            expected_users={self.admin, self.editor},
            email=False,
        )

        # creating another alert for the same channel won't create any new notifications
        alert2 = Alert.create_and_send(self.channel, Alert.TYPE_POWER)

        self.assert_notifications(after=alert2.created_on,
                                  expected_json={},
                                  expected_users=set(),
                                  email=False)

        # if a user clears their notifications however, they will get new ones for this channel
        self.admin.notifications.update(is_seen=True)

        alert3 = Alert.create_and_send(self.channel, Alert.TYPE_POWER)

        self.assert_notifications(
            after=alert3.created_on,
            expected_json={
                "type": "channel:alert",
                "created_on": matchers.ISODate(),
                "target_url": f"/channels/channel/read/{self.channel.uuid}/",
                "is_seen": False,
                "channel": {
                    "uuid": str(self.channel.uuid),
                    "name": "Test Channel"
                },
            },
            expected_users={self.admin},
            email=False,
        )

        # an alert for a different channel will also create new notifications
        vonage = self.create_channel("NX", "Vonage", "1234")
        alert4 = Alert.create_and_send(vonage, Alert.TYPE_POWER)

        self.assert_notifications(
            after=alert4.created_on,
            expected_json={
                "type": "channel:alert",
                "created_on": matchers.ISODate(),
                "target_url": f"/channels/channel/read/{vonage.uuid}/",
                "is_seen": False,
                "channel": {
                    "uuid": str(vonage.uuid),
                    "name": "Vonage"
                },
            },
            expected_users={self.admin, self.editor},
            email=False,
        )

        # if a user visits the channel read page, their notification for that channel is now read
        self.login(self.admin)
        self.client.get(
            reverse("channels.channel_read", kwargs={"uuid": vonage.uuid}))

        self.assertTrue(self.admin.notifications.get(channel=vonage).is_seen)
        self.assertFalse(self.editor.notifications.get(channel=vonage).is_seen)
Beispiel #28
0
    def test_flow_event(self, mock_send):
        self.setupChannel()

        org = self.channel.org
        org.save()

        flow = self.get_flow("color")

        # replace our uuid of 4 with the right thing
        actionset = ActionSet.objects.get(x=4)
        actionset.actions = [
            WebhookAction(str(uuid4()), org.get_webhook_url()).as_json()
        ]
        actionset.save()

        # run a user through this flow
        flow.start([], [self.joe])

        # have joe reply with mauve, which will put him in the other category that triggers the API Action
        sms = self.create_msg(
            contact=self.joe,
            direction="I",
            status="H",
            text="Mauve",
            attachments=[
                "image/jpeg:http://s3.com/text.jpg",
                "audio/mp4:http://s3.com/text.mp4"
            ],
        )

        mock_send.return_value = MockResponse(200, "{}")
        Flow.find_and_handle(sms)

        # should have one event created
        event = WebHookEvent.objects.get()

        self.assertEqual("C", event.status)
        self.assertEqual(1, event.try_count)
        self.assertFalse(event.next_attempt)

        result = WebHookResult.objects.get()
        self.assertIn("successfully", result.message)
        self.assertEqual(200, result.status_code)
        self.assertEqual(self.joe, result.contact)

        self.assertTrue(mock_send.called)

        args = mock_send.call_args_list[0][0]
        prepared_request = args[0]
        self.assertIn(self.channel.org.get_webhook_url(), prepared_request.url)

        data = json.loads(prepared_request.body)

        self.assertEqual(data["channel"], {
            "uuid": str(self.channel.uuid),
            "name": self.channel.name
        })
        self.assertEqual(
            data["contact"], {
                "uuid": str(self.joe.uuid),
                "name": self.joe.name,
                "urn": str(self.joe.get_urn("tel"))
            })
        self.assertEqual(data["flow"], {
            "uuid": str(flow.uuid),
            "name": flow.name,
            "revision": 1
        })
        self.assertEqual(
            data["input"],
            {
                "urn":
                "tel:+250788123123",
                "text":
                "Mauve",
                "attachments": [
                    "image/jpeg:http://s3.com/text.jpg",
                    "audio/mp4:http://s3.com/text.mp4"
                ],
            },
        )
        self.assertEqual(
            data["results"],
            {
                "color": {
                    "category":
                    "Other",
                    "node_uuid":
                    matchers.UUID4String(),
                    "name":
                    "color",
                    "value":
                    "Mauve\nhttp://s3.com/text.jpg\nhttp://s3.com/text.mp4",
                    "created_on":
                    matchers.ISODate(),
                    "input":
                    "Mauve\nhttp://s3.com/text.jpg\nhttp://s3.com/text.mp4",
                }
            },
        )