<commit_before>from __future__ import absolute_import, unicode_literals

from collections import OrderedDict
from itertools import chain

import unicodecsv

from dash.orgs.views import OrgPermsMixin, OrgObjPermsMixin
from dash.utils import datetime_to_ms, get_obj_cacheable

from django.conf import settings
from django.core.urlresolvers import reverse
from django.http import (
    HttpResponse, HttpResponseBadRequest, HttpResponseRedirect, JsonResponse)
from django.shortcuts import get_object_or_404
from django.utils.translation import ugettext_lazy as _

from smartmin import views as smartmin
from smartmin.templatetags.smartmin import format_datetime

from tracpro.contacts.models import Contact
from tracpro.groups.models import Group

from . import charts, forms, tasks
from .models import Poll, Question, PollRun, Response, Window


class PollCRUDL(smartmin.SmartCRUDL):
    model = Poll
    actions = ('read', 'update', 'list', 'select')

    class PollMixin(object):

        def get_queryset(self):
            """Only allow viewing active polls for the current org."""
            return Poll.get_all(self.request.org)

    class Read(PollMixin, OrgObjPermsMixin, smartmin.SmartReadView):

        def get_context_data(self, **kwargs):
            context = super(PollCRUDL.Read, self).get_context_data(**kwargs)
            questions = self.object.get_questions()
            pollruns = self.object.get_pollruns(
                self.request.region, self.request.include_subregions)

            # if we're viewing "All Regions" don't include regional only pollruns
            if not self.request.region:
                pollruns = pollruns.universal()

            window = self.request.POST.get('window', self.request.GET.get('window', None))
            window = Window[window] if window else Window.last_30_days
            window_min, window_max = window.to_range()

            pollruns = pollruns.filter(conducted_on__gte=window_min, conducted_on__lt=window_max)
            pollruns = pollruns.order_by('conducted_on')

            for question in questions:
                question.chart_type, question.chart_data = charts.multiple_pollruns(
                    pollruns, question, self.request.data_regions)

            context['window'] = window
            context['window_min'] = datetime_to_ms(window_min)
            context['window_max'] = datetime_to_ms(window_max)
            context['window_options'] = Window.__members__.values()
            context['questions'] = questions
            return context

    class Update(PollMixin, OrgObjPermsMixin, smartmin.SmartUpdateView):
        exclude = ('is_active', 'flow_uuid', 'org')
        form_class = forms.PollForm

        def post_save(self, obj):
            for field_key, value in self.form.cleaned_data.iteritems():
                if field_key.startswith('__question__'):
                    question_id = field_key.split('__')[2]
                    Question.objects.filter(pk=question_id, poll=self.object).update(text=value)

    class List(PollMixin, OrgPermsMixin, smartmin.SmartListView):
        fields = ('name', 'questions', 'pollruns', 'last_conducted')
        field_config = {'pollruns': {'label': _("Dates")}}
        link_fields = ('name', 'pollruns')
        default_order = ('name',)

        def derive_pollruns(self, obj):
            return obj.get_pollruns(
                self.request.region, self.request.include_subregions)

        def get_questions(self, obj):
            return obj.get_questions().count()

        def get_pollruns(self, obj):
            return self.derive_pollruns(obj).count()

        def get_last_conducted(self, obj):
            last_pollrun = self.derive_pollruns(obj).order_by('-conducted_on').first()
            return last_pollrun.conducted_on if last_pollrun else _("Never")

        def lookup_field_link(self, context, field, obj):
            if field == 'pollruns':
                return reverse('polls.pollrun_by_poll', args=[obj.pk])

            return super(PollCRUDL.List, self).lookup_field_link(context, field, obj)

    class Select(OrgPermsMixin, smartmin.SmartFormView):
        title = _("Poll Flows")
        form_class = forms.FlowsForm
        success_url = '@polls.poll_list'
        submit_button_name = _("Update")
        success_message = _("Updated flows to track as polls")

        def get_form_kwargs(self):
            kwargs = super(PollCRUDL.Select, self).get_form_kwargs()
            kwargs['org'] = self.request.org
            return kwargs

        def form_valid(self, form):
            Poll.sync_with_flows(self.request.org, form.cleaned_data['flows'])
            return HttpResponseRedirect(self.get_success_url())


