Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1#!/usr/bin/env python 

2 

3""" 

4camcops_server/tasks/apeqpt.py 

5 

6=============================================================================== 

7 

8 Copyright (C) 2012-2020 Rudolf Cardinal (rudolf@pobox.com). 

9 

10 This file is part of CamCOPS. 

11 

12 CamCOPS is free software: you can redistribute it and/or modify 

13 it under the terms of the GNU General Public License as published by 

14 the Free Software Foundation, either version 3 of the License, or 

15 (at your option) any later version. 

16 

17 CamCOPS is distributed in the hope that it will be useful, 

18 but WITHOUT ANY WARRANTY; without even the implied warranty of 

19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

20 GNU General Public License for more details. 

21 

22 You should have received a copy of the GNU General Public License 

23 along with CamCOPS. If not, see <https://www.gnu.org/licenses/>. 

24 

25=============================================================================== 

26 

27- By Joe Kearney, Rudolf Cardinal. 

28 

29""" 

30 

31from typing import List, TYPE_CHECKING 

32 

33from fhirclient.models.questionnaire import QuestionnaireItem 

34from fhirclient.models.questionnaireresponse import ( 

35 QuestionnaireResponseItem, 

36 QuestionnaireResponseItemAnswer, 

37) 

38from sqlalchemy.sql.sqltypes import Integer, UnicodeText 

39 

40from camcops_server.cc_modules.cc_constants import CssClass 

41from camcops_server.cc_modules.cc_html import tr_qa 

42from camcops_server.cc_modules.cc_request import CamcopsRequest 

43from camcops_server.cc_modules.cc_sqla_coltypes import ( 

44 CamcopsColumn, 

45 PendulumDateTimeAsIsoTextColType, 

46 ZERO_TO_ONE_CHECKER, 

47 ZERO_TO_TWO_CHECKER, 

48 ZERO_TO_FOUR_CHECKER 

49) 

50from camcops_server.cc_modules.cc_summaryelement import SummaryElement 

51from camcops_server.cc_modules.cc_task import ( 

52 get_from_dict, 

53 Task, 

54) 

55 

56if TYPE_CHECKING: 

57 from camcops_server.cc_modules.cc_exportrecipient import ExportRecipient 

58 

59 

60# ============================================================================= 

61# APEQPT 

62# ============================================================================= 

63 

64class Apeqpt(Task): 

65 """ 

66 Server implementation of the APEQPT task. 

67 """ 

68 __tablename__ = "apeqpt" 

69 shortname = "APEQPT" 

70 provides_trackers = True 

71 

72 q_datetime = CamcopsColumn( 

73 "q_datetime", PendulumDateTimeAsIsoTextColType, 

74 comment="Date/time the assessment tool was completed") 

75 

76 N_CHOICE_QUESTIONS = 3 

77 q1_choice = CamcopsColumn( 

78 "q1_choice", Integer, 

79 comment="Enough information was provided (0 no, 1 yes)", 

80 permitted_value_checker=ZERO_TO_ONE_CHECKER) 

81 q2_choice = CamcopsColumn( 

82 "q2_choice", Integer, 

83 comment="Treatment preference (0 no, 1 yes)", 

84 permitted_value_checker=ZERO_TO_ONE_CHECKER) 

85 q3_choice = CamcopsColumn( 

86 "q3_choice", Integer, 

87 comment="Preference offered (0 no, 1 yes, 2 N/A)", 

88 permitted_value_checker=ZERO_TO_TWO_CHECKER) 

89 

90 q1_satisfaction = CamcopsColumn( 

91 "q1_satisfaction", Integer, 

92 comment=( 

93 "Patient satisfaction (0 not at all satisfied - " 

94 "4 completely satisfied)" 

95 ), 

96 permitted_value_checker=ZERO_TO_FOUR_CHECKER) 

97 q2_satisfaction = CamcopsColumn( 

98 "q2_satisfaction", UnicodeText, 

99 comment="Service experience") 

100 

101 MAIN_QUESTIONS = [ 

102 "q_datetime", 

103 "q1_choice", 

104 "q2_choice", 

105 "q3_choice", 

106 "q1_satisfaction", 

107 ] 

108 

109 @staticmethod 

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

111 _ = req.gettext 

112 return _("Assessment Patient Experience Questionnaire " 

113 "for Psychological Therapies") 

114 

115 def is_complete(self) -> bool: 

116 if self.any_fields_none(self.MAIN_QUESTIONS): 

117 return False 

118 if not self.field_contents_valid(): 

119 return False 

120 return True 

121 

122 def get_summaries(self, req: CamcopsRequest) -> List[SummaryElement]: 

123 return self.standard_task_summary_fields() 

124 

125 def get_task_html(self, req: CamcopsRequest) -> str: 

126 c_dict = { 

127 0: "0 — " + self.wxstring(req, "a0_choice"), 

128 1: "1 — " + self.wxstring(req, "a1_choice"), 

129 2: "2 — " + self.wxstring(req, "a2_choice"), 

130 } 

131 s_dict = { 

132 0: "0 — " + self.wxstring(req, "a0_satisfaction"), 

133 1: "1 — " + self.wxstring(req, "a1_satisfaction"), 

134 2: "2 — " + self.wxstring(req, "a2_satisfaction"), 

135 3: "3 — " + self.wxstring(req, "a3_satisfaction"), 

136 4: "4 — " + self.wxstring(req, "a4_satisfaction"), 

137 } 

