Пример #1
0
def pollrun_start(pollrun_id):
    """
    Starts a newly created pollrun by creating runs in RapidPro and creating
    empty responses for them.
    """
    from tracpro.polls.models import PollRun, Response

    pollrun = PollRun.objects.select_related('poll', 'region').get(pk=pollrun_id)
    if pollrun.pollrun_type not in (PollRun.TYPE_PROPAGATED, PollRun.TYPE_REGIONAL):
        raise ValueError("Can't start non-regional poll")

    org = pollrun.poll.org
    client = org.get_temba_client()

    contacts = Contact.objects.filter(is_active=True)
    if pollrun.pollrun_type == PollRun.TYPE_PROPAGATED:
        descendants = pollrun.region.get_descendants(include_self=True)
        contacts = contacts.filter(region__in=descendants)
    elif pollrun.pollrun_type == PollRun.TYPE_REGIONAL:
        contacts = contacts.filter(region=pollrun.region)
    contact_uuids = contacts.values_list('uuid', flat=True)

    runs = client.create_runs(pollrun.poll.flow_uuid, contact_uuids, restart_participants=True)
    for run in runs:
        Response.create_empty(org, pollrun, run)

    logger.info("Created %d new runs for new poll pollrun #%d" % (len(runs), pollrun.pk))
Пример #2
0
    def test_list(self):
        pollrun1 = factories.UniversalPollRun(
            poll=self.poll1, conducted_on=datetime.datetime(2014, 12, 1, tzinfo=pytz.UTC))
        Response.create_empty(
            self.unicef, pollrun1,
            Run.create(id=123, contact='C-001', created_on=timezone.now()))

        self.login(self.admin)
        response = self.url_get('unicef', reverse('contacts.contact_list'))
        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(response.context['object_list']), 5)
        # no poll pollruns shown in "All Regions" view
        self.assertNotContains(response, "Farm Poll")

        url = '{}?search=an'.format(reverse('contacts.contact_list'))
        response = self.url_get('unicef', url)
        self.assertEqual(len(response.context['object_list']), 2)
        self.assertContains(response, "Ann")
        self.assertContains(response, "Dan")

        self.login(self.user1)

        response = self.url_get('unicef', reverse('contacts.contact_list'))
        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(response.context['object_list']), 3)
        self.assertContains(response, "Farm Poll")
Пример #3
0
def pollrun_start(pollrun_id):
    """
    Starts a newly created pollrun by creating runs in RapidPro and creating
    empty responses for them.
    """
    from tracpro.polls.models import PollRun, Response

    pollrun = PollRun.objects.select_related('poll',
                                             'region').get(pk=pollrun_id)
    if pollrun.pollrun_type not in (PollRun.TYPE_PROPAGATED,
                                    PollRun.TYPE_REGIONAL):
        raise ValueError("Can't start non-regional poll")

    org = pollrun.poll.org
    client = org.get_temba_client()

    contacts = Contact.objects.active()
    if pollrun.pollrun_type == PollRun.TYPE_PROPAGATED:
        descendants = pollrun.region.get_descendants(include_self=True)
        contacts = contacts.filter(region__in=descendants)
    elif pollrun.pollrun_type == PollRun.TYPE_REGIONAL:
        contacts = contacts.filter(region=pollrun.region)
    contact_uuids = list(contacts.values_list('uuid', flat=True))

    runs = client.create_runs(pollrun.poll.flow_uuid,
                              contact_uuids,
                              restart_participants=True)
    for run in runs:
        Response.create_empty(org, pollrun, run)

    logger.info("Created %d new runs for new poll pollrun #%d" %
                (len(runs), pollrun.pk))
Пример #4
0
def pollrun_restart_participants(pollrun_id, contact_uuids):
    """
    Restarts the given contacts in the given poll pollrun by replacing any
    existing response they have with an empty one.
    """
    from tracpro.polls.models import PollRun, Response

    pollrun = PollRun.objects.select_related('poll',
                                             'region').get(pk=pollrun_id)
    if pollrun.pollrun_type not in (PollRun.TYPE_REGIONAL,
                                    PollRun.TYPE_PROPAGATED):
        raise ValueError("Can't restart participants of a non-regional poll")

    if not pollrun.is_last_for_region(pollrun.region):
        raise ValueError("Can only restart last pollrun of poll for a region")

    org = pollrun.poll.org
    client = org.get_temba_client()

    runs = client.create_runs(pollrun.poll.flow_uuid,
                              contact_uuids,
                              restart_participants=True)
    for run in runs:
        Response.create_empty(org, pollrun, run)

    logger.info("Created %d restart runs for poll pollrun #%d" %
                (len(runs), pollrun.pk))