class PollRunListMixin(object):
    default_order = ('-conducted_on',)

    def get_conducted_on(self, obj):
        return obj.conducted_on.strftime(settings.SITE_DATE_FORMAT)

    def get_participants(self, obj):
        def calculate():
            return obj.get_response_counts(
                self.request.region, self.request.include_subregions)
        counts = get_obj_cacheable(obj, '_response_counts', calculate)
        return chain(counts.values())

    def get_responses(self, obj):
        def calculate():
            return obj.get_response_counts(
                self.request.region, self.request.include_subregions)
        counts = get_obj_cacheable(obj, '_response_counts', calculate)
        if counts[Response.STATUS_PARTIAL]:
            return "{complete} ({partial})".format(
                complete=counts[Response.STATUS_COMPLETE],
                partial=counts[Response.STATUS_PARTIAL],
            )
        else:
            return counts[Response.STATUS_COMPLETE]

    def get_region(self, obj):
        return obj.region.name if obj.region else _("All")

    def lookup_field_link(self, context, field, obj):
        if field == 'poll':
            return reverse('polls.poll_read', args=[obj.poll_id])
        if field == 'conducted_on':
            return reverse('polls.pollrun_read', args=[obj.pk])
        elif field == 'participants':
            return reverse('polls.pollrun_participation', args=[obj.pk])
        elif field == 'responses':
            return reverse('polls.response_by_pollrun', args=[obj.pk])


class PollRunCRUDL(smartmin.SmartCRUDL):
    model = PollRun
    actions = (
        'create', 'restart', 'read', 'participation', 'list', 'by_poll',
        'latest')

    class Create(OrgPermsMixin, smartmin.SmartCreateView):

        def post(self, request, *args, **kwargs):
            try:
                poll = Poll.get_all(self.request.org).get(pk=request.POST.get('poll'))
            except Poll.DoesNotExist:
                return HttpResponseBadRequest()

            kwargs = {
                'region': request.region,
                'poll': poll,
                'created_by': self.request.user,
            }

            # Note: This is separate from the include_subregions session
            # setting.
            if request.POST.get('propagate', False):
                pollrun = PollRun.objects.create_propagated(**kwargs)
            else:
                pollrun = PollRun.objects.create_regional(**kwargs)

            return JsonResponse(pollrun.as_json(
                request.region, self.request.include_subregions))

    class Restart(OrgPermsMixin, smartmin.SmartFormView):

        def post(self, request, *args, **kwargs):
            org = self.derive_org()
            pollrun = PollRun.objects.by_org(org).get(
                pk=request.POST.get('pollrun'))
            region = request.region

            incomplete_responses = pollrun.get_incomplete_responses(region)
            contact_uuids = [r.contact.uuid for r in incomplete_responses]

            tasks.pollrun_restart_participants.delay(pollrun.pk, contact_uuids)

            return JsonResponse({'contacts': len(contact_uuids)})

    class Read(OrgPermsMixin, smartmin.SmartReadView):

        def get_queryset(self):
            return PollRun.objects.get_all(
                self.request.region,
                self.request.include_subregions)

        def get_context_data(self, **kwargs):
            context = super(PollRunCRUDL.Read, self).get_context_data(**kwargs)
            questions = self.object.poll.get_questions()

            for question in questions:
                question.chart_type, question.chart_data = charts.single_pollrun(
                    self.object, question, self.request.data_regions)

            context['questions'] = questions
            return context

    class Participation(OrgPermsMixin, smartmin.SmartReadView):

        def get_queryset(self):
            return PollRun.objects.get_all(
                self.request.region,
                self.request.include_subregions)

        def get_context_data(self, **kwargs):
            context = super(PollRunCRUDL.Participation, self).get_context_data(**kwargs)
            reporting_groups = Group.get_all(self.request.org).order_by('name')
            responses = self.object.get_responses(self.request.region)

            # initialize an ordered dict of group to response counts
            per_group_counts = OrderedDict()
            for reporting_group in reporting_groups:
                per_group_counts[reporting_group] = dict(E=0, P=0, C=0)

            no_group_counts = dict(E=0, P=0, C=0)
            overall_counts = dict(E=0, P=0, C=0)

            reporting_groups_by_id = {g.pk: g for g in reporting_groups}
            for response in responses:
                group_id = response.contact.group_id
                group = reporting_groups_by_id[group_id] if group_id else None
                status = response.status

                if group:
                    per_group_counts[group][status] += 1
                else:
                    no_group_counts[status] += 1

                overall_counts[status] += 1

            def calc_completion(counts):
                total = counts['E'] + counts['P'] + counts['C']
                return "%d%%" % int(100 * counts['C'] / total) if total else ''

            # for each set of counts, also calculate the completion percentage
            for group, counts in per_group_counts.iteritems():
                counts['X'] = calc_completion(counts)

            no_group_counts['X'] = calc_completion(no_group_counts)
            overall_counts['X'] = calc_completion(overall_counts)

            # participation table counts
            context['per_group_counts'] = per_group_counts
            context['no_group_counts'] = no_group_counts<commit_msg>Handle if response is not for a requested reporter group<commit_after>from __future__ import absolute_import, unicode_literals

from collections import OrderedDict
from itertools import chain

import unicodecsv