138 q_a = "" 

139 for i in range(1, self.N_CHOICE_QUESTIONS + 1): 

140 nstr = str(i) 

141 q_a += tr_qa( 

142 self.wxstring(req, "q" + nstr + "_choice"), 

143 get_from_dict(c_dict, getattr(self, "q" + nstr + "_choice"))) 

144 

145 q_a += tr_qa(self.wxstring(req, "q1_satisfaction"), 

146 get_from_dict(s_dict, self.q1_satisfaction)) 

147 q_a += tr_qa(self.wxstring(req, "q2_satisfaction"), 

148 self.q2_satisfaction, default="") 

149 

150 return f""" 

151 <div class="{CssClass.SUMMARY}"> 

152 <table class="{CssClass.SUMMARY}"> 

153 {self.get_is_complete_tr(req)} 

154 </table> 

155 </div> 

156 <div class="{CssClass.EXPLANATION}"> 

157 Patient satisfaction rating for service provided. The service 

158 is rated on choice offered and general satisfaction. 

159 </div> 

160 <table class="{CssClass.TASKDETAIL}"> 

161 <tr> 

162 <th width="60%">Question</th> 

163 <th width="40%">Answer</th> 

164 </tr> 

165 {q_a} 

166 </table> 

167 """ 

168 

169 def get_fhir_questionnaire_items( 

170 self, 

171 req: "CamcopsRequest", 

172 recipient: "ExportRecipient") -> List[QuestionnaireItem]: 

173 items = [] 

174 

175 items.append(QuestionnaireItem(jsondict={ 

176 "linkId": "q_datetime", 

177 "text": self.wxstring(req, "q_date"), 

178 "type": "dateTime", 

179 }).as_json()) 

180 

181 items.append(QuestionnaireItem(jsondict={ 

182 "linkId": "q1_choice", 

183 "text": self.wxstring(req, "q1_choice"), 

184 "type": "choice", 

185 }).as_json()) 

186 

187 items.append(QuestionnaireItem(jsondict={ 

188 "linkId": "q2_choice", 

189 "text": self.wxstring(req, "q2_choice"), 

190 "type": "choice", 

191 }).as_json()) 

192 

193 items.append(QuestionnaireItem(jsondict={ 

194 "linkId": "q3_choice", 

195 "text": self.wxstring(req, "q3_choice"), 

196 "type": "choice", 

197 }).as_json()) 

198 

199 items.append(QuestionnaireItem(jsondict={ 

200 "linkId": "q1_satisfaction", 

201 "text": self.wxstring(req, "q1_satisfaction"), 

202 "type": "choice", 

203 }).as_json()) 

204 

205 items.append(QuestionnaireItem(jsondict={ 

206 "linkId": "q2_satisfaction", 

207 "text": self.wxstring(req, "q2_satisfaction"), 

208 "type": "choice", 

209 }).as_json()) 

210 

211 return items 

212 

213 def get_fhir_questionnaire_response_items( 

214 self, 

215 req: "CamcopsRequest", 

216 recipient: "ExportRecipient") -> List[QuestionnaireResponseItem]: 

217 

218 items = [] 

219 

220 answer = QuestionnaireResponseItemAnswer(jsondict={ 

221 "valueDateTime": self.q_datetime.isoformat() 

222 }) 

223 items.append(QuestionnaireResponseItem(jsondict={ 

224 "linkId": "q_datetime", 

225 "text": self.wxstring(req, "q_date"), 

226 "answer": [answer.as_json()], 

227 }).as_json()) 

228 

229 answer = QuestionnaireResponseItemAnswer(jsondict={ 

230 "valueInteger": self.q1_choice 

231 }) 

232 items.append(QuestionnaireResponseItem(jsondict={ 

233 "linkId": "q1_choice", 

234 "text": self.wxstring(req, "q1_choice"), 

235 "answer": [answer.as_json()], 

236 }).as_json()) 

237 

238 answer = QuestionnaireResponseItemAnswer(jsondict={ 

239 "valueInteger": self.q2_choice 

240 }) 

241 items.append(QuestionnaireResponseItem(jsondict={ 

242 "linkId": "q2_choice", 

243 "text": self.wxstring(req, "q2_choice"), 

244 "answer": [answer.as_json()], 

245 }).as_json()) 

246 

247 answer = QuestionnaireResponseItemAnswer(jsondict={ 

248 "valueInteger": self.q3_choice 

249 }) 

250 items.append(QuestionnaireResponseItem(jsondict={ 

251 "linkId": "q3_choice", 

252 "text": self.wxstring(req, "q3_choice"), 

253 "answer": [answer.as_json()], 

254 }).as_json()) 

255 

256 answer = QuestionnaireResponseItemAnswer(jsondict={ 

257 "valueInteger": self.q1_satisfaction 

258 }) 

259 items.append(QuestionnaireResponseItem(jsondict={ 

260 "linkId": "q1_satisfaction", 

261 "text": self.wxstring(req, "q1_satisfaction"), 

262 "answer": [answer.as_json()], 

263 }).as_json()) 

264 

265 answer = QuestionnaireResponseItemAnswer(jsondict={ 

266 "valueString": self.q2_satisfaction 

267 }) 

268 items.append(QuestionnaireResponseItem(jsondict={ 

269 "linkId": "q2_satisfaction", 

270 "text": self.wxstring(req, "q2_satisfaction"), 

271 "answer": [answer.as_json()], 

272 }).as_json()) 

273 

274 return items