示例#1
0
class IndicatorDelete(DeleteView):
    model = Indicator
    form_class = IndicatorForm

    @method_decorator(login_required)
    @method_decorator(group_excluded('ViewOnly', url='workflow/permission'))
    @method_decorator(indicator_pk_adapter(has_indicator_write_access))
    def dispatch(self, request, *args, **kwargs):
        return super(IndicatorDelete, self).dispatch(request, *args, **kwargs)

    def form_invalid(self, form):
        messages.error(self.request, 'Invalid Form', fail_silently=False)
        return self.render_to_response(self.get_context_data(form=form))

    def form_valid(self, form):
        form.save()
        messages.success(self.request, _('Success, Indicator Deleted!'))
        return self.render_to_response(self.get_context_data(form=form))

    def delete(self, request, *args, **kwargs):
        if request.is_ajax():
            indicator = self.get_object()
            if not request.POST.get('rationale'):
                # if an indicator has results and no rationale is provided, fail:
                if indicator.result_set.all().count() > 0:
                    return JsonResponse(
                        {
                            "status": "failed",
                            "msg": _("Reason for change is required.")
                        },
                        status=400)
                # otherwise the rationale is this default:
                else:
                    rationale = _(
                        "Reason for change is not required when deleting an indicator with no linked results."
                    )
            else:
                rationale = request.POST.get('rationale')
            indicator_values = indicator.logged_fields
            program_page_url = indicator.program.program_page_url
            indicator.delete()
            ProgramAuditLog.log_indicator_deleted(self.request.user, indicator,
                                                  indicator_values, rationale)
            success_message = _("The indicator was successfully deleted.")
            response_context = {'status': 'success'}
            if request.POST.get('redirect'):
                response_context['redirect_url'] = program_page_url
                # message tagged "pnotify" to display a success popup after redirect
                messages.success(request,
                                 success_message,
                                 extra_tags="pnotify pnotify-success")
            else:
                response_context['msg'] = success_message
            return JsonResponse(response_context)
        else:
            return super(IndicatorDelete, self).delete(request, *args,
                                                       **kwargs)

    def get_success_url(self):
        return self.object.program.program_page_url
示例#2
0
class DashboardThemeCreate(CreateView):
    model = DashboardTheme
    template_name = 'configurabledashboard/themes/admin/form.html'

    # add the request to the kwargs
    def get_form_kwargs(self):
        kwargs = super(DashboardThemeCreate, self).get_form_kwargs()
        kwargs['request'] = self.request
        return kwargs

    @method_decorator(group_excluded('ViewOnly', url='workflow/permission'))
    def dispatch(self, request, *args, **kwargs):
        try:
            self.guidance = FormGuidance.objects.get(form="DashboardTheme")
        except FormGuidance.DoesNotExist:
            self.guidance = None
        return super(DashboardThemeCreate,
                     self).dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super(DashboardThemeCreate, self).get_context_data(**kwargs)

        return context

    def form_invalid(self, form):
        messages.error(self.request, 'Invalid Form', fail_silently=False)
        return self.render_to_response(self.get_context_data(form=form))

    def form_valid(self, form):
        form.save()
        messages.success(self.request, 'Success, Theme Created!')
        return self.render_to_response(self.get_context_data(form=form))

    form_class = DashboardThemeCreateForm
