示例#1
0
    def set_parameters(self, request):
        self.user = request.user
        self.registry_code = request.GET.get("registry_code")
        self.registry_model = get_object_or_404(Registry,
                                                code=self.registry_code)

        self.clinicians_have_patients = self.registry_model.has_feature(
            "clinicians_have_patients")
        self.form_progress = FormProgress(self.registry_model)
        self.supports_contexts = self.registry_model.has_feature("contexts")
        self.rdrf_context_manager = RDRFContextManager(self.registry_model)

        def getint(param):
            try:
                return int(request.POST.get(param) or 0)
            except ValueError:
                return 0

        self.search_term = request.POST.get("search[value]") or ""
        self.draw = getint("draw")  # unknown
        self.start = getint("start")  # offset
        self.length = getint("length")  # page size
        self.page_number = (
            (self.start / self.length) if self.length else 0) + 1

        self.sort_field, self.sort_direction = self.get_ordering(request)

        self.columns = self.get_configure_columns()
示例#2
0
 def save_form_progress(self, registry_code, context_model=None):
     from rdrf.forms.progress.form_progress import FormProgress
     registry_model = Registry.objects.get(code=registry_code)
     form_progress = FormProgress(registry_model)
     dynamic_data = self.load_dynamic_data(registry_code,
                                           "cdes",
                                           flattened=False)
     return form_progress.save_progress(self.obj, dynamic_data,
                                        context_model)
示例#3
0
 def __init__(self,
              registry_model,
              patient_model,
              form_model,
              context_form_group,
              context_model=None):
     self.registry_model = registry_model
     self.context_form_group = context_form_group
     self.patient_model = patient_model
     self.form_model = form_model
     self.context_model = context_model
     self.progress = FormProgress(self.registry_model)
     # if no progress cdes defined on form, don't show any percentage
     self.has_progress = form_model.has_progress_indicator
示例#4
0
    class FormWrapper(object):
        def __init__(self,
                     registry_model,
                     patient_model,
                     form_model,
                     context_form_group,
                     context_model=None):
            self.registry_model = registry_model
            self.context_form_group = context_form_group
            self.patient_model = patient_model
            self.form_model = form_model
            self.context_model = context_model
            self.progress = FormProgress(self.registry_model)
            # if no progress cdes defined on form, don't show any percentage
            self.has_progress = form_model.has_progress_indicator

        @property
        def link(self):
            return reverse('registry_form',
                           args=(self.registry_model.code, self.form_model.id,
                                 self.patient_model.pk, self.context_model.id))

        @property
        def title(self):
            if not self.context_form_group or self.context_form_group.context_type == "F":
                return self.form_model.nice_name
            else:
                # multiple group
                if self.context_form_group.supports_direct_linking:
                    value = self.context_form_group.get_name_from_cde(
                        self.patient_model, self.context_model)
                    if not value:
                        return "Not set"
                    else:
                        return value
                else:
                    return self.context_form_group.name + " " + self.form_model.nice_name

        @property
        def progress_percentage(self):
            return self.progress.get_form_progress(self.form_model,
                                                   self.patient_model,
                                                   self.context_model)

        @property
        def is_current(self):
            return self.progress.get_form_currency(self.form_model,
                                                   self.patient_model,
                                                   self.context_model)
    def _update_progress(self):
        form_progress = FormProgress(self.registry_model)

        for patient_model in Patient.objects.filter(
                rdrf_registry__in=[self.registry_model]):
            if not self.registry_model.has_feature("contexts"):
                default_context = patient_model.default_context(
                    self.registry_model)
                form_progress.save_for_patient(patient_model, default_context)
                self.stdout.write("Recalculated progress for Patient %s" %
                                  patient_model.pk)

            else:
                self.stderr.write(
                    "Script does not support registries with multiple contexts allowed, yet"
                )
                sys.exit(1)
示例#6
0
 def __init__(self,
              registry_model,
              column,
              form_model=None,
              section_model=None,
              cde_model=None,
              field=None):
     self.registry_model = registry_model
     self.column = column
     self.form_model = form_model
     self.section_model = section_model
     self.form_progress = FormProgress(self.registry_model)
     self.progress_percentage = None
     if self.section_model:
         self.is_multiple = section_model.allow_multiple
     else:
         self.is_multiple = False
     self.cde_model = cde_model
     self.field = field
