{{ answer.pk }} |
+
+
+
+
+ {{ answer.color }}
+ |
{{ answer.name }} |
{{ answer.get_type_display }} |
{{ answer.answer }} |
diff --git a/decisiontree/tests/test_app.py b/decisiontree/tests/test_app.py
index eaded02..fd1b215 100644
--- a/decisiontree/tests/test_app.py
+++ b/decisiontree/tests/test_app.py
@@ -39,6 +39,17 @@ def test_valid_trigger(self):
question = self.transition.current_state.question.text
self.assertTrue(question in msg.responses[0]['text'])
+ messages = list(dt.TranscriptMessage.objects.all())
+ self.assertEqual(len(messages), 2)
+ incoming, outgoing = messages
+ self.assertEqual(incoming.session.connection, self.connection)
+ self.assertEqual(incoming.direction, dt.TranscriptMessage.INCOMING)
+ self.assertEqual(incoming.message, "food")
+ self.assertEqual(outgoing.session.connection, self.connection)
+ self.assertEqual(outgoing.direction, dt.TranscriptMessage.OUTGOING)
+ self.assertEqual(outgoing.message, msg.responses[0]['text'])
+ self.assertTrue(incoming.created < outgoing.created)
+
def test_basic_response(self):
self._send('food')
answer = self.transition.answer.answer
@@ -46,11 +57,33 @@ def test_basic_response(self):
next_question = self.transition.next_state.question.text
self.assertTrue(next_question in msg.responses[0]['text'])
+ messages = list(dt.TranscriptMessage.objects.all())
+ self.assertEqual(len(messages), 4)
+ incoming, outgoing = messages[-2:]
+ self.assertEqual(incoming.session.connection, self.connection)
+ self.assertEqual(incoming.direction, dt.TranscriptMessage.INCOMING)
+ self.assertEqual(incoming.message, answer)
+ self.assertEqual(outgoing.session.connection, self.connection)
+ self.assertEqual(outgoing.direction, dt.TranscriptMessage.OUTGOING)
+ self.assertEqual(outgoing.message, msg.responses[0]['text'])
+ self.assertTrue(incoming.created < outgoing.created)
+
def test_error_response(self):
self._send('food')
msg = self._send('bad-answer')
self.assertTrue('is not a valid answer' in msg.responses[0]['text'])
+ messages = list(dt.TranscriptMessage.objects.all())
+ self.assertEqual(len(messages), 4)
+ incoming, outgoing = messages[-2:]
+ self.assertEqual(incoming.session.connection, self.connection)
+ self.assertEqual(incoming.direction, dt.TranscriptMessage.INCOMING)
+ self.assertEqual(incoming.message, "bad-answer")
+ self.assertEqual(outgoing.session.connection, self.connection)
+ self.assertEqual(outgoing.direction, dt.TranscriptMessage.OUTGOING)
+ self.assertEqual(outgoing.message, msg.responses[0]['text'])
+ self.assertTrue(incoming.created < outgoing.created)
+
def test_error_response_from_question(self):
self.survey.root_state.question.error_response = 'my error response'
self.survey.root_state.question.save()
@@ -58,6 +91,17 @@ def test_error_response_from_question(self):
msg = self._send('bad-answer')
self.assertTrue('my error response' == msg.responses[0]['text'])
+ messages = list(dt.TranscriptMessage.objects.all())
+ self.assertEqual(len(messages), 4)
+ incoming, outgoing = messages[-2:]
+ self.assertEqual(incoming.session.connection, self.connection)
+ self.assertEqual(incoming.direction, dt.TranscriptMessage.INCOMING)
+ self.assertEqual(incoming.message, "bad-answer")
+ self.assertEqual(outgoing.session.connection, self.connection)
+ self.assertEqual(outgoing.direction, dt.TranscriptMessage.OUTGOING)
+ self.assertEqual(outgoing.message, msg.responses[0]['text'])
+ self.assertTrue(incoming.created < outgoing.created)
+
def test_sequence_start(self):
self._send('food')
answer = self.transition.answer.answer
@@ -89,6 +133,17 @@ def test_sequence_end(self):
self.assertEqual(msg.responses[0]['text'],
"Your session with 'food' has ended")
+ messages = list(dt.TranscriptMessage.objects.all())
+ self.assertEqual(len(messages), 4)
+ incoming, outgoing = messages[-2:]
+ self.assertEqual(incoming.session.connection, self.connection)
+ self.assertEqual(incoming.direction, dt.TranscriptMessage.INCOMING)
+ self.assertEqual(incoming.message, "end")
+ self.assertEqual(outgoing.session.connection, self.connection)
+ self.assertEqual(outgoing.direction, dt.TranscriptMessage.OUTGOING)
+ self.assertEqual(outgoing.message, msg.responses[0]['text'])
+ self.assertTrue(incoming.created < outgoing.created)
+
def test_num_tries_increments(self):
self.survey.root_state.num_retries = 3
self.survey.root_state.save()
diff --git a/decisiontree/utils.py b/decisiontree/utils.py
index bcc943a..1e2f147 100644
--- a/decisiontree/utils.py
+++ b/decisiontree/utils.py
@@ -1,11 +1,13 @@
+from django.db.models import get_model
from django.utils.encoding import force_text
-from .models import Tree
+from rapidsms.router import send
def get_survey(trigger, connection):
"""Returns a survey only if it matches the connection's tenant."""
from decisiontree.multitenancy.utils import multitenancy_enabled
+ Tree = get_model('decisiontree', 'Tree')
queryset = Tree.objects.filter(trigger__iexact=trigger)
if multitenancy_enabled():
tenant = connection.backend.tenantlink.tenant
@@ -126,3 +128,36 @@ def edit_string_for_tags(tags):
else:
names.append(name)
return u', '.join(sorted(names))
+
+
+def start_survey(survey, connections):
+ """For each connection, establish a new Session and send the first question.
+
+ Cancels any open sessions the connections might have had.
+ """
+ Session = get_model('decisiontree', 'Session')
+ TranscriptMessage = get_model('decisiontree', 'TranscriptMessage')
+
+ # First, close any open survey sessions.
+ open_sessions = Session.objects.open().filter(connection__in=connections)
+ open_sessions.update(state=None, canceled=True)
+
+ # Create a new, open survey session for each connection
+ # and send the first message.
+ message = survey.root_state.question.text
+ sessions = []
+ for connection in connections:
+ session = Session.objects.create(
+ connection=connection,
+ tree=survey,
+ state=survey.root_state,
+ )
+ TranscriptMessage.objects.create(
+ session=session,
+ direction=TranscriptMessage.OUTGOING,
+ message=message,
+ )
+ # TODO: notify app listeners?
+ send(message, [connection])
+ sessions.append(session)
+ return sessions