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