コード例 #1
0
def get_or_generate_indicator(indicator_description):
    try:
        indicator = Indicator.objects.get(slug=indicator_description['slug'])
    except ObjectDoesNotExist:
        # add basic fields to indicator
        indicator = Indicator(**{k: v for k, v in indicator_description.items() if k != 'subdomain'})
        indicator.save()
        print(indicator_description['subdomain'])
        # add indicator to its subdomain
        subdomain = get_or_generate_subdomain(indicator_description['subdomain'])
        subdomain.indicators.add(indicator)
        subdomain.save()
    return indicator
コード例 #2
0
def create_model(data, date, _sector):
    for _block in data:
        block = Block.objects.get(name=_block)
        # print(_block)
        print(date)
        for key in data[_block]:
            serial = str(key)
            # num = random.randrange(1000, 5000)
            # den = random.randrange(5001, 9999)
            num = data[_block][key][0]
            den = data[_block][key][1]
            per = float((float(num) / den) * 100)
            # print('{} {} {} {}'.format(serial, num, den, per))
            Indicator.objects.create(serial=serial,
                                     block=block,
                                     numerator=num,
                                     denominator=den,
                                     percent=per,
                                     sector=_sector,
                                     created=date)
        month = datetime.datetime.strptime(date, '%Y-%m-%d').month
        year = datetime.datetime.strptime(date, '%Y-%m-%d').year
        for _serial in health_indicators:
            objs = Indicator.objects.all().filter(serial=_serial,
                                                  created__month=month,
                                                  created__year=year)
            mx = Indicator.max_percent(serial=_serial, month=month, year=year)
            for i in objs:
                i.max = mx
                i.save()
コード例 #3
0
    def save_indicators(self, indicators_json, program):
        for indicator_data in indicators_json:

            # Pop off the ones that will need extensive processing
            unassigned_results_json = indicator_data.pop('result_set')
            periodic_targets_json = indicator_data.pop('periodictargets')

            # Pop off the many-to-many fields that will be added after the indicator is saved
            indicator_types = indicator_data.pop('indicator_type')
            objectives = indicator_data.pop('objectives')
            strategic_objectives = indicator_data.pop('strategic_objectives')
            # TODO: disaggregation types should be handled
            disaggregations = indicator_data.pop('disaggregation')

            # First do the foreign keys and save the indicator
            indicator_data['level'] = self.replace_names_with_values(
                indicator_data['level'], Level, 'name', ['name'])
            indicator_data[
                'data_collection_frequency'] = self.replace_names_with_values(
                    indicator_data['data_collection_frequency'],
                    DataCollectionFrequency, 'frequency', ['frequency'])
            indicator_data[
                'reporting_frequency'] = self.replace_names_with_values(
                    indicator_data['reporting_frequency'], ReportingFrequency,
                    'frequency', ['frequency'])
            indicator_data['sector'] = self.replace_names_with_values(
                indicator_data['sector'], Sector, 'sector', ['sector'])
            indicator_data[
                'external_service_record'] = self.replace_names_with_values(
                    indicator_data['external_service_record'], ExternalService,
                    'name', ['name'])
            indicator_data['approved_by'] = self.replace_names_with_values(
                indicator_data['approved_by'], TolaUser, 'name', ['name'])
            indicator_data[
                'approval_submitted_by'] = self.replace_names_with_values(
                    indicator_data['approval_submitted_by'], TolaUser, 'name',
                    ['name'])

            indicator = Indicator(**indicator_data)
            indicator.program = program
            indicator.save()

            indicator_types = self.replace_names_with_values(
                indicator_types, IndicatorType, 'indicator_type',
                ['indicator_type'])
            objectives = self.replace_names_with_values(
                objectives, Objective, 'name', ['name', 'program_id'])
            strategic_objectives = self.replace_names_with_values(
                strategic_objectives, StrategicObjective, 'name', ['name'])

            indicator.indicator_type.add(*indicator_types)
            indicator.objectives.add(*objectives)
            indicator.strategic_objectives.add(*strategic_objectives)
            indicator.save()

            self.save_periodic_targets(periodic_targets_json, indicator)
            self.save_results(unassigned_results_json, indicator)
コード例 #4
0
 def list(self, request, *args, **kwargs):
     queryset = self.get_queryset()
     serializer = IndicatorSerializer(queryset, many=True)
     serial = self.request.query_params.get('serial', None)
     year = self.request.query_params.get('year', None)
     month = self.request.query_params.get('month', None)
     max_score = Indicator.max_percent(
         serial=serial, month=month,
         year=year) if serial and month and year is not None else None
     new_serializer_data = list(serializer.data)
     if max_score is not None:
         new_serializer_data.append({'max_percent': max_score})
     return Response(new_serializer_data)