from dash.orgs.views import OrgPermsMixin, OrgObjPermsMixin
from dash.utils import datetime_to_ms, get_obj_cacheable

from django.conf import settings
from django.core.urlresolvers import reverse
from django.http import (
    HttpResponse, HttpResponseBadRequest, HttpResponseRedirect, JsonResponse)
from django.shortcuts import get_object_or_404
from django.utils.translation import ugettext_lazy as _

from smartmin import views as smartmin
from smartmin.templatetags.smartmin import format_datetime

from tracpro.contacts.models import Contact
from tracpro.groups.models import Group

from . import charts, forms, tasks
from .models import Poll, Question, PollRun, Response, Window


class PollCRUDL(smartmin.SmartCRUDL):
    model = Poll
    actions = ('read', 'update', 'list', 'select')

    class PollMixin(object):

        def get_queryset(self):
            """Only allow viewing active polls for the current org."""
            return Poll.get_all(self.request.org)

    class Read(PollMixin, OrgObjPermsMixin, smartmin.SmartReadView):

        def get_context_data(self, **kwargs):
            context = super(PollCRUDL.Read, self).get_context_data(**kwargs)
            questions = self.object.get_questions()
            pollruns = self.object.get_pollruns(
                self.request.region, self.request.include_subregions)

            # if we're viewing "All Regions" don't include regional only pollruns
            if not self.request.region:
                pollruns = pollruns.universal()

            window = self.request.POST.get('window', self.request.GET.get('window', None))
            window = Window[window] if window else Window.last_30_days
            window_min, window_max = window.to_range()

            pollruns = pollruns.filter(conducted_on__gte=window_min, conducted_on__lt=window_max)
            pollruns = pollruns.order_by('conducted_on')

            for question in questions:
                question.chart_type, question.chart_data = charts.multiple_pollruns(
                    pollruns, question, self.request.data_regions)

            context['window'] = window
            context['window_min'] = datetime_to_ms(window_min)
            context['window_max'] = datetime_to_ms(window_max)
            context['window_options'] = Window.__members__.values()
            context['questions'] = questions
            return context

    class Update(PollMixin, OrgObjPermsMixin, smartmin.SmartUpdateView):
        exclude = ('is_active', 'flow_uuid', 'org')
        form_class = forms.PollForm

        def post_save(self, obj):
            for field_key, value in self.form.cleaned_data.iteritems():
                if field_key.startswith('__question__'):
                    question_id = field_key.split('__')[2]
                    Question.objects.filter(pk=question_id, poll=self.object).update(text=value)

    class List(PollMixin, OrgPermsMixin, smartmin.SmartListView):
        fields = ('name', 'questions', 'pollruns', 'last_conducted')
        field_config = {'pollruns': {'label': _("Dates")}}
        link_fields = ('name', 'pollruns')
        default_order = ('name',)

        def derive_pollruns(self, obj):
            return obj.get_pollruns(
                self.request.region, self.request.include_subregions)

        def get_questions(self, obj):
            return obj.get_questions().count()

        def get_pollruns(self, obj):
            return self.derive_pollruns(obj).count()

        def get_last_conducted(self, obj):
            last_pollrun = self.derive_pollruns(obj).order_by('-conducted_on').first()
            return last_pollrun.conducted_on if last_pollrun else _("Never")

        def lookup_field_link(self, context, field, obj):
            if field == 'pollruns':
                return reverse('polls.pollrun_by_poll', args=[obj.pk])

            return super(PollCRUDL.List, self).lookup_field_link(context, field, obj)

    class Select(OrgPermsMixin, smartmin.SmartFormView):
        title = _("Poll Flows")
        form_class = forms.FlowsForm
        success_url = '@polls.poll_list'
        submit_button_name = _("Update")
        success_message = _("Updated flows to track as polls")

        def get_form_kwargs(self):
            kwargs = super(PollCRUDL.Select, self).get_form_kwargs()
            kwargs['org'] = self.request.org
            return kwargs

        def form_valid(self, form):
            Poll.sync_with_flows(self.request.org, form.cleaned_data['flows'])
            return HttpResponseRedirect(self.get_success_url())


