Skip to content

Commit

Permalink
Display associated case with messages
Browse files Browse the repository at this point in the history
* If you user tries to open case on message with case, go to existing case
* Also sets case for messages recieved before refactor
  • Loading branch information
rowanseymour committed Mar 5, 2016
1 parent 45b7c93 commit 43b437b
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 23 deletions.
7 changes: 6 additions & 1 deletion casepro/cases/migrations/0032_populate_message_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def populate_message_case(apps, schema_editor):
Case = apps.get_model('cases', 'Case')
Message = apps.get_model('msgs', 'Message')

cases = list(Case.objects.order_by('org', 'opened_on'))
cases = list(Case.objects.select_related('initial_message').order_by('org', 'opened_on'))
num_updated = 0

for case in cases:
Expand All @@ -20,6 +20,11 @@ def populate_message_case(apps, schema_editor):

num_updated += missing_messages.update(case=case)

if case.initial_message.case != case:
case.initial_message.case = case
case.initial_message.save(update_fields=('case',))
num_updated += 1

if cases:
print "Attached %d missing messages to %d cases" % (num_updated, len(cases))

Expand Down
5 changes: 4 additions & 1 deletion casepro/msgs/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ def search(cls, org, user, search):
if search['before']:
queryset = queryset.filter(created_on__lt=search['before'])

queryset = queryset.select_related('contact').prefetch_related('labels')
queryset = queryset.select_related('contact').prefetch_related('labels', 'case__assignee')

return queryset.order_by('-created_on', '-pk').distinct('created_on', 'pk')

Expand Down Expand Up @@ -331,6 +331,8 @@ def as_json(self):
"""
Prepares this message for JSON serialization
"""
case_json = {'id': self.case.pk, 'assignee': self.case.assignee.as_json()} if self.case else None

return {
'id': self.backend_id,
'contact': self.contact.as_json(),
Expand All @@ -340,6 +342,7 @@ def as_json(self):
'flagged': self.is_flagged,
'archived': self.is_archived,
'direction': self.DIRECTION,
'case': case_json,
'sender': None
}

Expand Down
58 changes: 43 additions & 15 deletions casepro/msgs/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,31 +371,59 @@ def test_search(self):

ann = self.create_contact(self.unicef, 'C-001', "Ann")
bob = self.create_contact(self.unicef, 'C-002', "Bob")
cat = self.create_contact(self.unicef, 'C-003', "Cat")
don = self.create_contact(self.unicef, 'C-004', "Don")
nic = self.create_contact(self.nyaruka, 'C-101', "Nic")

# labelled but not cased
msg1 = self.create_message(self.unicef, 101, ann, "What is HIV?", [self.aids], is_handled=True)
msg2 = self.create_message(self.unicef, 102, bob, "I ♡ RapidPro", [self.pregnancy], is_handled=True)

# labelled and flagged
msg3 = self.create_message(self.unicef, 103, bob, "HELP!", [self.pregnancy], is_handled=True, is_flagged=True)

# labelled and cased/archived
msg4 = self.create_message(self.unicef, 104, bob, "raids", [self.aids], is_handled=True, is_archived=True)
msg5 = self.create_message(self.unicef, 105, cat, "AIDS??", [self.aids], is_handled=True, is_archived=True)
case = self.create_case(self.unicef, cat, self.moh, msg5)

# unlabelled
self.create_message(self.unicef, 106, don, "RapidCon 2016", is_handled=True)

self.create_message(self.unicef, 101, ann, "What is HIV?", [self.aids], is_handled=True)
self.create_message(self.unicef, 102, bob, "I ♡ RapidPro", [self.pregnancy], is_handled=True)
self.create_message(self.unicef, 103, don, "RapidCon 2016!", is_handled=True)
# different org
self.create_message(self.nyaruka, 201, nic, "Moar codes", is_handled=True)

# log in as a non-administrator
self.login(self.user1)

# page requests first page of existing inbox messages
# request first page of inbox (i.e. labelled) messages
t0 = now()
response = self.url_get('unicef', url, {
'folder': 'inbox', 'text': "", 'page': 1, 'after': "", 'before': format_iso8601(t0)
})

self.assertEqual(len(response.json['results']), 3)
self.assertEqual(response.json['results'][0]['id'], 103)
self.assertEqual(response.json['results'][1]['id'], 102)
self.assertEqual(response.json['results'][1]['contact'], {'uuid': "C-002", 'name': "Bob"})
self.assertEqual(response.json['results'][1]['text'], "I ♡ RapidPro")
self.assertEqual(response.json['results'][1]['labels'], [{'id': self.pregnancy.pk, 'name': "Pregnancy"}])
self.assertEqual(response.json['results'][2]['id'], 101)

# request first page of archived messages
t0 = now()
response = self.url_get('unicef', url, {
'folder': 'inbox',
'text': "",
'page': 1,
'after': "",
'before': format_iso8601(t0)
'folder': 'archived', 'text': "", 'page': 1, 'after': "", 'before': format_iso8601(t0)
})