示例#7
0
class PatientsListingView(View):
    def __init__(self, *args, **kwargs):
        super(PatientsListingView, self).__init__(*args, **kwargs)
        self.registry_model = None
        self.user = None
        self.registries = []
        self.patient_id = None

        # grid params
        self.custom_ordering = None
        self.start = None
        self.length = None
        self.page_number = None
        self.sort_field = None
        self.sort_direction = None
        self.columns = None
        self.queryset = None
        self.records_total = None
        self.filtered_total = None
        self.context = {}

    def get(self, request):
        # get just displays the empty table and writes the page
        # which initiates an ajax/post request on registry select
        # the protocol is the jquery DataTable
        # see http://datatables.net/manual/server-side
        self.user = request.user
        if self.user and self.user.is_anonymous:
            login_url = "%s?next=%s" % (reverse("two_factor:login"),
                                        reverse("login_router"))
            return redirect(login_url)

        self.do_security_checks()
        self.set_csrf(request)
        self.set_registry(request)
        self.set_registries()  # for drop down
        self.patient_id = request.GET.get("patient_id", None)

        template_context = self.build_context()
        template = self.get_template()

        return render(request, template, template_context)

    def get_template(self):
        template = 'rdrf_cdes/patients_listing_no_registries.html' if len(
            self.registries) == 0 else 'rdrf_cdes/patients_listing.html'
        return template

    def build_context(self):
        return {
            "registries":
            self.registries,
            "location":
            _("Patient Listing"),
            "patient_id":
            self.patient_id,
            "registry_code":
            self.registry_model.code if self.registry_model else None,
            "columns": [
                col.to_dict(i)
                for (i, col) in enumerate(self.get_configure_columns())
            ],
        }

    def get_columns(self):
        return [
            ColumnFullName(_("Patient"), "patients.can_see_full_name"),
            ColumnDateOfBirth(_("Date of Birth"), "patients.can_see_dob"),
            ColumnCodeField(_("Code"), "patients.can_see_code_field"),
            ColumnWorkingGroups(_("Working Groups"),
                                "patients.can_see_working_groups"),
            ColumnDiagnosisProgress(_("Diagnosis Entry Progress"),
                                    "patients.can_see_diagnosis_progress"),
            ColumnDiagnosisCurrency(_("Updated < 365 days"),
                                    "patients.can_see_diagnosis_currency"),
            ColumnGeneticDataMap(_("Genetic Data"),
                                 "patients.can_see_genetic_data_map"),
            ColumnContextMenu(_("Modules"), "patients.can_see_data_modules"),
        ]

    def get_configure_columns(self):
        columns = self.get_columns()
        for i, col in enumerate(columns):
            col.configure(self.registry_model, self.user, i)
        return [col for col in columns if col.user_can_see]

    def do_security_checks(self):
        if self.user.is_patient:
            raise PermissionDenied()

    def set_csrf(self, request):
        self.context.update(csrf(request))

    def set_registry(self, request):
        registry_code = request.GET.get("registry_code", None)
        if registry_code is not None:
            try:
                self.registry_model = Registry.objects.get(code=registry_code)
            except Registry.DoesNotExist:
                return HttpResponseRedirect("/")

    def set_registries(self):
        if self.registry_model is None:
            if self.user.is_superuser:
                self.registries = [
                    registry_model
                    for registry_model in Registry.objects.all()
                ]
            else:
                self.registries = [
                    registry_model
                    for registry_model in self.user.registry.all()
                ]
        else:
            self.registries = [self.registry_model]

    def json(self, data):
        json_data = json.dumps(data)
        return HttpResponse(json_data, content_type="application/json")

    def post(self, request):
        # see http://datatables.net/manual/server-side
        self.user = request.user
        if self.user and self.user.is_anonymous:
            login_url = "%s?next=%s" % (reverse("two_factor:login"),
                                        reverse("login_router"))
            return redirect(login_url)
        self.set_parameters(request)
        self.set_csrf(request)
        rows = self.get_results(request)
        results_dict = self.get_results_dict(self.draw, self.page_number,
                                             self.record_total,
                                             self.filtered_total, rows)
        return self.json(results_dict)

    def set_parameters(self, request):
        self.user = request.user
        self.registry_code = request.GET.get("registry_code")
        self.registry_model = get_object_or_404(Registry,
                                                code=self.registry_code)

        self.clinicians_have_patients = self.registry_model.has_feature(
            "clinicians_have_patients")
        self.form_progress = FormProgress(self.registry_model)
        self.supports_contexts = self.registry_model.has_feature("contexts")
        self.rdrf_context_manager = RDRFContextManager(self.registry_model)

        def getint(param):
            try:
                return int(request.POST.get(param) or 0)
            except ValueError:
                return 0

        self.search_term = request.POST.get("search[value]") or ""
        self.draw = getint("draw")  # unknown
        self.start = getint("start")  # offset
        self.length = getint("length")  # page size
        self.page_number = (
            (self.start / self.length) if self.length else 0) + 1

        self.sort_field, self.sort_direction = self.get_ordering(request)

        self.columns = self.get_configure_columns()

    def get_results(self, request):
        if self.registry_model is None:
            return []
        if not self.check_security():
            return []

        patients = self.run_query()
        return patients

    def check_security(self):
        self.do_security_checks()
        if not self.user.is_superuser:
            if self.registry_model.code not in [
                    r.code for r in self.user.registry.all()
            ]:
                logger.warning(
                    "User id %s tried to browse patients in registry %s of which they are not a member"
                    % (self.user.id, self.registry_model.code))
                return False
        return True

    def get_ordering(self, request):
        # columns[0][data]:full_name
        # order[0][column]:1
        # order[0][dir]:asc
        sort_column_index = None
        sort_direction = None
        for key in request.POST:
            if key.startswith("order"):
                if "[column]" in key:
                    sort_column_index = request.POST[key]
                elif "[dir]" in key:
                    sort_direction = request.POST[key]

        column_name = "columns[%s][data]" % sort_column_index
        sort_field = request.POST.get(column_name, None)
        return sort_field, sort_direction

    def run_query(self):
        self.get_initial_queryset()
        self.filter_by_user_group()
        self.apply_ordering()
        self.record_total = self.patients.count()
        self.apply_search_filter()
        self.filtered_total = self.patients.count()
        return self.get_rows_in_page()

    def _get_main_or_default_context(self, patient_model):
        # for registries which do not have multiple contexts this will be the single context model
        # assigned to the patient
        # for registries which allow multiple form groups, it will be the
        # (only) context with cfg marked as default
        context_model = patient_model.default_context(self.registry_model)
        assert context_model is not None, "Expected context model to exist always"
        if context_model.context_form_group:
            assert context_model.context_form_group.is_default, "Expected to always get a context of the default form group"

        return context_model

    def apply_custom_ordering(self, qs):
        key_func = [
            col.sort_key(self.supports_contexts, self.form_progress,
                         self.rdrf_context_manager) for col in self.columns
            if col.field == self.sort_field and col.sort_key
            and not col.sort_fields
        ]

        if key_func:
            # we have to retrieve all rows - otherwise , queryset has already been
            # ordered on base model
            k = key_func[0]

            def key_func_wrapper(thing):
                value = k(thing)

                if value is None:
                    return self.bottom
                else:
                    return value

            return sorted(qs,
                          key=key_func_wrapper,
                          reverse=(self.sort_direction == "desc"))
        else:
            return qs

    def get_rows_in_page(self):
        results = self.apply_custom_ordering(self.patients)

        rows = []
        paginator = Paginator(results, self.length)
        try:
            page = paginator.page(self.page_number)
        except InvalidPage:
            logger.error("invalid page number: %s" % self.page_number)
            return []

        self.append_rows(page, rows)
        return rows

    def append_rows(self, page_object, row_list_to_update):
        if self.registry_model.has_feature("consent_checks"):
            row_list_to_update.extend([
                self._get_row_dict(obj)
                for obj in page_object.object_list if consent_check(
                    self.registry_model, self.user, obj, "see_patient")
            ])
        else:
            row_list_to_update.extend(
                [self._get_row_dict(obj) for obj in page_object.object_list])

    def _get_row_dict(self, instance):
        # we need to do this so that the progress data for this instance
        # loaded!
        self.form_progress.reset()
        self.form_progress._set_current(instance)
        return {
            col.field: col.fmt(
                col.cell(instance, self.supports_contexts, self.form_progress,
                         self.rdrf_context_manager))
            for col in self.columns
        }

    def get_initial_queryset(self):
        self.registry_queryset = Registry.objects.filter(
            code=self.registry_model.code)
        self.patients = Patient.objects.all().prefetch_related(
            "working_groups").prefetch_related("rdrf_registry").filter(
                rdrf_registry__code=self.registry_model.code)

    def apply_search_filter(self):
        if self.search_term:
            self.patients = self.patients.filter(
                Q(given_names__icontains=self.search_term)
                | Q(family_name__icontains=self.search_term))

    def filter_by_user_group(self):
        if not self.user.is_superuser:
            if self.user.is_curator:
                query_patients = Q(
                    rdrf_registry__in=self.registry_queryset) & Q(
                        working_groups__in=self.user.working_groups.all())
                self.patients = self.patients.filter(query_patients)
            elif self.user.is_genetic_staff:
                self.patients = self.patients.filter(
                    working_groups__in=self.user.working_groups.all())
            elif self.user.is_genetic_curator:
                self.patients = self.patients.filter(
                    working_groups__in=self.user.working_groups.all())
            elif self.user.is_working_group_staff:
                self.patients = self.patients.filter(
                    working_groups__in=self.user.working_groups.all())
            elif self.user.is_clinician and self.clinicians_have_patients:
                self.patients = self.patients.filter(clinician=self.user)
            elif self.user.is_clinician and not self.clinicians_have_patients:
                query_patients = Q(
                    rdrf_registry__in=self.registry_queryset) & Q(
                        working_groups__in=self.user.working_groups.all())
                self.patients = self.patients.filter(query_patients)
            elif self.user.is_patient:
                self.patients = self.patients.filter(user=self.user)
            else:
                self.patients = self.patients.none()
        else:
            self.patients = self.patients.filter(
                rdrf_registry__in=self.registry_queryset)

    def apply_ordering(self):
        if self.sort_field and self.sort_direction:

            def sdir(field):
                return "-" + field if self.sort_direction == "desc" else field

            sort_fields = chain(*[
                map(sdir, col.sort_fields) for col in self.columns
                if col.field == self.sort_field
            ])

            self.patients = self.patients.order_by(*sort_fields)

    def get_results_dict(self, draw, page, total_records,
                         total_filtered_records, rows):
        return {
            "draw": draw,
            "recordsTotal": total_records,
            "recordsFiltered": total_filtered_records,
            "rows": rows
        }