示例#3
0
class ResultDelete(DeleteView):
    """TODO: This should handle GET differently - currently returns a nonexistent template"""
    model = Result

    @method_decorator(login_required)
    @method_decorator(group_excluded('ViewOnly', url='workflow/permission'))
    @method_decorator(result_pk_adapter(has_result_write_access))
    def dispatch(self, request, *args, **kwargs):
        return super(ResultDelete, self).dispatch(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        if request.is_ajax():
            if not request.POST.get('rationale'):
                return JsonResponse(
                    {
                        "status": "failed",
                        "msg": _("Reason for change is required")
                    },
                    status=401)

            result = self.get_object()
            result_values = result.logged_fields
            result.delete()
            ProgramAuditLog.log_result_deleted(self.request.user,
                                               result.indicator, result_values,
                                               self.request.POST['rationale'])

            return JsonResponse({"status": "success", "msg": "Result Deleted"})
        else:
            return super(ResultDelete, self).delete(request, *args, **kwargs)

    def get_success_url(self):
        return self.object.program.program_page_url
示例#4
0
class TrainingUpdate(UpdateView):
    """
    Training Form
    """
    model = TrainingAttendance

    @method_decorator(group_excluded('ViewOnly', url='workflow/permission'))
    def dispatch(self, request, *args, **kwargs):
        try:
            self.guidance = FormGuidance.objects.get(form="Training")
        except FormGuidance.DoesNotExist:
            self.guidance = None
        return super(TrainingUpdate, self).dispatch(request, *args, **kwargs)

    # add the request to the kwargs
    def get_form_kwargs(self):
        kwargs = super(TrainingUpdate, self).get_form_kwargs()
        kwargs['request'] = self.request
        return kwargs

    def form_invalid(self, form):
        messages.error(self.request, 'Invalid Form', fail_silently=False)
        return self.render_to_response(self.get_context_data(form=form))

    def form_valid(self, form):
        form.save()
        messages.success(self.request, 'Success, Training Updated!')

        return self.render_to_response(self.get_context_data(form=form))

    form_class = TrainingAttendanceForm
示例#5
0
class BeneficiaryDelete(DeleteView):
    """
    Beneficiary Delete
    """
    model = Beneficiary
    success_url = reverse_lazy('beneficiary_list')

    @method_decorator(group_excluded('ViewOnly', url='workflow/permission'))
    def dispatch(self, request, *args, **kwargs):
        return super(BeneficiaryDelete, self).dispatch(request, *args,
                                                       **kwargs)

    def form_invalid(self, form):

        messages.error(self.request, 'Invalid Form', fail_silently=False)

        return self.render_to_response(self.get_context_data(form=form))

    def form_valid(self, form):

        form.save()

        messages.success(self.request, 'Success, Beneficiary Deleted!')
        return self.render_to_response(self.get_context_data(form=form))

    form_class = BeneficiaryForm
示例#6
0
class CustomDashboardCreate(CreateView):
    #   :param request:
    #   :param id:
    #   """
    model = CustomDashboard
    template_name = 'configurabledashboard/dashboard/form.html'

    @method_decorator(group_excluded('ViewOnly', url='workflow/permission'))
    def dispatch(self, request, *args, **kwargs):
        try:
            self.guidance = FormGuidance.objects.get(form="CustomDashboard")
        except FormGuidance.DoesNotExist:
            self.guidance = None
        return super(CustomDashboardCreate,
                     self).dispatch(request, *args, **kwargs)

    # add the request to the kwargs
    def get_form_kwargs(self):
        kwargs = super(CustomDashboardCreate, self).get_form_kwargs()
        kwargs['request'] = self.request
        return kwargs

    def get_initial(self):
        initial = {}
        return initial

    def get_context_data(self, **kwargs):
        context = super(CustomDashboardCreate, self).get_context_data(**kwargs)
        pk = self.kwargs['pk']
        context.update({'pk': pk})
        return context

    def form_invalid(self, form):

        messages.error(self.request, 'Invalid Form', fail_silently=False)

        return self.render_to_response(self.get_context_data(form=form))

    def form_valid(self, form):
        if form.is_valid():
            data = form.save(commit=False)
            form_theme = data.theme
            getSelectedTheme = DashboardTheme.objects.all().filter(
                id=form_theme.id)
            parsedLayout = json.loads(getSelectedTheme[0].layout_dictionary,
                                      object_pairs_hook=OrderedDict)
            new_map = {}
            for key in parsedLayout:
                new_map[key] = "NONE"
            data.component_map = json.dumps(new_map)
            data.save()

        #save formset from context
        context = self.get_context_data()

        messages.success(self.request, 'Success, Dashboard Created!')
        redirect_url = '/configurabledashboard/' + str(self.kwargs['pk'])
        return HttpResponseRedirect(redirect_url)

    form_class = CustomDashboardCreateForm
示例#7
0
class SiteProfileUpdate(UpdateView):
    """
    SiteProfile Form Update an existing site profile
    """
    model = SiteProfile

    @method_decorator(group_excluded('ViewOnly', url='workflow/permission'))
    def dispatch(self, request, *args, **kwargs):
        self.guidance = None
        return super(SiteProfileUpdate, self).dispatch(request, *args,
                                                       **kwargs)

    # add the request to the kwargs
    def get_form_kwargs(self):
        kwargs = super(SiteProfileUpdate, self).get_form_kwargs()
        kwargs['request'] = self.request
        return kwargs

    def get_context_data(self, **kwargs):
        context = super(SiteProfileUpdate, self).get_context_data(**kwargs)
        getProjects = []
        context.update({'getProjects': getProjects})
        return context

    def form_invalid(self, form):
        messages.error(self.request, 'Invalid Form', fail_silently=False)
        return self.render_to_response(self.get_context_data(form=form))

    def form_valid(self, form):
        form.save()
        messages.success(self.request, 'Success, SiteProfile Updated!')

        return self.render_to_response(self.get_context_data(form=form))

    form_class = SiteProfileForm
示例#8
0
class CustomDashboardCreate(CreateView):
    #   :param request:
    #   :param id:
    #   """
    model = CustomDashboard
    template_name = 'configurabledashboard/dashboard/form.html'

    try:
        guidance = FormGuidance.objects.get(form="CustomDashboard")
    except FormGuidance.DoesNotExist:
        guidance = None

    @method_decorator(group_excluded('ViewOnly', url='workflow/permission'))
    def dispatch(self, request, *args, **kwargs):
        return super(CustomDashboardCreate,
                     self).dispatch(request, *args, **kwargs)

    # add the request to the kwargs
    def get_form_kwargs(self):
        kwargs = super(CustomDashboardCreate, self).get_form_kwargs()
        kwargs['request'] = self.request
        return kwargs

    def get_initial(self):
        initial = {}
        return initial

    def get_context_data(self, **kwargs):
        context = super(CustomDashboardCreate, self).get_context_data(**kwargs)
        pk = self.kwargs['pk']
        context.update({'pk': pk})
        return context

    def form_invalid(self, form):

        messages.error(self.request, 'Invalid Form', fail_silently=False)

        return self.render_to_response(self.get_context_data(form=form))

    def form_valid(self, form):
        print form
        form.save()

        #save formset from context
        context = self.get_context_data()

        messages.success(self.request, 'Success, Dashboard Created!')

        latest = CustomDashboard.objects.latest('id')
        getCustomDashboard = CustomDashboard.objects.get(id=latest.id)
        dashboard_id = getCustomDashboard.id
        redirect_url = '/configurabledashboard/update/' + str(dashboard_id)
        return HttpResponseRedirect(redirect_url)

    form_class = CustomDashboardCreateForm
示例#9
0
class DashboardComponentCreate(CreateView):
    model = DashboardComponent
    template_name = 'configurabledashboard/components/admin/form.html'

    # add the request to the kwargs
    def get_form_kwargs(self):
        kwargs = super(DashboardComponentCreate, self).get_form_kwargs()
        kwargs['request'] = self.request
        id = self.kwargs['id']
        return kwargs

    @method_decorator(group_excluded('ViewOnly', url='workflow/permission'))
    def dispatch(self, request, *args, **kwargs):
        try:
            guidance = FormGuidance.objects.get(form="DashboardComponent")
        except FormGuidance.DoesNotExist:
            guidance = None
        return super(DashboardComponentCreate,
                     self).dispatch(request, *args, **kwargs)

    def get_initial(self):
        initial = {
            'getCustomDashboard':
            CustomDashboard.objects.get(id=self.kwargs['id']),
            'getComponentDataSources': ComponentDataSource.objects.all(),
        }

    def get_context_data(self, **kwargs):
        context = super(DashboardComponentCreate,
                        self).get_context_data(**kwargs)
        try:
            getCustomDashboard = CustomDashboard.objects.get(
                id=self.kwargs['id'])
        except CustomDashboard.DoesNotExist:
            getCustomDashboard = None
        context.update({'getCustomDashboard': getCustomDashboard})

        return context

    def form_invalid(self, form):
        messages.error(self.request, 'Invalid Form', fail_silently=False)
        return self.render_to_response(self.get_context_data(form=form))

    def form_valid(self, form):
        form.save()
        context = self.get_context_data()
        messages.success(self.request, 'Success, Component Created!')
        latestComponent = DashboardComponent.objects.latest('id')
        getCustomDashboard = CustomDashboard.objects.get(id=self.kwargs['id'])
        getCustomDashboard.components.add(latestComponent)
        return self.render_to_response(self.get_context_data(form=form))

    form_class = DashboardComponentCreateForm
示例#10
0
class SiteProfileCreate(CreateView):
    """
    Using SiteProfile Form, create a new site profile
    """
    model = SiteProfile

    @method_decorator(group_excluded('ViewOnly', url='workflow/permission'))
    def dispatch(self, request, *args, **kwargs):
        self.guidance = None
        return super(SiteProfileCreate, self).dispatch(request, *args,
                                                       **kwargs)

    def post(self, request, *args, **kwargs):
        # permission check that includes checking the user is associated with the sites Country
        verify_program_access_level_of_any_program(
            request, 'high', country_id=request.POST['country'])

        return super(SiteProfileCreate, self).post(request, *args, **kwargs)

    # add the request to the kwargs
    def get_form_kwargs(self):
        kwargs = super(SiteProfileCreate, self).get_form_kwargs()
        kwargs['request'] = self.request
        return kwargs

    def get_initial(self):
        countries = getCountry(self.request.user)
        default_country = None
        if countries:
            default_country = countries[0]
        initial = {
            'approved_by': self.request.user,
            'filled_by': self.request.user,
            'country': default_country
        }

        return initial

    def form_invalid(self, form):

        messages.error(self.request, 'Invalid Form', fail_silently=False)

        return self.render_to_response(self.get_context_data(form=form))

    def form_valid(self, form):
        form.save()
        messages.success(self.request, 'Success, Site Profile Created!')
        latest = SiteProfile.objects.latest('id')
        redirect_url = '/workflow/siteprofile_update/' + str(latest.id)
        return HttpResponseRedirect(redirect_url)

    form_class = SiteProfileForm
示例#11
0
class BeneficiaryCreate(CreateView):
    """
    Beneficiary Form
    """
    model = Beneficiary

    @method_decorator(group_excluded('ViewOnly', url='workflow/permission'))
    def dispatch(self, request, *args, **kwargs):
        try:
            self.guidance = FormGuidance.objects.get(form="Beneficiary")
        except FormGuidance.DoesNotExist:
            self.guidance = None
        return super(BeneficiaryCreate, self).dispatch(request, *args,
                                                       **kwargs)

    def get_initial(self):
        initial = {
            'training': self.kwargs['id'],
        }

        return initial

    # add the request to the kwargs
    def get_form_kwargs(self):
        kwargs = super(BeneficiaryCreate, self).get_form_kwargs()
        kwargs['request'] = self.request
        return kwargs

    def form_invalid(self, form):

        messages.error(self.request, 'Invalid Form', fail_silently=False)

        return self.render_to_response(self.get_context_data(form=form))

    def form_valid(self, form):
        form.save()
        messages.success(self.request, 'Success, Beneficiary Created!')
        latest = Beneficiary.objects.latest('id')
        redirect_url = '/formlibrary/beneficiary_update/' + str(latest.id)
        return HttpResponseRedirect(redirect_url)

    form_class = BeneficiaryForm
示例#12
0
class CustomDashboardUpdate(UpdateView):

    model = CustomDashboard
    form_class = CustomDashboardForm

    @method_decorator(group_excluded('ViewOnly', url='workflow/permission'))
    def dispatch(self, request, *args, **kwargs):
        try:
            guidance = FormGuidance.objects.get(form="CustomDashboard")
        except FormGuidance.DoesNotExist:
            guidance = None

        return super(CustomDashboardUpdate,
                     self).dispatch(request, *args, **kwargs)

    def get_initial(self):
        getCustomDashboard = CustomDashboard.objects.get(id=self.kwargs['pk'])
        getDashboardComponents = DashboardComponent.objects.all().filter(
            componentset=getCustomDashboard)
        getAllComponentDataSources = ComponentDataSource.objects.all()
        initial = {
            'getCustomDashboard': getCustomDashboard,
            'getDashboardComponents': getDashboardComponents,
            'getAllComponentDataSources': getAllComponentDataSources,
        }

        return initial

    def get_form(self, form_class):
        check_form_type = self.request.get_full_path()
        if check_form_type.startswith('/configurabledashboard/edit'):
            form = CustomDashboardModalForm
        else:
            form = CustomDashboardForm

        return form(**self.get_form_kwargs())

    def get_context_data(self, **kwargs):
        context = super(CustomDashboardUpdate, self).get_context_data(**kwargs)
        pk = self.kwargs['pk']
        context.update({'pk': pk})

        check_path = self.request.get_full_path()
        if check_path.startswith('/confirgureabledashboard/map'):
            location = self.kwargs['location']
            component_type = self.kwargs['type']
        # TODO: If applicable, work through flow for remapping
        # else if check_form_type.startswith('/confirgureabledashboard/remap'):
        #     location = self.kwargs['location']
        #     component_type = self.kwargs['type']
        else:
            location = None
            component_type = None
        context.update({'location': location})
        context.update({'component_type': component_type})

        try:
            getCustomDashboard = CustomDashboard.objects.get(
                id=self.kwargs['pk'])
        except CustomDashboard.DoesNotExist:
            getCustomDashboard = None
        context.update({'getCustomDashboard': getCustomDashboard})

        try:
            selected_theme = getCustomDashboard.theme
            getDashboardTheme = DashboardTheme.objects.all().filter(
                id=selected_theme.id)
        except DashboardTheme.DoesNotExist:
            getDashboardTheme = None
        context.update({'getDashboardTheme': getDashboardTheme})

        # This theme layout helps to map the components to their position on the page
        # Dashboard layout should be pairs of the # position in the template (1,2,3...) and
        # the component type that needs to be slotted into that position

        if getDashboardTheme:
            getDashboardTheme[0].layout_dictionary
            layout = getDashboardTheme[0].layout_dictionary
            getDashboardLayoutList = json.loads(layout,
                                                object_pairs_hook=OrderedDict)
        else:
            getDashboardLayoutList = None
        context.update({'getDashboardLayoutList': getDashboardLayoutList})

        try:
            getDashboardComponents = DashboardComponent.objects.all().filter(
                componentset=getCustomDashboard)
        except DashboardComponent.DoesNotExist:
            getDashboardComponents = None
        context.update({'getDashboardComponents': getDashboardComponents})

        try:
            getComponentOrder = json.loads(getCustomDashboard.component_map,
                                           object_pairs_hook=OrderedDict)
        except:
            getComponentOrder = None
        context.update({'getComponentOrder': getComponentOrder})

        try:
            getAllComponentMaps = []
            for component in getDashboardComponents:
                if component.data_map:
                    getAllComponentMaps[component] = json.loads(
                        component.data_map)
        except not getDashboardComponents:
            getAllComponentMaps = None
        context.update({'getAllComponentMaps': getAllComponentMaps})

        try:
            getAllComponentDataSources = ComponentDataSource.objects.all()
        except ComponentDataSource.DoesNotExist:
            getAllComponentDataSources = None
        context.update(
            {'getAllComponentDataSources': getAllComponentDataSources})

        # try:
        #     getAllDataFilters = {}
        #     for data_source in getAllComponentDataSources:
        #         data_source_filters = import_data_filter_options(data_source.data_source, data_source.data_filter_key, data_source.authorization_token)
        #         getAllDataFilters[data_source.id] = data_source_filters
        # except not getAllComponentDataSources:
        #     getAllDataFilters = None
        # context.update({'getAllDataFilters': getAllDataFilters})

        mapped_location = self.request.GET.get('location')
        component_type = self.request.GET.get('type')
        if mapped_location and component_type:
            context.update({'mapped_location': mapped_location})
            context.update({'component_type': component_type})

        return context

    # add the request to the kwargs
    def get_form_kwargs(self):
        kwargs = super(CustomDashboardUpdate, self).get_form_kwargs()
        kwargs['request'] = self.request
        return kwargs

    def form_invalid(self, form):
        messages.error(self.request, self, fail_silently=False)
        return self.render_to_response(self.get_context_data(form=form))

    def form_valid(self, form):
        check_form_type = self.request.get_full_path()
        #TODO: Once refactoring is done, revisit whether checking form type still needed
        # if check_form_type.startswith('/confirgureabledashboard/map'):
        #     getCustomDashboard.component_map = form.cleaned_data['component_map']
        #     getCustomDashboard.save()
        # for position in getCustomDashboard.component_map:
        #     mapped_position = form.component_map.0
        #     if position.0 == mapped_position:
        #         position.1 == form.component_map.1
        #         mapped = true
        # if mapped != true:
        #     getCustomDashboard.component_map.append(form.component_map)
        # else:
        form.save()
        messages.success(self.request,
                         'Success, CustomDashboard Output Updated!')

        return self.render_to_response(self.get_context_data(form=form))
示例#13
0
class ResultUpdate(ResultFormMixin, UpdateView):
    """Update Result view called by result_update as modal"""
    model = Result
    form_class = ResultForm

    @method_decorator(login_required)
    @method_decorator(group_excluded('ViewOnly', url='workflow/permission'))
    @method_decorator(result_pk_adapter(has_result_write_access))
    def dispatch(self, request, *args, **kwargs):
        self.result = get_object_or_404(Result, pk=self.kwargs.get('pk'))
        self.indicator = self.result.indicator
        return super(ResultUpdate, self).dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        custom_disaggregation_values = DisaggregationValue.objects.filter(
            result=self.result).exclude(
                disaggregation_label__disaggregation_type__standard=True)

        standard_disaggregation_values = DisaggregationValue.objects.filter(
            result=self.result).filter(
                disaggregation_label__disaggregation_type__standard=True)
        standard_disaggregation_labels = DisaggregationLabel.get_standard_labels(
        )
        custom_disaggregation_labels = DisaggregationLabel.objects.filter(
            disaggregation_type__indicator=self.indicator.id)
        context = super(ResultUpdate, self).get_context_data(**kwargs)
        context['indicator'] = self.indicator

        context['readonly'] = not self.request.has_write_access
        context['custom_disaggregation_labels'] = custom_disaggregation_labels
        context['custom_disaggregation_values'] = custom_disaggregation_values
        context[
            'standard_disaggregation_labels'] = standard_disaggregation_labels
        context[
            'standard_disaggregation_values'] = standard_disaggregation_values
        context['title_str'] = u'{}: {}'.format(
            str(self.indicator.form_title_level), str(self.indicator.name))
        return context

    def get_form_kwargs(self):
        kwargs = super(ResultUpdate, self).get_form_kwargs()
        kwargs['user'] = self.request.user
        kwargs['indicator'] = self.indicator
        kwargs['program'] = self.indicator.program
        kwargs['request'] = self.request
        return kwargs

    def form_valid(self, form):
        old_result = Result.objects.get(id=self.kwargs['pk'])

        getDisaggregationLabel = DisaggregationLabel.objects.filter(
            Q(disaggregation_type__indicator__id=old_result.indicator_id)
            | Q(disaggregation_type__standard=True)).distinct()

        # save the form then update manytomany relationships
        old_values = old_result.logged_fields
        new_result = form.save(
        )  # internally this clears disaggregation_value m2m relationships!

        # like the create view, create disaggregation values as all or nothing

        disaggregation_label_ids = set(
            [str(dl.id) for dl in getDisaggregationLabel])
        process_disaggregation = False
        for k, v in self.request.POST.items():
            if k in disaggregation_label_ids and v:
                process_disaggregation = True
                break

        if process_disaggregation:
            for label in getDisaggregationLabel:
                form_id_for_label = str(label.id)
                form_disagg_value = self.request.POST.get(
                    form_id_for_label, '')
                new_result.disaggregation_value.create(
                    disaggregation_label=label, value=form_disagg_value)

        # Result.achieved comes back different from the DB than from the ResultForm
        new_result.refresh_from_db()
        ProgramAuditLog.log_result_updated(self.request.user,
                                           new_result.indicator, old_values,
                                           new_result.logged_fields,
                                           form.cleaned_data.get('rationale'))

        if self.request.is_ajax():
            data = serializers.serialize('json', [self.object])
            return HttpResponse(data)

        messages.success(self.request, _('Success, Data Updated!'))
        redirect_url = new_result.program.program_page_url

        return HttpResponseRedirect(redirect_url)
示例#14
0
class ResultCreate(ResultFormMixin, CreateView):
    """Create new Result called by result_add as modal"""
    model = Result
    form_class = ResultForm

    @method_decorator(login_required)
    @method_decorator(group_excluded('ViewOnly', url='workflow/permission'))
    @method_decorator(indicator_adapter(has_result_write_access))
    def dispatch(self, request, *args, **kwargs):
        if not request.has_write_access:
            raise PermissionDenied

        self.indicator = get_object_or_404(Indicator,
                                           pk=self.kwargs['indicator'])
        return super(ResultCreate, self).dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        custom_disaggregation_labels = DisaggregationLabel.objects.filter(
            disaggregation_type__indicator=self.indicator.id)
        standard_disaggregation_labels = DisaggregationLabel.get_standard_labels(
        )

        context = super(ResultCreate, self).get_context_data(**kwargs)
        context['indicator'] = self.indicator
        context['custom_disaggregation_labels'] = custom_disaggregation_labels
        context[
            'standard_disaggregation_labels'] = standard_disaggregation_labels
        context['title_str'] = u'{}: {}'.format(
            str(self.indicator.form_title_level), str(self.indicator.name))
        return context

    def get_form_kwargs(self):
        kwargs = super(ResultCreate, self).get_form_kwargs()
        kwargs['user'] = self.request.user
        kwargs['indicator'] = self.indicator
        kwargs['program'] = self.indicator.program
        kwargs['request'] = self.request
        return kwargs

    def form_valid(self, form):
        indicator = self.request.POST['indicator']
        disaggregation_labels = DisaggregationLabel.objects.filter(
            Q(disaggregation_type__indicator__id=indicator)
            | Q(disaggregation_type__standard=True))

        new = form.save()

        # The following code appears to be accomplishing the following
        # The for submitted contains key/vals for all disaggregation_labels on creation
        # if 1 or more values are present, create values in the DB for all key/vals
        # otherwise leave the disaggregation_value associates completely empty
        # In other words, save key/vals as all or nothing

        disaggregation_label_ids = set(
            [str(dl.id) for dl in disaggregation_labels])
        process_disaggregation = False
        for k, v in self.request.POST.items():
            if k in disaggregation_label_ids and v:
                process_disaggregation = True
                break

        if process_disaggregation is True:
            for label in disaggregation_labels:
                form_id_for_label = str(label.id)
                form_disagg_value = self.request.POST.get(
                    form_id_for_label, '')
                new.disaggregation_value.create(disaggregation_label=label,
                                                value=form_disagg_value)

        ProgramAuditLog.log_result_created(self.request.user, new.indicator,
                                           new)

        if self.request.is_ajax():
            data = {
                'pk': new.pk,
                'url': reverse('result_update', kwargs={'pk': new.pk})
            }
            return JsonResponse(data)

        messages.success(self.request, _('Success, Data Created!'))
        redirect_url = new.indicator.program.program_page_url
        return HttpResponseRedirect(redirect_url)
示例#15
0
class IndicatorUpdate(IndicatorFormMixin, UpdateView):
    """
    Update and Edit Indicators.
    url: indicator_update/<pk>
    """
    @method_decorator(login_required)
    @method_decorator(group_excluded('ViewOnly', url='workflow/permission'))
    @method_decorator(indicator_pk_adapter(has_indicator_write_access))
    @transaction.atomic
    def dispatch(self, request, *args, **kwargs):
        if request.method == 'GET':
            # If target_frequency is set but not targets are saved then
            # unset target_frequency too.
            indicator = self.get_object()
            reset_indicator_target_frequency(indicator)

        self.set_form_guidance()

        return super(IndicatorUpdate, self).dispatch(request, *args, **kwargs)

    @property
    def _form_title_display_str(self):
        """
        The header of the form when updating - composed here instead of in the template
        such that it can also be used via AJAX
        """
        if self.object.results_framework and self.object.auto_number_indicators:
            if self.object.level_display_ontology:
                return u'{} {} {}{}'.format(
                    self.object.leveltier_name,
                    _('indicator'),
                    self.object.level_display_ontology,
                    self.object.level_order_display,
                )
            else:
                return _('Indicator setup')
        elif self.object.results_framework and self.object.number:
            return u'{} {}'.format(_('indicator'), self.object.number)
        elif self.object.results_framework:
            return _('Indicator setup')
        elif self.object.old_level:
            return u'{} {}'.format(
                str(ugettext(self.object.old_level)),
                str(_('indicator')),
            )
        else:
            return _('Indicator setup')

    @property
    def _form_subtitle_display_str(self):
        return truncatechars(self.object.name, 300)

    def get_context_data(self, **kwargs):
        context = super(IndicatorUpdate, self).get_context_data(**kwargs)
        indicator = self.object
        program = indicator.program

        context['program'] = program

        pts = PeriodicTarget.objects.filter(indicator=indicator) \
            .annotate(num_data=Count('result')).order_by('customsort', 'create_date', 'period')

        ptargets = []
        for pt in pts:
            ptargets.append({
                'id': pt.pk,
                'num_data': pt.num_data,
                'start_date': pt.start_date,
                'end_date': pt.end_date,
                'period': pt.
                period,  # period is deprecated, this should move to .period_name
                'period_name': pt.period_name,
                'target': pt.target
            })

        # if the modal is loaded (not submitted) and the indicator frequency is a periodic
        if self.request.method == 'GET' and indicator.target_frequency in Indicator.REGULAR_TARGET_FREQUENCIES:
            latest_pt_end_date = indicator.periodictargets.aggregate(
                lastpt=Max('end_date'))['lastpt']

            if latest_pt_end_date is None or latest_pt_end_date == 'None':
                latest_pt_end_date = program.reporting_period_start
            else:
                latest_pt_end_date += timedelta(days=1)

            target_frequency_num_periods = len([
                p for p in PeriodicTarget.generate_for_frequency(
                    indicator.target_frequency)(latest_pt_end_date,
                                                program.reporting_period_end)
            ])
            # target_frequency_num_periods = IPTT_ReportView._get_num_periods(
            #     latest_pt_end_date, program.reporting_period_end, indicator.target_frequency)

            num_existing_targets = pts.count()
            event_name = ''

            generated_targets = generate_periodic_targets(
                indicator.target_frequency, latest_pt_end_date,
                target_frequency_num_periods, event_name, num_existing_targets)

            # combine the list of existing periodic_targets with the newly generated placeholder for missing targets
            ptargets += generated_targets

        context['periodic_targets'] = ptargets

        # redirect user to certain tabs of the form given GET params
        if self.request.GET.get('targetsactive') == 'true':
            context['targetsactive'] = True

        context['readonly'] = not self.request.has_write_access

        context['title_str'] = self._form_title_display_str
        context['subtitle_str'] = self._form_subtitle_display_str

        return context

    def get_initial(self):
        target_frequency_num_periods = self.get_object(
        ).target_frequency_num_periods
        if not target_frequency_num_periods:
            target_frequency_num_periods = 1

        initial = {
            'target_frequency_num_periods': target_frequency_num_periods
        }
        return initial

    # add the request to the kwargs
    def get_form_kwargs(self):
        kwargs = super(IndicatorUpdate, self).get_form_kwargs()
        kwargs['request'] = self.request
        program = Program.rf_aware_objects.get(pk=self.object.program_id)
        kwargs['program'] = program
        return kwargs

    def form_valid(self, form, **kwargs):
        periodic_targets = self.request.POST.get('periodic_targets')
        old_indicator = Indicator.objects.get(pk=self.kwargs.get('pk'))
        existing_target_frequency = old_indicator.target_frequency
        new_target_frequency = form.cleaned_data.get('target_frequency')
        lop = form.cleaned_data.get('lop_target')
        rationale = form.cleaned_data.get('rationale')
        old_indicator_values = old_indicator.logged_fields
        prev_level = old_indicator.level  # previous value of "new" level (not to be confused with Indicator.old_level)

        # if existing_target_frequency != new_target_frequency
        # then either existing_target_frequency is None or LoP
        # It shouldn't be anything else as the user should have to delete all targets first

        # Disassociate existing records and delete old PeriodicTargets
        if existing_target_frequency != new_target_frequency:
            PeriodicTarget.objects.filter(indicator=old_indicator).delete()

        # Save completed PeriodicTargets to the DB)
        if new_target_frequency == Indicator.LOP:
            # assume only 1 PT at this point
            lop_pt, created = PeriodicTarget.objects.update_or_create(
                indicator=old_indicator,
                defaults={
                    'target': lop,
                    'period': PeriodicTarget.LOP_PERIOD,
                })

            if created:
                lop_pt.create_date = timezone.now()
                lop_pt.save()

                # Redirect results to new LoP target
                Result.objects.filter(indicator=old_indicator).update(
                    periodic_target=lop_pt)
        else:
            # now create/update periodic targets (will be empty u'[]' for LoP)
            pt_json = json.loads(periodic_targets)

            normalized_pt_json = self.normalize_periodic_target_client_json_dates(
                pt_json)

            self.validate_periodic_target_json_from_client(
                normalized_pt_json, old_indicator.program,
                new_target_frequency)

            generated_pt_ids = []
            for i, pt in enumerate(normalized_pt_json):
                defaults = {
                    'period': pt.get('period', ''),
                    'target': pt.get('target', 0),
                    'customsort': i,
                    'start_date': pt['start_date'],
                    'end_date': pt['end_date'],
                    'edit_date': timezone.now()
                }

                periodic_target, created = PeriodicTarget.objects \
                    .update_or_create(indicator=old_indicator, id=pt['id'], defaults=defaults)

                if created:
                    periodic_target.create_date = timezone.now()
                    periodic_target.save()
                    generated_pt_ids.append(periodic_target.id)

            # Reassign results to newly created PTs
            if generated_pt_ids:
                pts = PeriodicTarget.objects.filter(indicator=old_indicator,
                                                    pk__in=generated_pt_ids)
                for pt in pts:
                    Result.objects.filter(indicator=old_indicator,
                                          date_collected__range=[
                                              pt.start_date, pt.end_date
                                          ]).update(periodic_target=pt)

        # save the indicator form
        form.save()
        self.object.refresh_from_db()

        # Write to audit log if results attached or special case of RF level reassignment
        results_count = Result.objects.filter(indicator=self.object).count()
        if (results_count and results_count > 0
            ) or old_indicator.level_id != self.object.level_id:
            ProgramAuditLog.log_indicator_updated(self.request.user,
                                                  self.object,
                                                  old_indicator_values,
                                                  self.object.logged_fields,
                                                  rationale)

        # refresh the periodic targets form such that pkids of new PeriodicTargets are submitted in the future
        content = render_to_string(
            'indicators/indicatortargets.html', {
                'indicator':
                self.object,
                'periodic_targets':
                PeriodicTarget.objects.filter(indicator=self.object).annotate(
                    num_data=Count('result'))
            })

        return JsonResponse({
            'content':
            content,
            'title_str':
            self._form_title_display_str,
            'subtitle_str':
            self._form_subtitle_display_str,
            'save_success_msg':
            self._save_success_msg(
                self.object,
                created=False,
                level_changed=(self.object.level != prev_level)),
        })