コード例 #5
0
def periodic_targets_form(request, program):
    """
    Returns a form for the periodic targets sub-section,
    used by the Indicator Form

    For historical reasons, the input is a POST of the whole indicator form sent via ajax
    from which a subset of fields are used to generate the returned template
    """
    if not request.has_write_access:
        raise PermissionDenied

    program = get_object_or_404(Program, pk=program)

    form = PTFormInputsForm(data=request.POST)

    if not form.is_valid():
        return JsonResponse(form.errors)

    event_name = ''
    start_date = ''
    target_frequency_num_periods = 1
    target_frequency_type = form.cleaned_data.get('target_frequency')

    if target_frequency_type in Indicator.REGULAR_TARGET_FREQUENCIES:
        start_date = program.reporting_period_start
        # target_frequency_num_periods = IPTT_ReportView._get_num_periods(
        #     start_date, program.reporting_period_end, target_frequency_type)
        target_frequency_num_periods = len([
            p for p in PeriodicTarget.generate_for_frequency(
                target_frequency_type)(start_date,
                                       program.reporting_period_end)
        ])

    generated_targets = generate_periodic_targets(
        target_frequency_type, start_date, target_frequency_num_periods,
        event_name)

    dummy_indicator = Indicator(
        target_frequency=target_frequency_type,
        unit_of_measure_type=form.cleaned_data.get('unit_of_measure_type'),
        is_cumulative=False,
    )

    content = render_to_string('indicators/indicatortargets.html', {
        'indicator': dummy_indicator,
        'periodic_targets': generated_targets
    })

    return JsonResponse({
        'content': content,
    })
コード例 #6
0
def calculate_score(blocks, sector, month, year):
    data = {}
    vals = {}
    for key in health_indicators:
        tmp = {}
        min, max, rnge = Indicator.get_serial_minmax(serial=key,
                                                     month=month,
                                                     year=year)
        tmp['min'] = float(min)
        tmp['max'] = float(max)
        tmp['range'] = float(rnge)
        # print('{} {} {}'.format(min, max, rnge))
        vals[key] = tmp
    queryset = Indicator.objects.filter(created__year=year,
                                        created__month=month)
    for block in blocks:
        blk = Block.objects.get(name=block)
        obj1 = queryset.filter(block=blk)
        cmp = 0.0
        total_weight = 0.0
        for key in health_indicators:
            if vals[key]['range'] == 0:
                continue
            obj2 = obj1.filter(serial=key).first()
            per = float(obj2.percent)
            cmp = cmp + health_indicators[key]['weight'] * (
                (per - vals[key]['min']) / vals[key]['range'])
            total_weight += health_indicators[key]['weight']
        data[block] = (cmp / total_weight)
    data_sorted = sorted(data.items(), key=itemgetter(1), reverse=True)
    rank = {}
    for i in range(0, len(data_sorted)):
        rank[data_sorted[i][0]] = i + 1
    # print(data)
    # print(rank)
    for block in blocks:
        Score.objects.create(composite=data[block],
                             rank=rank[block],
                             block=Block.objects.get(name=block),
                             period=datetime.datetime(year, month,
                                                      1).strftime('%Y-%m-%d'))
