Coverage for tasks/apeqpt.py : 79%

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
3"""
4camcops_server/tasks/apeqpt.py
6===============================================================================
8 Copyright (C) 2012-2020 Rudolf Cardinal (rudolf@pobox.com).
10 This file is part of CamCOPS.
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.
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.
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/>.
25===============================================================================
27- By Joe Kearney, Rudolf Cardinal.
29"""
31from typing import List, TYPE_CHECKING
33from fhirclient.models.questionnaire import QuestionnaireItem
34from fhirclient.models.questionnaireresponse import (
35 QuestionnaireResponseItem,
36 QuestionnaireResponseItemAnswer,
37)
38from sqlalchemy.sql.sqltypes import Integer, UnicodeText
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)
56if TYPE_CHECKING:
57 from camcops_server.cc_modules.cc_exportrecipient import ExportRecipient
60# =============================================================================
61# APEQPT
62# =============================================================================
64class Apeqpt(Task):
65 """
66 Server implementation of the APEQPT task.
67 """
68 __tablename__ = "apeqpt"
69 shortname = "APEQPT"
70 provides_trackers = True
72 q_datetime = CamcopsColumn(
73 "q_datetime", PendulumDateTimeAsIsoTextColType,
74 comment="Date/time the assessment tool was completed")
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)
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")
101 MAIN_QUESTIONS = [
102 "q_datetime",
103 "q1_choice",
104 "q2_choice",
105 "q3_choice",
106 "q1_satisfaction",
107 ]
109 @staticmethod
110 def longname(req: "CamcopsRequest") -> str:
111 _ = req.gettext
112 return _("Assessment Patient Experience Questionnaire "
113 "for Psychological Therapies")
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
122 def get_summaries(self, req: CamcopsRequest) -> List[SummaryElement]:
123 return self.standard_task_summary_fields()
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")))
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="")
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 """
169 def get_fhir_questionnaire_items(
170 self,
171 req: "CamcopsRequest",
172 recipient: "ExportRecipient") -> List[QuestionnaireItem]:
173 items = []
175 items.append(QuestionnaireItem(jsondict={
176 "linkId": "q_datetime",
177 "text": self.wxstring(req, "q_date"),
178 "type": "dateTime",
179 }).as_json())
181 items.append(QuestionnaireItem(jsondict={
182 "linkId": "q1_choice",
183 "text": self.wxstring(req, "q1_choice"),
184 "type": "choice",
185 }).as_json())
187 items.append(QuestionnaireItem(jsondict={
188 "linkId": "q2_choice",
189 "text": self.wxstring(req, "q2_choice"),
190 "type": "choice",
191 }).as_json())
193 items.append(QuestionnaireItem(jsondict={
194 "linkId": "q3_choice",
195 "text": self.wxstring(req, "q3_choice"),
196 "type": "choice",
197 }).as_json())
199 items.append(QuestionnaireItem(jsondict={
200 "linkId": "q1_satisfaction",
201 "text": self.wxstring(req, "q1_satisfaction"),
202 "type": "choice",
203 }).as_json())
205 items.append(QuestionnaireItem(jsondict={
206 "linkId": "q2_satisfaction",
207 "text": self.wxstring(req, "q2_satisfaction"),
208 "type": "choice",
209 }).as_json())
211 return items
213 def get_fhir_questionnaire_response_items(
214 self,
215 req: "CamcopsRequest",
216 recipient: "ExportRecipient") -> List[QuestionnaireResponseItem]:
218 items = []
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())
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())
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())
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())
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())
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())
274 return items