Пример #5
0
    def org_task(self, org):
        """
        Fetches new and modified flow runs for the given org and creates/updates
        poll responses.
        """
        from tracpro.orgs_ext.constants import TaskType
        from tracpro.polls.models import Poll, PollRun, Response

        client = org.get_temba_client()
        redis_connection = get_redis_connection()
        last_time_key = LAST_FETCHED_RUN_TIME_KEY % org.pk
        last_time = redis_connection.get(last_time_key)

        if last_time is not None:
            last_time = parse_iso8601(last_time)
        else:
            newest_runs = Response.objects.filter(
                pollrun__poll__org=org).order_by('-created_on')
            newest_runs = newest_runs.exclude(
                pollrun__pollrun_type=PollRun.TYPE_SPOOFED)
            newest_run = newest_runs.first()
            last_time = newest_run.created_on if newest_run else None

        until = timezone.now()

        total_runs = 0
        for poll in Poll.objects.active().by_org(org):
            poll_runs = client.get_runs(flows=[poll.flow_uuid],
                                        after=last_time,
                                        before=until)
            total_runs += len(poll_runs)

            # convert flow runs into poll responses
            for run in poll_runs:
                try:
                    Response.from_run(org, run, poll=poll)
                except ValueError as e:
                    logger.error("Unable to save run #%d due to error: %s" %
                                 (run.id, e.message))
                    continue

        logger.info("Fetched %d new and updated runs for org #%d (since=%s)" %
                    (total_runs, org.id,
                     format_iso8601(last_time) if last_time else 'Never'))

        task_result = dict(time=datetime_to_ms(timezone.now()),
                           counts=dict(fetched=total_runs))
        org.set_task_result(TaskType.fetch_runs, task_result)

        redis_connection.set(last_time_key, format_iso8601(until))
Пример #6
0
def fetch_org_runs(org_id):
    """
    Fetches new and modified flow runs for the given org and creates/updates
    poll responses.
    """
    from tracpro.orgs_ext.constants import TaskType
    from tracpro.polls.models import Poll, PollRun, Response

    org = Org.objects.get(pk=org_id)

    client = org.get_temba_client()
    redis_connection = get_redis_connection()
    last_time_key = LAST_FETCHED_RUN_TIME_KEY % org.pk
    last_time = redis_connection.get(last_time_key)

    if last_time is not None:
        last_time = parse_iso8601(last_time)
    else:
        newest_runs = Response.objects.filter(pollrun__poll__org=org).order_by("-created_on")
        newest_runs = newest_runs.exclude(pollrun__pollrun_type=PollRun.TYPE_SPOOFED)
        newest_run = newest_runs.first()
        last_time = newest_run.created_on if newest_run else None

    until = timezone.now()

    total_runs = 0
    for poll in Poll.get_all(org):
        poll_runs = client.get_runs(flows=[poll.flow_uuid], after=last_time, before=until)
        total_runs += len(poll_runs)

        # convert flow runs into poll responses
        for run in poll_runs:
            try:
                Response.from_run(org, run, poll=poll)
            except ValueError as e:
                logger.error("Unable to save run #%d due to error: %s" % (run.id, e.message))
                continue

    logger.info(
        "Fetched %d new and updated runs for org #%d (since=%s)"
        % (total_runs, org.id, format_iso8601(last_time) if last_time else "Never")
    )

    task_result = dict(time=datetime_to_ms(timezone.now()), counts=dict(fetched=total_runs))
    org.set_task_result(TaskType.fetch_runs, task_result)

    redis_connection.set(last_time_key, format_iso8601(until))