コード例 #7
0
    def create_indicators(
        self, program_id, param_sets, indicator_suffix='', apply_skips=True, apply_rf_skips=False,
        personal_indicator=False):
        indicator_ids = []
        program = Program.objects.get(id=program_id)
        frequency_labels = {
            Indicator.LOP: 'LoP only',
            Indicator.MID_END: 'Midline and endline',
            Indicator.EVENT: 'Event',
            Indicator.ANNUAL: 'Annual',
            Indicator.SEMI_ANNUAL: 'Semi-annual',
            Indicator.TRI_ANNUAL: 'Tri-annual',
            Indicator.QUARTERLY: 'Quarterly',
            Indicator.MONTHLY: 'Monthly',
        }
        uom_labels = {
            Indicator.NUMBER: 'Number (#)',
            Indicator.PERCENTAGE: "Percentage (%)",
        }
        direction_labels = {
            Indicator.DIRECTION_OF_CHANGE_NONE: "Direction of change NA",
            Indicator.DIRECTION_OF_CHANGE_POSITIVE: "Increase (+)",
            Indicator.DIRECTION_OF_CHANGE_NEGATIVE: "Decrease (-)",
        }

        # Keep track of results and evidence created across the whole programs so we can skip them periodically
        result_count = 0
        result_skip_mod = 7
        evidence_count = 0
        evidence_skip_mod = 7

        old_levels = list(Indicator.objects.filter(old_level__isnull=False).order_by('old_level')
                          .distinct().values_list('old_level', flat=True))
        old_levels.append(None)
        old_level_cycle = cycle(old_levels)

        rf_levels = list(Level.objects.filter(program__id=program.id))
        if apply_rf_skips:
            rf_levels.append(None)
        rf_level_cycle = cycle(rf_levels)

        indicator_types = list(IndicatorType.objects.all())
        if apply_skips:
            indicator_types.append(None)
        type_cycle = cycle(indicator_types)

        sectors = list(Sector.objects.all()[:5])
        if apply_skips:
            sectors.append(None)
        sector_cycle = cycle(sectors)

        sites = list(SiteProfile.objects.filter(country__country="Tolaland"))
        if apply_skips:
            sites.append(None)
        site_cycle = cycle(sites)



        for n, params in enumerate(param_sets):
            if params['is_cumulative']:
                cumulative_text = 'Cumulative'
            else:
                cumulative_text = 'Non-cumulative'

            null_text = '| No {}'.format(params['null_level']) if params['null_level'] else ''

            indicator_name = '{} | {} | {} | {} {}'.format(
                frequency_labels[params['freq']],
                uom_labels[params['uom_type']],
                cumulative_text,
                direction_labels[params['direction']],
                null_text,
            )

            frequency = params['freq']
            if params['null_level'] == 'targets':
                frequency = None

            # Finally, create the indicator
            indicator = Indicator(
                name=indicator_name + ' | ' + indicator_suffix,
                is_cumulative=params['is_cumulative'],
                target_frequency=frequency,
                unit_of_measure='This is a UOM',
                baseline=0,
                unit_of_measure_type=params['uom_type'],
                direction_of_change=params['direction'],
                program=program,
                old_level=None if program.results_framework else next(old_level_cycle),
                level=next(rf_level_cycle),
                sector=None if not personal_indicator else next(sector_cycle),
            )
            indicator.save()

            i_type = next(type_cycle)
            if personal_indicator and i_type:
                indicator.indicator_type.add(i_type)
            indicator.save()
            indicator_ids.append(indicator.id)

            if params['null_level'] == 'targets':
                indicator.lop_target = 100
                indicator.save()
                continue

            self.make_targets(program, indicator)
            periodic_targets = PeriodicTarget.objects.filter(indicator__id=indicator.id)

            # Different combinations of UOM type, direction of change and cummulativeness require
            # different inputs.
            if params['uom_type'] == Indicator.NUMBER:
                if params['direction'] == Indicator.DIRECTION_OF_CHANGE_POSITIVE:
                    if params['is_cumulative']:
                        target_start = 100
                        target_increment = target_start
                        achieved_start = 90
                        achieved_increment = int(achieved_start * 1.1)
                    else:
                        target_start = 100
                        target_increment = target_start
                        achieved_start = 90
                        achieved_increment = int(achieved_start * 1.1)
                else:
                    if params['is_cumulative']:
                        target_start = 500
                        target_increment = -int(math.floor((target_start/len(periodic_targets))/10)*10)
                        achieved_start = 400
                        achieved_increment = target_increment+2
                    else:
                        target_start = 500
                        target_increment = -int(math.floor((target_start/len(periodic_targets))/10)*10)
                        achieved_start = 400
                        achieved_increment = target_increment * .8
            else:
                if params['direction'] == Indicator.DIRECTION_OF_CHANGE_POSITIVE:
                    # Don't need to check non-cumulative because we don't really handle it
                    target_start = 10
                    target_increment = 3
                    achieved_start = 7
                    achieved_increment = 4
                else:
                    # Don't need to check non-cumulative because we don't really handle it
                    target_start = 90
                    target_increment = max(-math.floor(target_start/len(periodic_targets)), -2)
                    achieved_start = 95
                    achieved_increment = target_increment - 1

            lop_target = 0
            day_offset = timedelta(days=2)
            for i, pt in enumerate(periodic_targets):
                # Create the target amount (the PeriodicTarget object has already been created)
                pt.target = target_start + target_increment * i
                pt.save()

                if params['is_cumulative']:
                    lop_target = pt.target
                else:
                    lop_target += pt.target

                # Users shouldn't put in results with a date in the future, so neither should we.
                if pt.start_date and date.today() < pt.start_date + day_offset:
                    continue

                # Skip creating a result if the null_level is result or if
                # the number of results has reached the arbitrary skip point.
                result_count += 1
                if (apply_skips and result_count % result_skip_mod == result_skip_mod - 2) or \
                        params['null_level'] == 'results':
                    continue

                # if params['direction'] == Indicator.DIRECTION_OF_CHANGE_NEGATIVE:
                #     achieved_value = achieved_start - (achieved_increment * i)
                # else:
                achieved_value = achieved_start + (achieved_increment * i)

                results_to_create = 1
                if apply_skips and result_count % result_skip_mod in (1, result_skip_mod - 3):
                    results_to_create = 2
                    if params['uom_type'] == Indicator.NUMBER:
                        achieved_value = int(achieved_value * .4)
                    else:
                        achieved_value = int(achieved_value * .9)

                # Now create the Results and their related Records
                if pt.start_date:
                    date_collected = pt.start_date + day_offset
                else:
                    date_collected = date.today()

                for c in range(results_to_create):
                    rs = Result(
                        periodic_target=pt,
                        indicator=indicator,
                        program=program,
                        achieved=achieved_value,
                        date_collected=date_collected)
                    rs.save()
                    date_collected = date_collected + day_offset
                    if params['uom_type'] == Indicator.NUMBER:
                        achieved_value = int(achieved_value * 1.5)
                    else:
                        achieved_value = int(achieved_value * 1.15)

                    evidence_count += 1
                    if params['null_level'] == 'evidence':
                        continue

                    if apply_skips and evidence_count % evidence_skip_mod == int(evidence_skip_mod / 2):
                        evidence_count += 1
                        continue
                    rs.record_name = 'Evidence {} for result id {}'.format(evidence_count, rs.id)
                    rs.evidence_url = 'http://my/evidence/url'

                    r_site = next(site_cycle)
                    if personal_indicator and r_site:
                        rs.site.add(r_site)

                    rs.save()

            indicator.lop_target = lop_target
            indicator.save()

        return indicator_ids