self.assertEqual(len(response.json['results']), 2)
self.assertEqual(response.json['results'][0]['id'], 102)
self.assertEqual(response.json['results'][0]['contact'], {'uuid': "C-002", 'name': "Bob"})
self.assertEqual(response.json['results'][0]['text'], "I ♡ RapidPro")
self.assertEqual(response.json['results'][0]['labels'], [{'id': self.pregnancy.pk, 'name': "Pregnancy"}])
self.assertEqual(response.json['results'][1]['id'], 101)
self.assertEqual(response.json['results'][0]['id'], 105)
self.assertEqual(response.json['results'][0]['contact'], {'uuid': "C-003", 'name': "Cat"})
self.assertEqual(response.json['results'][0]['text'], "AIDS??")
self.assertEqual(response.json['results'][0]['labels'], [{'id': self.aids.pk, 'name': "AIDS"}])
self.assertEqual(response.json['results'][0]['case'], {'id': case.pk,
'assignee': {'id': self.moh.pk, 'name': "MOH"}})
self.assertEqual(response.json['results'][1]['id'], 104)

@patch('casepro.test.TestBackend.flag_messages')
@patch('casepro.test.TestBackend.unflag_messages')
Expand Down Expand Up @@ -621,7 +649,7 @@ def test_handle_messages(self, mock_archive_messages, mock_label_messages):

# contact #5 has a case open that day
msg8 = self.create_message(self.unicef, 108, eve, "Start case", created_on=d1, is_handled=True)
case1 = Case.objects.create(org=self.unicef, contact=eve, assignee=self.moh, initial_message=msg8)
case1 = self.create_case(self.unicef, eve, self.moh, msg8)
case1.opened_on = d1
case1.save()

Expand Down
11 changes: 10 additions & 1 deletion casepro/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import pytz

from casepro.backend import BaseBackend
from casepro.cases.models import Partner
from casepro.cases.models import Case, Partner
from casepro.contacts.models import Contact, Group, Field
from casepro.msgs.models import Label, Message
from casepro.profiles import ROLE_ANALYST, ROLE_MANAGER
Expand Down Expand Up @@ -105,6 +105,15 @@ def create_message(self, org, backend_id, contact, text, labels=(), **kwargs):
msg.labels.add(*labels)
return msg

def create_case(self, org, contact, assignee, message, labels=(), **kwargs):
case = Case.objects.create(org=org, contact=contact, assignee=assignee, initial_message=message, **kwargs)
case.labels.add(*labels)

message.case = case
message.save(update_fields=('case',))

return case

def datetime(self, year, month, day, hour=0, minute=0, second=0, microsecond=0, tz=pytz.UTC):
return datetime(year, month, day, hour, minute, second, microsecond, tz)

Expand Down
10 changes: 6 additions & 4 deletions static/coffee/controllers.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -319,15 +319,17 @@ controllers.controller 'MessagesController', [ '$scope', '$timeout', '$modal', '
)

$scope.onCaseFromMessage = (message) ->
if message.case
CaseService.navigateToCase(message.case, null)
return

partners = if $scope.user.partner then null else $scope.partners
resolve = {message: (() -> message), partners: (() -> partners)}
$modal.open({templateUrl: 'newCaseModal.html', controller: 'NewCaseModalController', resolve: resolve})
.result.then((result) ->
CaseService.openCase(message, result.summary, result.assignee, (caseObj, isNew) ->
caseUrl = '/case/read/' + caseObj.id + '/'
if !isNew
caseUrl += '?alert=open_found_existing'
UtilsService.navigate(caseUrl)
withAlert = if !isNew then 'open_found_existing' else null
CaseService.navigateToCase(caseObj, withAlert)
)
)

Expand Down
11 changes: 10 additions & 1 deletion static/coffee/services.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ services.factory 'LabelService', ['$http', ($http) ->
# Case service
#=====================================================================

services.factory 'CaseService', ['$http', ($http) ->
services.factory 'CaseService', ['$http', '$window', ($http, $window) ->
new class CaseService

#----------------------------------------------------------------------------
Expand Down Expand Up @@ -399,6 +399,15 @@ services.factory 'CaseService', ['$http', ($http) ->
callback()
).error(DEFAULT_ERR_HANDLER)

#----------------------------------------------------------------------------
# Navigates to the read page for the given case
#----------------------------------------------------------------------------
navigateToCase: (caseObj, withAlert) ->
caseUrl = '/case/read/' + caseObj.id + '/'
if withAlert
caseUrl += '?alert=' + withAlert
$window.location.href = caseUrl

#----------------------------------------------------------------------------
# Fetches timeline events
#----------------------------------------------------------------------------
Expand Down
4 changes: 4 additions & 0 deletions templates/cases/home_messages.haml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@
%span.glyphicon.glyphicon-phone>
[[ message.contact.uuid | limitTo:6 | uppercase ]]
.message-text{ ng-click:"onExpandMessage(message)" }
%span.label-container{ ng-if:"message.case" }
%span.label.label-warning
[[ message.case.assignee.name ]]
 
%span.label-container{ ng-repeat:"label in filterDisplayLabels(message.labels)" }
%span.label.label-success
[[ label.name ]]
Expand Down

0 comments on commit 43b437b

Please sign in to comment.