Source code for crate_anon.crateweb.consent.forms

"""
crate_anon/crateweb/consent/forms.py

===============================================================================

    Copyright (C) 2015, University of Cambridge, Department of Psychiatry.
    Created by Rudolf Cardinal (rnc1001@cam.ac.uk).

    This file is part of CRATE.

    CRATE is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    CRATE is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with CRATE. If not, see <https://www.gnu.org/licenses/>.

===============================================================================

**Django forms for the consent-to-contact system.**

"""

import logging

from cardinal_pythonlib.django.forms import (
    MultipleNhsNumberAreaField,
    MultipleWordAreaField,
    SingleNhsNumberField,
)
from django import forms
from django.conf import settings
from django.utils.safestring import mark_safe

from crate_anon.crateweb.consent.models import (
    ClinicianResponse,
    Study,
    TeamInfo,
    TeamRep,
)
from crate_anon.crateweb.research.research_db_info import (
    SingleResearchDatabase,
)

log = logging.getLogger(__name__)


[docs]class SingleNhsNumberForm(forms.Form): """ Form to capture an NHS number. """ nhs_number = SingleNhsNumberField(label="NHS number")
[docs]class AbstractContactRequestForm(forms.Form): """ Base class for contact requets. """
[docs] def clean(self) -> None: cleaned_data = super().clean() study = cleaned_data.get("study") if not study: raise forms.ValidationError("Must specify study") request_direct_approach = cleaned_data.get("request_direct_approach") if request_direct_approach and not study.request_direct_approach: raise forms.ValidationError( "Study not approved for direct approach." )
[docs]class SuperuserSubmitContactRequestForm(AbstractContactRequestForm): """ Form for superusers (the RDBM) to submit a contact request. """ study = forms.ModelChoiceField( queryset=Study.get_queryset_possible_contact_studies() ) request_direct_approach = forms.BooleanField( label="Request direct approach to patient, if available " "(UNTICK to ask clinician for additional info)", required=False, initial=True, ) nhs_numbers = MultipleNhsNumberAreaField( label="NHS numbers", required=False ) rids = MultipleWordAreaField(required=False) mrids = MultipleWordAreaField(required=False)
[docs] def __init__( self, *args, dbinfo: SingleResearchDatabase, **kwargs ) -> None: super().__init__(*args, **kwargs) rids = self.fields["rids"] # type: MultipleWordAreaField mrids = self.fields["mrids"] # type: MultipleWordAreaField rids.label = f"{dbinfo.rid_field} ({dbinfo.rid_description}) (RID)" mrids.label = f"{dbinfo.mrid_field} ({dbinfo.mrid_description}) (MRID)"
[docs]class ResearcherSubmitContactRequestForm(AbstractContactRequestForm): """ Form for researchers to submit a contact request for their own studies. """ study = forms.ModelChoiceField(queryset=None) # ... queryset changed below request_direct_approach = forms.BooleanField( label="Request direct approach to patient, if available " "(UNTICK to ask clinician for additional info)", required=False, initial=True, ) rids = MultipleWordAreaField(required=False) mrids = MultipleWordAreaField(required=False)
[docs] def __init__( self, *args, user: settings.AUTH_USER_MODEL, dbinfo: SingleResearchDatabase, **kwargs, ) -> None: super().__init__(*args, **kwargs) study = self.fields["study"] # type: forms.ModelChoiceField rids = self.fields["rids"] # type: MultipleWordAreaField mrids = self.fields["mrids"] # type: MultipleWordAreaField study.queryset = Study.filter_studies_for_researcher( queryset=Study.get_queryset_possible_contact_studies(), user=user ) # https://docs.djangoproject.com/en/1.8/ref/models/querysets/#field-lookups # noqa # https://stackoverflow.com/questions/5329586/django-modelchoicefield-filtering-query-set-and-setting-default-value-as-an-obj # noqa rids.label = f"{dbinfo.rid_field} ({dbinfo.rid_description}) (RID)" mrids.label = f"{dbinfo.mrid_field} ({dbinfo.mrid_description}) (MRID)"
[docs]class ClinicianSubmitContactRequestForm(AbstractContactRequestForm): """ Form for clinician to request that a patient of their's gets contacted about a study. """ study = forms.ModelChoiceField( queryset=Study.get_queryset_possible_contact_studies() ) nhs_numbers = MultipleNhsNumberAreaField( label="NHS numbers", required=False ) rids = MultipleWordAreaField(required=False) mrids = MultipleWordAreaField(required=False) email = forms.EmailField( required=True, label=mark_safe( "Please ensure we have the correct details for you." "<br />Email" ), ) signatory_title = forms.CharField( required=False, label="Title for signature (e.g. 'Consultant psychiatrist')", ) title = forms.CharField(required=True, label="Title") firstname = forms.CharField(required=True, label="First name") lastname = forms.CharField(required=True, label="Last name") let_rdbm_contact_pt = forms.BooleanField( label="Get the database manager to contact the patient directly", required=False, )
[docs] def __init__( self, *args, dbinfo: SingleResearchDatabase, email_addr: str, title: str, firstname: str, lastname: str, **kwargs, ) -> None: super().__init__(*args, **kwargs) rids = self.fields["rids"] # type: MultipleWordAreaField mrids = self.fields["mrids"] # type: MultipleWordAreaField rids.label = f"{dbinfo.rid_field} ({dbinfo.rid_description}) (RID)" mrids.label = f"{dbinfo.mrid_field} ({dbinfo.mrid_description}) (MRID)" email = self.fields["email"] clinician_title = self.fields["title"] first = self.fields["firstname"] last = self.fields["lastname"] email.initial = email_addr clinician_title.initial = title first.initial = firstname last.initial = lastname
[docs]class ClinicianResponseForm(forms.ModelForm): """ Form for clinicians to respond to a contact request. """ class Meta: model = ClinicianResponse fields = [ "token", "email_choice", "response", "veto_reason", "ineligible_reason", "pt_uncontactable_reason", "clinician_confirm_name", ] widgets = { "token": forms.HiddenInput(), "email_choice": forms.HiddenInput(), }
[docs]class TeamRepAdminForm(forms.ModelForm): """ Custom form for the RDBM to edit team reps. The purposes is so that we only ask the database for team information at the point of use (and not e.g. to run database migrations from the command line!). """ class Meta: model = TeamRep fields = [ "team", "user", ]
[docs] def __init__(self, *args, **kwargs) -> None: """ Set the possible teams. """ super().__init__(*args, **kwargs) self.fields["team"] = forms.ChoiceField( choices=TeamInfo.team_choices() )