コード例 #8
0
    def create_partial_indicator_set(self, program_id, indicator_suffix=''):
        indicator_ids = []
        program = Program.objects.get(id=program_id)
        frequency_labels = {
            Indicator.LOP: 'Life of Program (LoP) only',
            Indicator.MID_END: 'Midline and endline',
            Indicator.ANNUAL: 'Annual',
            Indicator.QUARTERLY: 'Quarterly',
        }
        uom_labels = {
            Indicator.DIRECTION_OF_CHANGE_NONE:
            "Direction of change (not applicable)",
            Indicator.NUMBER: 'Number (#)',
            Indicator.PERCENTAGE: "Percentage (%)",
        }
        direction_labels = {
            Indicator.DIRECTION_OF_CHANGE_NONE:
            "Direction of change (not applicable)",
            Indicator.DIRECTION_OF_CHANGE_POSITIVE: "Increase (+)",
            Indicator.DIRECTION_OF_CHANGE_NEGATIVE: "Decrease (-)",
        }

        indicator_types = [
            {
                'freq': Indicator.ANNUAL,
                'uom_type': Indicator.NUMBER,
                'is_cumulative': True,
                'direction': Indicator.DIRECTION_OF_CHANGE_POSITIVE
            },
            {
                'freq': Indicator.ANNUAL,
                'uom_type': Indicator.PERCENTAGE,
                'is_cumulative': True,
                'direction': Indicator.DIRECTION_OF_CHANGE_NONE
            },
            {
                'freq': Indicator.QUARTERLY,
                'uom_type': Indicator.NUMBER,
                'is_cumulative': False,
                'direction': Indicator.DIRECTION_OF_CHANGE_NONE
            },
            {
                'freq': Indicator.QUARTERLY,
                'uom_type': Indicator.PERCENTAGE,
                'is_cumulative': True,
                'direction': Indicator.DIRECTION_OF_CHANGE_NEGATIVE
            },
            {
                'freq': Indicator.LOP,
                'uom_type': Indicator.NUMBER,
                'is_cumulative': True,
                'direction': Indicator.DIRECTION_OF_CHANGE_NONE
            },
            {
                'freq': Indicator.LOP,
                'uom_type': Indicator.PERCENTAGE,
                'is_cumulative': True,
                'direction': Indicator.DIRECTION_OF_CHANGE_NONE
            },
            {
                'freq': Indicator.MID_END,
                'uom_type': Indicator.NUMBER,
                'is_cumulative': True,
                'direction': Indicator.DIRECTION_OF_CHANGE_NONE
            },
            {
                'freq': Indicator.MID_END,
                'uom_type': Indicator.PERCENTAGE,
                'is_cumulative': True,
                'direction': Indicator.DIRECTION_OF_CHANGE_NONE
            },
        ]

        for q, combo in enumerate(indicator_types):

            if combo['is_cumulative']:
                cumulative_text = 'cumulative'
            else:
                cumulative_text = 'non-cumulative'
            indicator_name = '{} | {} | {} | {}'.format(
                frequency_labels[combo['freq']], uom_labels[combo['uom_type']],
                direction_labels[combo['direction']], cumulative_text)
            indicator = Indicator(name=indicator_name + indicator_suffix,
                                  is_cumulative=combo['is_cumulative'],
                                  target_frequency=combo['freq'],
                                  unit_of_measure='This is a UOM',
                                  baseline=0,
                                  unit_of_measure_type=combo['uom_type'],
                                  direction_of_change=combo['direction'],
                                  program=program,
                                  level=Level.objects.get(name='Goal'))
            indicator.save()
            indicator_ids.append(indicator.id)
            if q in [2, 3, 7]:
                continue
            self.make_targets(program, indicator)

            periodic_targets = PeriodicTarget.objects.filter(
                indicator__id=indicator.id)

            # Different combinations of UOM type, direction of change and cummulativeness require
            # different inputs.
            if q == 4:
                continue
            if combo['uom_type'] == Indicator.NUMBER:
                if combo[
                        'direction'] == Indicator.DIRECTION_OF_CHANGE_POSITIVE:
                    if combo['is_cumulative']:
                        target_start = 100
                        target_increment = target_start
                        achieved_start = 90
                        achieved_increment = achieved_start
                    else:
                        target_start = 100
                        target_increment = target_start
                        achieved_start = 90
                        achieved_increment = achieved_start
                else:
                    if combo['is_cumulative']:
                        target_start = 500
                        target_increment = -int(
                            math.floor(
                                (target_start / len(periodic_targets)) / 10) *
                            10)
                        achieved_start = 400
                        achieved_increment = -(target_increment - 2)
                    else:
                        target_start = 500
                        target_increment = -int(
                            math.floor(
                                (target_start / len(periodic_targets)) / 10) *
                            10)
                        achieved_start = 400
                        achieved_increment = -(target_increment - 2)
            else:
                if combo[
                        'direction'] == Indicator.DIRECTION_OF_CHANGE_POSITIVE:
                    # Don't need to check cumulative because we don't really handle it
                    target_start = 5
                    target_increment = 5
                    achieved_start = 4
                    achieved_increment = 5
                else:
                    # Don't need to check cumulative because we don't really handle it
                    target_start = 90
                    target_increment = max(
                        -math.floor(target_start / len(periodic_targets)), -2)
                    achieved_start = 95
                    achieved_increment = target_increment + 1

            lop_target = 0
            day_offset = timedelta(days=2)
            for i, pt in enumerate(periodic_targets):
                # Create the target amount (the PeriodicTarget object has already been created)
                pt.target = target_start + target_increment * i
                pt.save()

                if combo['is_cumulative']:
                    lop_target = pt.target
                else:
                    lop_target += pt.target

                # Users shouldn't put in results with a date in the future, so neither should we.
                if pt.start_date and date.today() < pt.start_date + day_offset:
                    continue

                # Now create the Results and their related Records
                if pt.start_date:
                    date_collected = pt.start_date + day_offset
                else:
                    date_collected = date.today()
                cd = CollectedData(periodic_target=pt,
                                   indicator=indicator,
                                   program=program,
                                   achieved=achieved_start +
                                   achieved_increment * i,
                                   date_collected=date_collected)
                cd.save()

                if q in [5, 6]:
                    continue
                document = Documentation.objects.create(
                    program=program,
                    name='Doc for CDid {}'.format(cd.id),
                    url='http://my/doc/here/')
                cd.evidence = document
                cd.save()

            indicator.lop_target = lop_target
            indicator.save()

        return indicator_ids