示例#8
0
class DataSource:
    def __init__(self,
                 registry_model,
                 column,
                 form_model=None,
                 section_model=None,
                 cde_model=None,
                 field=None):
        self.registry_model = registry_model
        self.column = column
        self.form_model = form_model
        self.section_model = section_model
        self.form_progress = FormProgress(self.registry_model)
        self.progress_percentage = None
        if self.section_model:
            self.is_multiple = section_model.allow_multiple
        else:
            self.is_multiple = False
        self.cde_model = cde_model
        self.field = field

    @property
    def datatype(self):
        return lower_strip(self.cde_model.datatype)

    @property
    def column_name(self):
        return self.column.name

    def get_value(self, patient_model, context_model):
        if self.field:
            return self._get_field_value(patient_model, context_model)
        else:
            return self._get_cde_value(patient_model, context_model)

    def _get_field_value(self, patient_model, context_model):
        if self.field == "patient_id":
            return patient_model.pk
        elif self.field == "form":
            return self.form_model.name
        elif self.field == "context_id":
            return context_model.pk
        elif self.field == "section":
            return self.section_model.display_name
        elif self.field == "form_group":
            return get_form_group(context_model)
        elif self.field == "username":
            return self._get_last_user(patient_model, context_model)
        elif self.field == "timestamp":
            return patient_model.get_form_timestamp(self.form_model,
                                                    context_model)
        elif self.field == "progress":
            return self._get_form_progress(patient_model, context_model)
        else:
            raise Exception("Unknown field: %s" % self.field)

    def _get_form_progress(self, patient_model, context_model):
        if self.progress_percentage is None:
            self.progress_percentage = self.form_progress.get_form_progress(
                self.form_model, patient_model, context_model)
        return self.progress_percentage

    def _get_last_user(self, patient_model, context_model):
        # last user to edit the _form_ in this context
        history = ClinicalData.objects.collection(self.registry_model.code,
                                                  "history")
        snapshots = history.find(patient_model, record_type="snapshot")
        snapshots = sorted([s for s in snapshots],
                           key=attrgetter("pk"),
                           reverse=True)
        for snapshot in snapshots:
            if snapshot.data and "record" in snapshot.data:
                record = snapshot.data["record"]
                if "context_id" in record:
                    if context_model.pk == record["context_id"]:
                        if "form_name" in snapshot.data:
                            form_name = snapshot.data["form_name"]
                            if form_name == self.form_model.name:
                                if "form_user" in snapshot.data:
                                    return snapshot.data["form_user"]

    def _get_cde_value(self, patient_model, context_model):
        try:
            data = get_clinical_data(self.registry_model.code,
                                     patient_model.pk, context_model.pk)

            raw_value = patient_model.get_form_value(
                self.registry_model.code,
                self.form_model.name,
                self.section_model.code,
                self.cde_model.code,
                False,
                context_id=context_model.pk,
                clinical_data=data)

        except KeyError:
            # the dynamic data record is empty
            return None

        value = self.cde_model.get_display_value(raw_value)
        return fix_display_value(self.cde_model.datatype, value)