Coverage for tasks/khandaker_insight_medical.py: 62%
63 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-08 23:14 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-08 23:14 +0000
1#!/usr/bin/env python
3"""
4camcops_server/tasks/khandaker_insight_medical.py
6===============================================================================
8 Copyright (C) 2012, University of Cambridge, Department of Psychiatry.
9 Created by Rudolf Cardinal (rnc1001@cam.ac.uk).
11 This file is part of CamCOPS.
13 CamCOPS is free software: you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
18 CamCOPS is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with CamCOPS. If not, see <https://www.gnu.org/licenses/>.
26===============================================================================
28"""
30# =============================================================================
31# Imports
32# =============================================================================
34from typing import Any, Dict, Tuple, Type
36import cardinal_pythonlib.rnc_web as ws
37from sqlalchemy.ext.declarative import DeclarativeMeta
38from sqlalchemy.sql.schema import Column
39from sqlalchemy.sql.sqltypes import UnicodeText
41from camcops_server.cc_modules.cc_constants import CssClass
42from camcops_server.cc_modules.cc_html import (
43 bold,
44 get_yes_no_none,
45 tr_span_col,
46)
47from camcops_server.cc_modules.cc_request import CamcopsRequest
48from camcops_server.cc_modules.cc_sqla_coltypes import BoolColumn
49from camcops_server.cc_modules.cc_task import Task, TaskHasPatientMixin
52# =============================================================================
53# Constants
54# =============================================================================
57class KQInfo(object):
58 def __init__(self, stem: str, heading_xml: str = "") -> None:
59 self.fieldname_yn = stem + "_yn"
60 self.fieldname_comment = stem + "_comment"
61 self.question_xmlstr = "q_" + stem
62 self.heading_xmlstr = heading_xml
64 def has_heading(self) -> bool:
65 return bool(self.heading_xmlstr)
68QUESTIONS = [
69 KQInfo("cancer", "heading_cancer"),
70 KQInfo("epilepsy", "heading_brain"),
71 KQInfo("cva_headinjury_braintumour"),
72 KQInfo("ms_pd_dementia"),
73 KQInfo("cerebralpalsy_otherbrain"),
74 KQInfo("visual_impairment"),
75 KQInfo("heart_disorder", "heading_cardiovascular"),
76 KQInfo("respiratory", "heading_respiratory"),
77 KQInfo("gastrointestinal", "heading_gastrointestinal"),
78 KQInfo("other_inflammatory", "heading_inflammatory"),
79 KQInfo("musculoskeletal", "heading_musculoskeletal"),
80 KQInfo("renal_urinary", "heading_renal_urinary"),
81 KQInfo("dermatological", "heading_dermatological"),
82 KQInfo("diabetes", "heading_endocrinological"),
83 KQInfo("other_endocrinological"),
84 KQInfo("haematological", "heading_haematological"),
85 KQInfo("infections", "heading_infections"),
86]
88X_TITLE = "title"
89X_INSTRUCTION = "instruction"
90X_HEADING_CONDITION = "heading_condition"
91X_HEADING_YN = "heading_yn"
92X_HEADING_COMMENT = "heading_comment"
93X_COMMENT_HINT = "comment_hint"
96# =============================================================================
97# Khandaker_1_MedicalHistory
98# =============================================================================
101class KhandakerInsightMedicalMetaclass(DeclarativeMeta):
102 # noinspection PyInitNewSignature
103 def __init__(
104 cls: Type["KhandakerInsightMedical"],
105 name: str,
106 bases: Tuple[Type, ...],
107 classdict: Dict[str, Any],
108 ) -> None:
109 for qinfo in QUESTIONS:
110 setattr(cls, qinfo.fieldname_yn, BoolColumn(qinfo.fieldname_yn))
111 setattr(
112 cls,
113 qinfo.fieldname_comment,
114 Column(qinfo.fieldname_comment, UnicodeText),
115 )
116 super().__init__(name, bases, classdict)
119class KhandakerInsightMedical(
120 TaskHasPatientMixin, Task, metaclass=KhandakerInsightMedicalMetaclass
121):
122 """
123 Server implementation of the Khandaker_1_MedicalHistory task.
124 """
126 __tablename__ = "khandaker_1_medicalhistory" # NB historical name
127 shortname = "Khandaker_Insight_Medical"
128 info_filename_stem = "khandaker_insight_medical"
130 @staticmethod
131 def longname(req: "CamcopsRequest") -> str:
132 _ = req.gettext
133 return _("Khandaker GM — Insight — Medical history")
135 def is_complete(self) -> bool:
136 for qinfo in QUESTIONS:
137 yn_value = getattr(self, qinfo.fieldname_yn)
138 if yn_value is None:
139 return False
140 if yn_value:
141 comment = getattr(self, qinfo.fieldname_comment)
142 if not comment:
143 return False
144 return True
146 def get_task_html(self, req: CamcopsRequest) -> str:
147 html = f"""
148 <div class="{CssClass.SUMMARY}">
149 <table class="{CssClass.SUMMARY}">
150 {self.get_is_complete_tr(req)}
151 </table>
152 </div>
153 <table class="{CssClass.TASKDETAIL}">
154 <tr>
155 <th width="40%">{self.xstring(req,
156 X_HEADING_CONDITION)}</th>
157 <th width="20%">{self.xstring(req, X_HEADING_YN)}</th>
158 <th width="40%">{self.xstring(req, X_HEADING_COMMENT)}</th>
159 </tr>
160 """
162 for qinfo in QUESTIONS:
163 if qinfo.has_heading():
164 html += tr_span_col(
165 self.xstring(req, qinfo.heading_xmlstr),
166 cols=3,
167 tr_class=CssClass.SUBHEADING,
168 )
169 yn_value = getattr(self, qinfo.fieldname_yn)
170 yn_str = get_yes_no_none(req, yn_value)
171 if yn_value:
172 yn_str = bold(yn_str)
173 comment_value = getattr(self, qinfo.fieldname_comment)
174 html += f"""
175 <tr>
176 <td>{self.xstring(req, qinfo.question_xmlstr)}</td>
177 <td>{yn_str}</td>
178 <td>{bold(ws.webify(comment_value))
179 if comment_value else ""}</td>
180 </tr>
181 """
183 html += "</table>"
184 return html