Source code for camcops_server.tasks.khandaker_mojo_medical

"""
camcops_server/tasks/khandaker_mojo_medical.py

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

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

    This file is part of CamCOPS.

    CamCOPS 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.

    CamCOPS 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 CamCOPS. If not, see <https://www.gnu.org/licenses/>.

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

"""

from typing import Any, Type

from sqlalchemy.sql.sqltypes import Date, Float, Integer, UnicodeText

from camcops_server.cc_modules.cc_constants import CssClass
from camcops_server.cc_modules.cc_html import tr_qa
from camcops_server.cc_modules.cc_request import CamcopsRequest
from camcops_server.cc_modules.cc_sqla_coltypes import (
    bool_column,
    camcops_column,
    ZERO_TO_TWO_CHECKER,
)
from camcops_server.cc_modules.cc_task import Task, TaskHasPatientMixin


[docs]class KhandakerMojoMedical( # type: ignore[misc] TaskHasPatientMixin, Task, ): """ Server implementation of the KhandakerMojoMedical task """ __tablename__ = "khandaker_mojo_medical" shortname = "Khandaker_MOJO_Medical" info_filename_stem = "khandaker_mojo" provides_trackers = False # Section 1: General Information FN_DIAGNOSIS = "diagnosis" FN_DIAGNOSIS_DATE = "diagnosis_date" FN_DIAGNOSIS_DATE_APPROXIMATE = "diagnosis_date_approximate" FN_HAS_FIBROMYALGIA = "has_fibromyalgia" FN_IS_PREGNANT = "is_pregnant" FN_HAS_INFECTION_PAST_MONTH = "has_infection_past_month" @classmethod def extend_columns( cls: Type["KhandakerMojoMedical"], **kwargs: Any ) -> None: setattr( cls, cls.FN_DIAGNOSIS, camcops_column( cls.FN_DIAGNOSIS, Integer, permitted_value_checker=ZERO_TO_TWO_CHECKER, comment=( "Diagnosis (0 Rheumatoid Arthritis, " "1 Ankylosing Spondylitis, 2 Sjögren’s Syndrome)" ), ), ) setattr( cls, cls.FN_DIAGNOSIS_DATE, camcops_column( cls.FN_DIAGNOSIS_DATE, Date, comment=( "Date of first diagnosis (may be approx from " "'duration of illness (years))'" ), ), ) setattr( cls, cls.FN_DIAGNOSIS_DATE_APPROXIMATE, bool_column( cls.FN_DIAGNOSIS_DATE_APPROXIMATE, comment="True if diagnosis date was derived from duration", ), ) setattr( cls, cls.FN_HAS_FIBROMYALGIA, bool_column( cls.FN_HAS_FIBROMYALGIA, comment="Do you have a diagnosis of fibromyalgia?", ), ) setattr( cls, cls.FN_IS_PREGNANT, bool_column( cls.FN_IS_PREGNANT, comment=( "Are you, or is there any possibility that you might " "be pregnant?" ), ), ) setattr( cls, cls.FN_HAS_INFECTION_PAST_MONTH, bool_column( cls.FN_HAS_INFECTION_PAST_MONTH, comment=( "Do you currently have an infection, or had " "treatment for an infection (e.g antibiotics) " "in the past month?" ), ), ) setattr( cls, cls.FN_HAD_INFECTION_TWO_MONTHS_PRECEDING, bool_column( cls.FN_HAD_INFECTION_TWO_MONTHS_PRECEDING, comment=( "Have you had an infection, or had treatment for " "an infection (e.g antibiotics) in the 2 months " "preceding last month?" ), constraint_name="ck_kh2mm_had_infection", ), ) setattr( cls, cls.FN_HAS_ALCOHOL_SUBSTANCE_DEPENDENCE, bool_column( cls.FN_HAS_ALCOHOL_SUBSTANCE_DEPENDENCE, comment=( "Do you have a current diagnosis of alcohol or " "substance dependence?" ), constraint_name="ck_kh2mm_has_alcohol", ), ) setattr( cls, cls.FN_SMOKING_STATUS, camcops_column( cls.FN_SMOKING_STATUS, Integer, permitted_value_checker=ZERO_TO_TWO_CHECKER, comment=( "What is your smoking status? (0 Never smoked, " "1 Ex-smoker, 2 Current smoker)" ), ), ) setattr( cls, cls.FN_ALCOHOL_UNITS_PER_WEEK, camcops_column( cls.FN_ALCOHOL_UNITS_PER_WEEK, Float, comment=( "How much alcohol do you drink per week? (medium " "glass of wine = 2 units, pint of beer at 4.5% = " "2.5 units, 25ml of spirits at 40% = 1 unit)" ), ), ) setattr( cls, cls.FN_DEPRESSION, bool_column( cls.FN_DEPRESSION, comment=( "Have you had any of the following conditions " "diagnosed by a doctor?" ), ), ) setattr( cls, cls.FN_BIPOLAR_DISORDER, bool_column( cls.FN_BIPOLAR_DISORDER, comment=( "Have you had any of the following conditions " "diagnosed by a doctor?" ), ), ) setattr( cls, cls.FN_SCHIZOPHRENIA, bool_column( cls.FN_SCHIZOPHRENIA, comment=( "Have you had any of the following conditions " "diagnosed by a doctor?" ), ), ) setattr( cls, cls.FN_AUTISM, bool_column( cls.FN_AUTISM, comment=( "Have you had any of the following conditions " "diagnosed by a doctor?" ), ), ) setattr( cls, cls.FN_PTSD, bool_column( cls.FN_PTSD, comment=( "Have you had any of the following conditions " "diagnosed by a doctor?" ), ), ) setattr( cls, cls.FN_ANXIETY, bool_column( cls.FN_ANXIETY, comment=( "Have you had any of the following conditions " "diagnosed by a doctor?" ), ), ) setattr( cls, cls.FN_PERSONALITY_DISORDER, bool_column( cls.FN_PERSONALITY_DISORDER, comment=( "Have you had any of the following conditions " "diagnosed by a doctor?" ), ), ) setattr( cls, cls.FN_INTELLECTUAL_DISABILITY, bool_column( cls.FN_INTELLECTUAL_DISABILITY, comment=( "Have you had any of the following conditions " "diagnosed by a doctor?" ), ), ) setattr( cls, cls.FN_OTHER_MENTAL_ILLNESS, bool_column( cls.FN_OTHER_MENTAL_ILLNESS, comment=( "Have you had any of the following conditions " "diagnosed by a doctor?" ), ), ) setattr( cls, cls.FN_OTHER_MENTAL_ILLNESS_DETAILS, camcops_column( cls.FN_OTHER_MENTAL_ILLNESS_DETAILS, UnicodeText, comment="If other, please list here", ), ) setattr( cls, cls.FN_HOSPITALISED_IN_LAST_YEAR, bool_column( cls.FN_HOSPITALISED_IN_LAST_YEAR, comment=( "Have you had a physical or mental illness " "requiring hospitalisation in the previous 12 " "months?" ), ), ) setattr( cls, cls.FN_HOSPITALISATION_DETAILS, camcops_column( cls.FN_HOSPITALISATION_DETAILS, UnicodeText, comment=( "If yes, please list here (name of illness, number " "of hospitilisations and duration):" ), ), ) setattr( cls, cls.FN_FAMILY_DEPRESSION, bool_column( cls.FN_FAMILY_DEPRESSION, comment=( "Has anyone in your immediate family " "(parents, siblings or children) had any of the " "following conditions diagnosed by a doctor?" ), ), ) setattr( cls, cls.FN_FAMILY_BIPOLAR_DISORDER, bool_column( cls.FN_FAMILY_BIPOLAR_DISORDER, comment=( "Has anyone in your immediate family " "(parents, siblings or children) had any of the " "following conditions diagnosed by a doctor?" ), ), ) setattr( cls, cls.FN_FAMILY_SCHIZOPHRENIA, bool_column( cls.FN_FAMILY_SCHIZOPHRENIA, comment=( "Has anyone in your immediate family " "(parents, siblings or children) had any of the " "following conditions diagnosed by a doctor?" ), ), ) setattr( cls, cls.FN_FAMILY_AUTISM, bool_column( cls.FN_FAMILY_AUTISM, comment=( "Has anyone in your immediate family " "(parents, siblings or children) had any of the " "following conditions diagnosed by a doctor?" ), ), ) setattr( cls, cls.FN_FAMILY_PTSD, bool_column( cls.FN_FAMILY_PTSD, comment=( "Has anyone in your immediate family " "(parents, siblings or children) had any of the " "following conditions diagnosed by a doctor?" ), ), ) setattr( cls, cls.FN_FAMILY_ANXIETY, bool_column( cls.FN_FAMILY_ANXIETY, comment=( "Has anyone in your immediate family " "(parents, siblings or children) had any of the " "following conditions diagnosed by a doctor?" ), ), ) setattr( cls, cls.FN_FAMILY_PERSONALITY_DISORDER, bool_column( cls.FN_FAMILY_PERSONALITY_DISORDER, comment=( "Has anyone in your immediate family " "(parents, siblings or children) had any of the " "following conditions diagnosed by a doctor?" ), ), ) setattr( cls, cls.FN_FAMILY_INTELLECTUAL_DISABILITY, bool_column( cls.FN_FAMILY_INTELLECTUAL_DISABILITY, comment=( "Has anyone in your immediate family " "(parents, siblings or children) had any of the " "following conditions diagnosed by a doctor?" ), constraint_name="ck_kh2mm_fam_int_dis", ), ) setattr( cls, cls.FN_FAMILY_OTHER_MENTAL_ILLNESS, bool_column( cls.FN_FAMILY_OTHER_MENTAL_ILLNESS, comment=( "Has anyone in your immediate family " "(parents, siblings or children) had any of the " "following conditions diagnosed by a doctor?" ), ), ) setattr( cls, cls.FN_FAMILY_OTHER_MENTAL_ILLNESS_DETAILS, camcops_column( cls.FN_FAMILY_OTHER_MENTAL_ILLNESS_DETAILS, UnicodeText, comment="If other, please list here", ), ) FN_HAD_INFECTION_TWO_MONTHS_PRECEDING = ( "had_infection_two_months_preceding" ) FN_HAS_ALCOHOL_SUBSTANCE_DEPENDENCE = "has_alcohol_substance_dependence" FN_SMOKING_STATUS = "smoking_status" FN_ALCOHOL_UNITS_PER_WEEK = "alcohol_units_per_week" # Section 2: Medical History FN_DEPRESSION = "depression" FN_BIPOLAR_DISORDER = "bipolar_disorder" FN_SCHIZOPHRENIA = "schizophrenia" FN_AUTISM = "autism" FN_PTSD = "ptsd" FN_ANXIETY = "anxiety" FN_PERSONALITY_DISORDER = "personality_disorder" FN_INTELLECTUAL_DISABILITY = "intellectual_disability" FN_OTHER_MENTAL_ILLNESS = "other_mental_illness" FN_OTHER_MENTAL_ILLNESS_DETAILS = "other_mental_illness_details" FN_HOSPITALISED_IN_LAST_YEAR = "hospitalised_in_last_year" FN_HOSPITALISATION_DETAILS = "hospitalisation_details" # Section 3: Family history FN_FAMILY_DEPRESSION = "family_depression" FN_FAMILY_BIPOLAR_DISORDER = "family_bipolar_disorder" FN_FAMILY_SCHIZOPHRENIA = "family_schizophrenia" FN_FAMILY_AUTISM = "family_autism" FN_FAMILY_PTSD = "family_ptsd" FN_FAMILY_ANXIETY = "family_anxiety" FN_FAMILY_PERSONALITY_DISORDER = "family_personality_disorder" FN_FAMILY_INTELLECTUAL_DISABILITY = "family_intellectual_disability" FN_FAMILY_OTHER_MENTAL_ILLNESS = "family_other_mental_illness" FN_FAMILY_OTHER_MENTAL_ILLNESS_DETAILS = ( "family_other_mental_illness_details" ) MANDATORY_FIELD_NAMES_1 = [ FN_DIAGNOSIS, FN_DIAGNOSIS_DATE, FN_HAS_FIBROMYALGIA, FN_IS_PREGNANT, FN_HAS_INFECTION_PAST_MONTH, FN_HAD_INFECTION_TWO_MONTHS_PRECEDING, FN_HAS_ALCOHOL_SUBSTANCE_DEPENDENCE, FN_SMOKING_STATUS, FN_ALCOHOL_UNITS_PER_WEEK, ] MANDATORY_FIELD_NAMES_2 = [ FN_DEPRESSION, FN_BIPOLAR_DISORDER, FN_SCHIZOPHRENIA, FN_AUTISM, FN_PTSD, FN_ANXIETY, FN_PERSONALITY_DISORDER, FN_INTELLECTUAL_DISABILITY, FN_OTHER_MENTAL_ILLNESS, FN_HOSPITALISED_IN_LAST_YEAR, ] MANDATORY_FIELD_NAMES_3 = [ FN_FAMILY_DEPRESSION, FN_FAMILY_BIPOLAR_DISORDER, FN_FAMILY_SCHIZOPHRENIA, FN_FAMILY_AUTISM, FN_FAMILY_PTSD, FN_FAMILY_ANXIETY, FN_FAMILY_PERSONALITY_DISORDER, FN_FAMILY_INTELLECTUAL_DISABILITY, FN_FAMILY_OTHER_MENTAL_ILLNESS, ] MANDATORY_FIELD_NAMES = ( MANDATORY_FIELD_NAMES_1 + MANDATORY_FIELD_NAMES_2 + MANDATORY_FIELD_NAMES_3 ) # If the answer is yes to any of these, we need to have the details DETAILS_FIELDS = { FN_OTHER_MENTAL_ILLNESS: FN_OTHER_MENTAL_ILLNESS_DETAILS, FN_HOSPITALISED_IN_LAST_YEAR: FN_HOSPITALISATION_DETAILS, FN_FAMILY_OTHER_MENTAL_ILLNESS: FN_FAMILY_OTHER_MENTAL_ILLNESS_DETAILS, } MULTI_CHOICE_FIELD_NAMES = [FN_DIAGNOSIS, FN_SMOKING_STATUS]
[docs] @staticmethod def longname(req: "CamcopsRequest") -> str: _ = req.gettext return _("Khandaker GM — MOJO — Medical questionnaire")
[docs] def is_complete(self) -> bool: if self.any_fields_none(self.MANDATORY_FIELD_NAMES): return False if not self.field_contents_valid(): return False for field_name, details_field_name in self.DETAILS_FIELDS.items(): if getattr(self, field_name): if getattr(self, details_field_name) is None: return False return True
[docs] def get_task_html(self, req: CamcopsRequest) -> str: heading_1 = self.xstring(req, "general_information_title") rows_1 = "" for field_name in self.MANDATORY_FIELD_NAMES_1: rows_1 += self.get_rows(req, field_name) heading_2 = self.xstring(req, "medical_history_title") rows_2 = "" for field_name in self.MANDATORY_FIELD_NAMES_2: rows_2 += self.get_rows(req, field_name) heading_3 = self.xstring(req, "family_history_title") rows_3 = "" for field_name in self.MANDATORY_FIELD_NAMES_3: rows_3 += self.get_rows(req, field_name) html = f""" <div class="{CssClass.SUMMARY}"> <table class="{CssClass.SUMMARY}"> {self.get_is_complete_tr(req)} </table> </div> <h3>{heading_1}</h3> <table class="{CssClass.TASKDETAIL}"> <tr> <th width="60%">Question</th> <th width="40%">Answer</th> </tr> {rows_1} </table> <h3>{heading_2}</h3> <table class="{CssClass.TASKDETAIL}"> <tr> <th width="60%">Question</th> <th width="40%">Answer</th> </tr> {rows_2} </table> <h3>{heading_3}</h3> <table class="{CssClass.TASKDETAIL}"> <tr> <th width="60%">Question</th> <th width="40%">Answer</th> </tr> {rows_3} </table> """ return html
def get_rows(self, req: CamcopsRequest, field_name: str) -> str: rows = "" question_text = self.xstring(req, f"q_{field_name}") answer = getattr(self, field_name) answer_text = answer if answer is not None and ( field_name in self.MULTI_CHOICE_FIELD_NAMES ): answer_text = self.xstring(req, f"{field_name}_{answer}") rows += tr_qa(question_text, answer_text) if answer and field_name in self.DETAILS_FIELDS: details_field_name = self.DETAILS_FIELDS[field_name] details_question_text = self.xstring( req, f"q_{details_field_name}" ) details_answer = getattr(self, details_field_name) rows += tr_qa(details_question_text, details_answer) if field_name == self.FN_DIAGNOSIS_DATE: rows += tr_qa( self.xstring(req, f"q_{self.FN_DIAGNOSIS_DATE_APPROXIMATE}"), getattr(self, self.FN_DIAGNOSIS_DATE_APPROXIMATE), ) return rows