コード例 #9
0
    def create_full_indicator_set(self,
                                  program_id,
                                  indicator_suffix='',
                                  null_level=0):
        if null_level == self.NULL_LEVELS['INDICATORS']:
            return
        indicator_ids = []
        program = Program.objects.get(id=program_id)

        seq = 0
        for direction in (Indicator.DIRECTION_OF_CHANGE_POSITIVE,
                          Indicator.DIRECTION_OF_CHANGE_NEGATIVE):
            for uom_type in Indicator.UNIT_OF_MEASURE_TYPES:
                for freq in Indicator.TARGET_FREQUENCIES:
                    for is_cumulative in (True, False):
                        if is_cumulative:
                            cumulative_text = 'cumulative'
                        else:
                            cumulative_text = 'non-cumulative'
                        indicator_name = '{} | {} | {} | {}'.format(
                            freq[1], uom_type[1],
                            Indicator.DIRECTION_OF_CHANGE[direction - 1][1],
                            cumulative_text)
                        levels = Level.objects.values_list('id', flat=True)
                        indicator = Indicator(
                            name=indicator_name + indicator_suffix,
                            is_cumulative=is_cumulative,
                            target_frequency=freq[0],
                            unit_of_measure='This is a UOM',
                            baseline=0,
                            unit_of_measure_type=uom_type[0],
                            direction_of_change=direction,
                            program=program,
                            level=Level.objects.get(id=levels[seq %
                                                              len(levels)]))
                        indicator.save()
                        indicator_ids.append(indicator.id)

                        seq += 1
                        if null_level == self.NULL_LEVELS['TARGETS']:
                            continue
                        self.make_targets(program, indicator)
                        if null_level == self.NULL_LEVELS['RESULTS']:
                            continue
                        periodic_targets = PeriodicTarget.objects.filter(
                            indicator__id=indicator.id)

                        # Different combinations of UOM type, direction of change and cummulativeness require
                        # different inputs.
                        if uom_type[0] == Indicator.NUMBER:
                            if direction == Indicator.DIRECTION_OF_CHANGE_POSITIVE:
                                if is_cumulative:
                                    target_start = 100
                                    target_increment = target_start
                                    achieved_start = 90
                                    achieved_increment = achieved_start
                                else:
                                    target_start = 100
                                    target_increment = target_start
                                    achieved_start = 90
                                    achieved_increment = achieved_start
                            else:
                                if is_cumulative:
                                    target_start = 500
                                    target_increment = -int(
                                        math.floor(
                                            (target_start /
                                             len(periodic_targets)) / 10) * 10)
                                    achieved_start = 400
                                    achieved_increment = -(target_increment -
                                                           2)
                                else:
                                    target_start = 500
                                    target_increment = -int(
                                        math.floor(
                                            (target_start /
                                             len(periodic_targets)) / 10) * 10)
                                    achieved_start = 400
                                    achieved_increment = -(target_increment -
                                                           2)
                        else:
                            if direction == Indicator.DIRECTION_OF_CHANGE_POSITIVE:
                                # Don't need to check cumulative because we don't really handle it
                                target_start = 5
                                target_increment = 5
                                achieved_start = 4
                                achieved_increment = 5
                            else:
                                # Don't need to check cumulative because we don't really handle it
                                target_start = 90
                                target_increment = max(
                                    -math.floor(
                                        target_start / len(periodic_targets)),
                                    -2)
                                achieved_start = 95
                                achieved_increment = target_increment + 1

                        lop_target = 0
                        day_offset = timedelta(days=2)
                        for i, pt in enumerate(periodic_targets):
                            # Create the target amount (the PeriodicTarget object has already been created)
                            pt.target = target_start + target_increment * i
                            pt.save()

                            if is_cumulative:
                                lop_target = pt.target
                            else:
                                lop_target += pt.target

                            # Users shouldn't put in results with a date in the future, so neither should we.
                            if pt.start_date and date.today(
                            ) < pt.start_date + day_offset:
                                continue

                            # Now create the Results and their related Records
                            if pt.start_date:
                                date_collected = pt.start_date + day_offset
                            else:
                                date_collected = date.today()
                            cd = CollectedData(periodic_target=pt,
                                               indicator=indicator,
                                               program=program,
                                               achieved=achieved_start +
                                               achieved_increment * i,
                                               date_collected=date_collected)
                            cd.save()

                            if null_level == self.NULL_LEVELS['EVIDENCE']:
                                continue
                            document = Documentation.objects.create(
                                program=program,
                                name='Doc for CDid {}'.format(cd.id),
                                url='http://my/doc/here/')
                            cd.evidence = document
                            cd.save()

                        indicator.lop_target = lop_target
                        indicator.save()

        return indicator_ids