def insert_new_level(request):
    level_data = copy.copy(request.data)
    program = Program.objects.get(id=request.data['program'])

    role = request.user.tola_user.program_role(program.id)
    if request.user.is_anonymous or role != 'high':
        return HttpResponseRedirect('/')

    # Update new Level data in preparation for saving
    if request.data['parent'] == "root":
        parent = None
    else:
        parent = Level.objects.get(id=request.data['parent'])
    level_data['parent'] = parent
    level_data['program'] = program
    if 'ontology' in request.data:
        del level_data['ontology']
    del level_data['level_depth']

    # First update the customsort values of all Levels that getting pushed down by the new Level.
    # No need to do it if the top tier level is being saved
    if request.data['parent'] != "root":
        levels_to_shift = Level.objects\
            .filter(program=program, parent_id=parent.id, customsort__gte=request.data['customsort'])\
            .order_by('-customsort')
        for s_level in levels_to_shift:
            s_level.customsort += 1
            s_level.save()

    new_level = Level(**level_data)

    try:
        new_level.full_clean()
    except ValidationError as e:
        return Response(e.message_dict, status=400)

    # Now the new level can be saved
    new_level.save()

    # Return all Levels for the program. There shouldn't be so much that it slows things down much.
    # Also return the newly created Level.
    all_data = LevelSerializer(Level.objects.filter(program=program),
                               many=True).data
    return Response({
        'all_data': all_data,
        'new_level': LevelSerializer(new_level).data
    })
Example #2
0
    def create_levels(program_id, level_data):
        fixture_data = deepcopy(level_data)
        tier_labels = LevelTier.get_templates()['mc_standard']['tiers']
        for i, tier in enumerate(tier_labels):
            t = LevelTier(name=tier, tier_depth=i+1, program_id=program_id)
            t.save()

        level_map = {}
        for level_fix in fixture_data:
            parent = None
            if 'parent_id' in level_fix['fields']:
                parent = level_map[level_fix['fields'].pop('parent_id')]

            level = Level(**level_fix['fields'])
            level.parent = parent
            level.program = Program.objects.get(id=program_id)
            level.save()
            level_map[level_fix['pk']] = level
Example #3
0
    def __init__(self, *args, **kwargs):
        indicator = kwargs.get('instance', None)
        self.request = kwargs.pop('request')
        if indicator and not indicator.unit_of_measure_type:
            kwargs['initial'][
                'unit_of_measure_type'] = Indicator.UNIT_OF_MEASURE_TYPES[0][0]
        if indicator and indicator.lop_target:
            lop_stripped = str(indicator.lop_target)
            lop_stripped = lop_stripped.rstrip('0').rstrip(
                '.') if '.' in lop_stripped else lop_stripped
            kwargs['initial']['lop_target'] = lop_stripped

        self.programval = kwargs.pop('program')
        self.prefilled_level = kwargs.pop(
            'level') if 'level' in kwargs else False

        super(IndicatorForm, self).__init__(*args, **kwargs)

        # program_display here is to display the program without interfering in the logic that
        # assigns a program to an indicator (and doesn't update it) - but it looks like other fields
        self.fields['program_display'] = forms.ChoiceField(
            choices=[
                ('', self.programval.name),
            ],
            required=False,
        )
        self.fields['program_display'].disabled = True
        self.fields['program_display'].label = _('Program')

        # level is here the new "result level" (RF) level option (FK to model Level)
        # Translators: This is a form field label that allows users to select which Level object to associate with the Result that's being entered into the form
        self.fields['level'].label = _('Result level')
        self.fields['level'].label_from_instance = lambda obj: obj.display_name
        # in cases where the user was sent here via CREATE from the RF BUILDER screen:
        if self.prefilled_level:
            # prefill level with only the level they clicked "add indicator" from:
            self.fields['level'].queryset = Level.objects.filter(
                pk=self.prefilled_level)
            self.fields['level'].initial = self.prefilled_level
            # do not allow the user to update (it is being "added to" that level)
            self.fields['level'].disabled = True
        else:
            # populate with all levels for the indicator's program:
            # self.fields['level'].queryset = Level.objects.filter(program_id=self.programval)
            self.fields['level'].choices = [('', '------')] + \
                                           [(l.id, l.display_name) for l in Level.sort_by_ontology(Level.objects.filter(program_id=self.programval))]

        if self.programval.results_framework and not self.programval.manual_numbering:
            # in this (the default) case, the number field is removed (values not updated):
            self.fields.pop('number')
        elif self.programval.results_framework:
            # in this case the number field gets this special help text (added as a popover):
            self.fields['number'].label = _('Display number')
            # Translators: a "number" in this context is a kind of label.  This is help text to explain why a user is seeing customized numbers instead of auto-generated ones that can derived from the indicator's place in the hierarchy
            self.fields['number'].help_text = _(
                "This number is displayed in place of the indicator number automatically generated through the results framework.  An admin can turn on auto-numbering in program settings"
            )
        if self.programval.results_framework:
            # no need to update the old_level field if they are using the results framework:
            self.fields.pop('old_level')
            self.fields['level'].required = True
        else:
            # pre-migration to RF, all fields remain unchanged in this regard (still required):
            self.fields['old_level'].required = True
            # Translators:  Indicator objects are assigned to Levels, which are in a hierarchy.  We recently changed how we organize Levels. This is a field label for the indicator-associated Level in the old level system
            self.fields['old_level'].label = _('Old indicator level')
            # Translators:  We recently changed how we organize Levels. The new system is called the "results framework". This is help text for users to let them know that they can use the new system now.
            self.fields['old_level'].help_text = _(
                "Indicators are currently grouped by an older version of indicator levels. To group indicators according to the results framework, an admin will need to adjust program settings."
            )

        if not self.request.has_write_access:
            for name, field in self.fields.items():
                field.disabled = True
        countries = getCountry(self.request.user)
        self.fields['disaggregation'].queryset = DisaggregationType.objects\
            .filter(country__in=countries, standard=False)
        if self.programval._using_results_framework == Program.NOT_MIGRATED and Objective.objects.filter(
                program_id=self.programval.id).exists():
            self.fields['objectives'].queryset = Objective.objects.filter(
                program__id__in=[self.programval.id])
        else:
            self.fields.pop('objectives')
        self.fields[
            'strategic_objectives'].queryset = StrategicObjective.objects.filter(
                country__in=countries)
        self.fields['approved_by'].queryset = TolaUser.objects.filter(
            country__in=countries).distinct()
        self.fields[
            'approval_submitted_by'].queryset = TolaUser.objects.filter(
                country__in=countries).distinct()
        self.fields['name'].label = _('Indicator')
        self.fields['name'].required = True
        self.fields['name'].widget = forms.Textarea(attrs={'rows': 3})
        self.fields['unit_of_measure'].required = True
        self.fields['target_frequency'].required = True
        # self.fields['is_cumulative'].widget = forms.RadioSelect()
        if self.instance.target_frequency and self.instance.target_frequency != Indicator.LOP:
            self.fields['target_frequency'].widget.attrs['readonly'] = True