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

1""" 

2camcops_server/tasks/khandaker_insight_medical.py 

3 

4=============================================================================== 

5 

6 Copyright (C) 2012, University of Cambridge, Department of Psychiatry. 

7 Created by Rudolf Cardinal (rnc1001@cam.ac.uk). 

8 

9 This file is part of CamCOPS. 

10 

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. 

15 

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. 

20 

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

23 

24=============================================================================== 

25 

26""" 

27 

28# ============================================================================= 

29# Imports 

30# ============================================================================= 

31 

32from typing import Any, Type 

33 

34import cardinal_pythonlib.rnc_web as ws 

35from sqlalchemy.sql.schema import Column 

36from sqlalchemy.sql.sqltypes import UnicodeText 

37 

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 

47 

48 

49# ============================================================================= 

50# Constants 

51# ============================================================================= 

52 

53 

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 

60 

61 def has_heading(self) -> bool: 

62 return bool(self.heading_xmlstr) 

63 

64 

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] 

84 

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" 

91 

92 

93# ============================================================================= 

94# Khandaker_1_MedicalHistory 

95# ============================================================================= 

96 

97 

98class KhandakerInsightMedical( # type: ignore[misc] 

99 TaskHasPatientMixin, 

100 Task, 

101): 

102 """ 

103 Server implementation of the Khandaker_1_MedicalHistory task. 

104 """ 

105 

106 __tablename__ = "khandaker_1_medicalhistory" # NB historical name 

107 shortname = "Khandaker_Insight_Medical" 

108 info_filename_stem = "khandaker_insight_medical" 

109 

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 ) 

121 

122 @staticmethod 

123 def longname(req: "CamcopsRequest") -> str: 

124 _ = req.gettext 

125 return _("Khandaker GM — Insight — Medical history") 

126 

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 

137 

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 """ 

153 

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 """ 

174 

175 html += "</table>" 

176 return html