Пример #7
0
    def handle(self, *args, **options):
        org_id = int(args[0]) if args else None
        if not org_id:
            raise CommandError("Most provide valid org id")

        try:
            org = Org.objects.get(pk=org_id)
        except Org.DoesNotExist:
            raise CommandError("No such org with id %d" % org_id)

        minutes, hours, days = options['minutes'], options['hours'], options[
            'days']

        if not (minutes or hours or days):
            raise CommandError(
                "Must provide at least one of --minutes --hours or --days")

        since = timezone.now() - relativedelta(
            minutes=minutes, hours=hours, days=days)

        self.stdout.write('Fetching responses for org %s since %s...' %
                          (org.name, since.strftime('%b %d, %Y %H:%M')))

        client = org.get_temba_client()

        polls_by_flow_uuids = {
            p.flow_uuid: p
            for p in Poll.objects.active().by_org(org)
        }

        runs = client.get_runs(flows=polls_by_flow_uuids.keys(), after=since)

        self.stdout.write("Fetched %d runs for org %s" % (len(runs), org.id))

        created = 0
        updated = 0
        for run in runs:
            if run.flow not in polls_by_flow_uuids:
                continue  # Response is for a Poll not tracked for this org.

            poll = polls_by_flow_uuids[run.flow]
            try:
                response = Response.from_run(org, run, poll=poll)
            except ValueError as e:
                self.stderr.write("Unable to save run #%d due to error: %s" %
                                  (run.id, e.message))
                continue

            if getattr(response, 'is_new', False):
                created += 1
            else:
                updated += 1

        self.stdout.write(
            "Created %d new responses and updated %d existing responses" %
            (created, updated))
Пример #8
0
    def test_list(self):
        issue1 = Issue.objects.create(poll=self.poll1, region=None, conducted_on=self.datetime(2014, 12, 1))
        Response.create_empty(self.unicef, issue1, Run.create(id=123, contact='C-001', created_on=timezone.now()))

        self.login(self.admin)
        response = self.url_get('unicef', reverse('contacts.contact_list'))
        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(response.context['object_list']), 5)
        self.assertNotContains(response, "Farm Poll")  # no poll issues shown in "All Regions" view

        response = self.url_get('unicef', '%s?search=an' % reverse('contacts.contact_list'))
        self.assertEqual(len(response.context['object_list']), 2)
        self.assertContains(response, "Ann")
        self.assertContains(response, "Dan")

        self.login(self.user1)

        response = self.url_get('unicef', reverse('contacts.contact_list'))
        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(response.context['object_list']), 3)
        self.assertContains(response, "Farm Poll")
Пример #9
0
def pollrun_restart_participants(pollrun_id, contact_uuids):
    """
    Restarts the given contacts in the given poll pollrun by replacing any
    existing response they have with an empty one.
    """
    from tracpro.polls.models import PollRun, Response

    pollrun = PollRun.objects.select_related('poll', 'region').get(pk=pollrun_id)
    if pollrun.pollrun_type not in (PollRun.TYPE_REGIONAL, PollRun.TYPE_PROPAGATED):
        raise ValueError("Can't restart participants of a non-regional poll")

    if not pollrun.is_last_for_region(pollrun.region):
        raise ValueError("Can only restart last pollrun of poll for a region")

    org = pollrun.poll.org
    client = org.get_temba_client()

    runs = client.create_runs(pollrun.poll.flow_uuid, contact_uuids, restart_participants=True)
    for run in runs:
        Response.create_empty(org, pollrun, run)

    logger.info("Created %d restart runs for poll pollrun #%d" % (len(runs), pollrun.pk))
Пример #10
0
    def handle(self, *args, **options):
        org_id = int(args[0]) if args else None
        if not org_id:
            raise CommandError("Most provide valid org id")

        try:
            org = Org.objects.get(pk=org_id)
        except Org.DoesNotExist:
            raise CommandError("No such org with id %d" % org_id)

        minutes, hours, days = options['minutes'], options['hours'], options['days']

        if not (minutes or hours or days):
            raise CommandError("Must provide at least one of --minutes --hours or --days")

        since = timezone.now() - relativedelta(minutes=minutes, hours=hours, days=days)

        self.stdout.write('Fetching responses for org %s since %s...' % (org.name, since.strftime('%b %d, %Y %H:%M')))

        client = org.get_temba_client()

        polls_by_flow_uuids = {p.flow_uuid: p for p in Poll.get_all(org)}

        runs = client.get_runs(flows=polls_by_flow_uuids.keys(), after=since)

        self.stdout.write("Fetched %d runs for org %s" % (len(runs), org.id))

        created = 0
        updated = 0
        for run in runs:
            if run.flow not in polls_by_flow_uuids:
                continue  # Response is for a Poll not tracked for this org.

            poll = polls_by_flow_uuids[run.flow]
            try:
                response = Response.from_run(org, run, poll=poll)
            except ValueError as e:
                self.stderr.write("Unable to save run #%d due to error: %s" % (run.id, e.message))
                continue

            if getattr(response, 'is_new', False):
                created += 1
            else:
                updated += 1

        self.stdout.write("Created %d new responses and updated %d existing responses" % (created, updated))