def calculate_totals_for_cases(apps, schema_editor): from casepro.statistics.models import datetime_to_date Case = apps.get_model('cases', 'Case') CaseAction = apps.get_model('cases', 'CaseAction') DailyCount = apps.get_model('statistics', 'DailyCount') cases = list(Case.objects.all().order_by('id')) num_updated = 0 for case in cases: open_action = case.actions.filter(action='O').first() org = open_action.case.org user = open_action.created_by partner = open_action.case.assignee case = open_action.case day = datetime_to_date(open_action.created_on, org) DailyCount.objects.create(day=day, item_type='C', scope='org:%d' % org.pk, count=1) DailyCount.objects.create(day=day, item_type='C', scope='org:%d:user:%d' % (org.pk, user.pk), count=1) DailyCount.objects.create(day=day, item_type='C', scope='partner:%d' % partner.pk, count=1) try: # only check the first close action, don't count reopens close_action = case.actions.filter( action='C').earliest('created_on') DailyCount.objects.create(day=day, item_type='D', scope='org:%d' % close_action.case.org.pk, count=1) DailyCount.objects.create( day=day, item_type='D', scope='org:%d:user:%d' % (close_action.case.org.pk, close_action.created_by.pk), count=1) DailyCount.objects.create(day=day, item_type='D', scope='partner:%d' % close_action.case.assignee.pk, count=1) num_updated += 1 if num_updated % 100 == 0: print("Created daily counts for %d of %d cases" % (num_updated, len(cases))) except CaseAction.DoesNotExist: # no close action means to close totals to count for this case pass
def clear_labels(self): """ Removes all labels from this message """ from casepro.statistics.models import DailyCount, datetime_to_date day = datetime_to_date(self.created_on, self.org) for label in self.labels.all(): DailyCount.record_removal(day, DailyCount.TYPE_INCOMING, label) Labelling.objects.filter(message=self).delete()
def unlabel(self, *labels): """ Removes the given labels from this message """ from casepro.statistics.models import DailyCount, datetime_to_date existing_labellings = Labelling.objects.filter( message=self, label__in=labels).select_related("label") day = datetime_to_date(self.created_on, self.org) for labelling in existing_labellings: DailyCount.record_removal(day, DailyCount.TYPE_INCOMING, labelling.label) Labelling.objects.filter( id__in=[l.id for l in existing_labellings]).delete()
def label(self, *labels): """ Adds the given labels to this message """ from casepro.profiles.models import Notification from casepro.statistics.models import DailyCount, datetime_to_date existing_label_ids = Labelling.objects.filter( message=self, label__in=labels).values_list("label", flat=True) add_labels = [l for l in labels if l.id not in existing_label_ids] new_labellings = [Labelling(message=self, label=l) for l in add_labels] Labelling.objects.bulk_create(new_labellings) day = datetime_to_date(self.created_on, self.org) for label in add_labels: DailyCount.record_item(day, DailyCount.TYPE_INCOMING, label) # notify all users who watch these labels for watcher in set(User.objects.filter(watched_labels__in=labels)): Notification.new_message_labelling(self.org, watcher, self)
def calculate_totals_for_cases(apps, schema_editor): from casepro.statistics.models import datetime_to_date Case = apps.get_model('cases', 'Case') CaseAction = apps.get_model('cases', 'CaseAction') DailyCount = apps.get_model('statistics', 'DailyCount') cases = list(Case.objects.all().order_by('id')) num_updated = 0 for case in cases: open_action = case.actions.filter(action='O').first() org = open_action.case.org user = open_action.created_by partner = open_action.case.assignee case = open_action.case day = datetime_to_date(open_action.created_on, org) DailyCount.objects.create(day=day, item_type='C', scope='org:%d' % org.pk, count=1) DailyCount.objects.create(day=day, item_type='C', scope='org:%d:user:%d' % (org.pk, user.pk), count=1) DailyCount.objects.create(day=day, item_type='C', scope='partner:%d' % partner.pk, count=1) try: # only check the first close action, don't count reopens close_action = case.actions.filter(action='C').earliest('created_on') DailyCount.objects.create(day=day, item_type='D', scope='org:%d' % close_action.case.org.pk, count=1) DailyCount.objects.create(day=day, item_type='D', scope='org:%d:user:%d' % (close_action.case.org.pk, close_action.created_by.pk), count=1) DailyCount.objects.create(day=day, item_type='D', scope='partner:%d' % close_action.case.assignee.pk, count=1) num_updated += 1 if num_updated % 100 == 0: print("Created daily counts for %d of %d cases" % (num_updated, len(cases))) except CaseAction.DoesNotExist: # no close action means to close totals to count for this case pass
def calculate_totals_for_cases(apps, schema_editor): from casepro.statistics.models import datetime_to_date Case = apps.get_model('cases', 'Case') CaseAction = apps.get_model('cases', 'CaseAction') Outgoing = apps.get_model('msgs', 'Outgoing') DailySecondTotalCount = apps.get_model('statistics', 'DailySecondTotalCount') qs = Case.objects.all().order_by('id') for case in qs: partner = case.assignee if case.closed_on is not None: # we only consider the first time a case was closed, not any subsequent reopenings close_action = case.actions.filter(action='C').earliest('created_on') org = close_action.case.org user = close_action.created_by partner = close_action.case.assignee case = close_action.case day = datetime_to_date(close_action.created_on, close_action.case.org) # count the time to close on an org level td = close_action.created_on - case.opened_on seconds_since_open = ceil(td.total_seconds()) DailySecondTotalCount.objects.create(day=day, item_type='C', scope='org:%d' % org.pk, count=1, seconds=seconds_since_open) # count the time since case was last assigned to this partner till it was closed if user.partners.filter(id=partner.id).exists(): # count the time since this case was (re)assigned to this partner try: action = case.actions.filter(action='A', assignee=partner).latest('created_on') start_date = action.created_on except CaseAction.DoesNotExist: start_date = case.opened_on td = close_action.created_on - start_date seconds_since_open = ceil(td.total_seconds()) DailySecondTotalCount.objects.create(day=day, item_type='C', scope='partner:%d' % partner.pk, count=1, seconds=seconds_since_open) # check if responded to if case.outgoing_messages.exists(): # count the first reponse at an org level first_response = case.outgoing_messages.earliest('created_on') day = datetime_to_date(first_response.created_on, case.org) td = first_response.created_on - case.opened_on seconds_since_open = ceil(td.total_seconds()) DailySecondTotalCount.objects.create(day=day, item_type='A', scope='org:%d' % case.org.pk, count=1, seconds=seconds_since_open) try: first_response = case.outgoing_messages.filter(partner=partner).earliest('created_on') except Outgoing.DoesNotExist: continue day = datetime_to_date(first_response.created_on, case.org) # count the first response by this partner author_action = case.actions.filter(action='O').order_by('created_on').first() reassign_action = case.actions.filter(action='A', assignee=partner).order_by('created_on').first() if author_action and get_partner(org, author_action.created_by) != partner: # only count the time since this case was (re)assigned to this partner # or cases that were assigned during creation by another partner if reassign_action: start_date = reassign_action.created_on else: start_date = author_action.created_on td = first_response.created_on - start_date seconds_since_open = ceil(td.total_seconds()) DailySecondTotalCount.objects.create(day=day, item_type='A', scope='partner:%d' % partner.pk, count=1, seconds=seconds_since_open)
def create_msgs(self, orgs): self._log("Creating messages. Press Ctrl+C to stop...\n") # cache labels and contacts for each org for org in orgs: org._contacts = list(org.contacts.order_by("id")) org._labels = list(org.labels.order_by("id")) last_backend_id = Message.objects.order_by("backend_id").values_list("backend_id", flat=True).last() backend_id_start = last_backend_id + 1 if last_backend_id else 1 BATCH_SIZE = 100 num_created = 0 try: msg_batch = [] while True: org = self.random_choice(orgs, bias=BIASED) backend_id = backend_id_start + num_created msg, labels = self.generate_msg(org, backend_id) msg._labels = labels msg_batch.append(msg) num_created += 1 if len(msg_batch) == BATCH_SIZE: Message.objects.bulk_create(msg_batch) labelling_batch = [] count_batch = [] for msg in msg_batch: count_batch.append( DailyCount( day=datetime_to_date(msg.created_on, org), item_type=DailyCount.TYPE_INCOMING, scope=DailyCount.encode_scope(org), count=1, ) ) for label in msg._labels: labelling_batch.append(Labelling.create(label, msg)) count_batch.append( DailyCount( day=datetime_to_date(msg.created_on, org), item_type=DailyCount.TYPE_INCOMING, scope=DailyCount.encode_scope(label), count=1, ) ) Labelling.objects.bulk_create(labelling_batch) DailyCount.objects.bulk_create(count_batch) msg_batch = [] self._log(f" > Created {num_created} messages\n") except KeyboardInterrupt: pass self._log(" > Squashing counts...\n") squash_counts() self._log(self.style.SUCCESS("OK") + "\n")