class PollRunListMixin(object):
    default_order = ('-conducted_on',)

    def get_conducted_on(self, obj):
        return obj.conducted_on.strftime(settings.SITE_DATE_FORMAT)

    def get_participants(self, obj):
        def calculate():
            return obj.get_response_counts(
                self.request.region, self.request.include_subregions)
        counts = get_obj_cacheable(obj, '_response_counts', calculate)
        return chain(counts.values())

    def get_responses(self, obj):
        def calculate():
            return obj.get_response_counts(
                self.request.region, self.request.include_subregions)
        counts = get_obj_cacheable(obj, '_response_counts', calculate)
        if counts[Response.STATUS_PARTIAL]:
            return "{complete} ({partial})".format(
                complete=counts[Response.STATUS_COMPLETE],
                partial=counts[Response.STATUS_PARTIAL],
            )
        else:
            return counts[Response.STATUS_COMPLETE]

    def get_region(self, obj):
        return obj.region.name if obj.region else _("All")

    def lookup_field_link(self, context, field, obj):
        if field == 'poll':
            return reverse('polls.poll_read', args=[obj.poll_id])
        if field == 'conducted_on':
            return reverse('polls.pollrun_read', args=[obj.pk])
        elif field == 'participants':
            return reverse('polls.pollrun_participation', args=[obj.pk])
        elif field == 'responses':
            return reverse('polls.response_by_pollrun', args=[obj.pk])


class PollRunCRUDL(smartmin.SmartCRUDL):
    model = PollRun
    actions = (
        'create', 'restart', 'read', 'participation', 'list', 'by_poll',
        'latest')

    class Create(OrgPermsMixin, smartmin.SmartCreateView):

        def post(self, request, *args, **kwargs):
            try:
                poll = Poll.get_all(self.request.org).get(pk=request.POST.get('poll'))
            except Poll.DoesNotExist:
                return HttpResponseBadRequest()

            kwargs = {
                'region': request.region,
                'poll': poll,
                'created_by': self.request.user,
            }

            # Note: This is separate from the include_subregions session
            # setting.
            if request.POST.get('propagate', False):
                pollrun = PollRun.objects.create_propagated(**kwargs)
            else:
                pollrun = PollRun.objects.create_regional(**kwargs)

            return JsonResponse(pollrun.as_json(
                request.region, self.request.include_subregions))

    class Restart(OrgPermsMixin, smartmin.SmartFormView):

        def post(self, request, *args, **kwargs):
            org = self.derive_org()
            pollrun = PollRun.objects.by_org(org).get(
                pk=request.POST.get('pollrun'))
            region = request.region

            incomplete_responses = pollrun.get_incomplete_responses(region)
            contact_uuids = [r.contact.uuid for r in incomplete_responses]

            tasks.pollrun_restart_participants.delay(pollrun.pk, contact_uuids)

            return JsonResponse({'contacts': len(contact_uuids)})

    class Read(OrgPermsMixin, smartmin.SmartReadView):

        def get_queryset(self):
            return PollRun.objects.get_all(
                self.request.region,
                self.request.include_subregions)

        def get_context_data(self, **kwargs):
            context = super(PollRunCRUDL.Read, self).get_context_data(**kwargs)
            questions = self.object.poll.get_questions()

            for question in questions:
                question.chart_type, question.chart_data = charts.single_pollrun(
                    self.object, question, self.request.data_regions)

            context['questions'] = questions
            return context

    class Participation(OrgPermsMixin, smartmin.SmartReadView):

        def get_queryset(self):
            return PollRun.objects.get_all(
                self.request.region,
                self.request.include_subregions)

        def get_context_data(self, **kwargs):
            context = super(PollRunCRUDL.Participation, self).get_context_data(**kwargs)
            reporting_groups = Group.get_all(self.request.org).order_by('name')
            responses = self.object.get_responses(
                self.request.region,
                self.request.include_subregions)

            # initialize an ordered dict of group to response counts
            per_group_counts = OrderedDict()
            for reporting_group in reporting_groups:
                per_group_counts[reporting_group] = dict(E=0, P=0, C=0)

            no_group_counts = dict(E=0, P=0, C=0)
            overall_counts = dict(E=0, P=0, C=0)

            reporting_groups_by_id = {g.pk: g for g in reporting_groups}
            for response in responses:
                group_id = response.contact.group_id
                group = reporting_groups_by_id[group_id] if group_id else None
                status = response.status

                if group:
                    try:
                        per_group_counts[group][status] += 1
                    except KeyError:
                        continue  # not for a relevant group
                else:
                    no_group_counts[status] += 1

                overall_counts[status] += 1

            def calc_completion(counts):
                total = counts['E'] + counts['P'] + counts['C']
                return "%d%%" % int(100 * counts['C'] / total) if total else ''

            # for each set of counts, also calculate the completion percentage
            for group, counts in per_group_counts.iteritems():
                counts['X'] = calc_completion(counts)

            no_group_counts['X'] = calc_completion(no_group_counts)
            overall_counts['X'] = calc_completion(overall_counts)

            # participation table counts
            context['per_group_counts'] = per_group_counts
            context['no_group_counts'] = no_group_counts
{'fraction_non_alphanumeric': 0.09832089552238805, 'fraction_numerical': 0.001958955223880597, 'mean_word_length': 2.4543257612373126, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2606373', 'n_tokens_mistral': 6293, 'n_tokens_neox': 5956, 'n_words': 1245}