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

28 

29from typing import Optional 

30 

31from sqlalchemy.ext.declarative import declared_attr 

32from sqlalchemy.sql.schema import Column 

33from sqlalchemy.sql.sqltypes import Integer, UnicodeText 

34 

35from camcops_server.cc_modules.cc_constants import CssClass 

36from camcops_server.cc_modules.cc_html import tr_qa 

37from camcops_server.cc_modules.cc_request import CamcopsRequest 

38from camcops_server.cc_modules.cc_sqla_coltypes import ( 

39 CamcopsColumn, 

40 ZERO_TO_FOUR_CHECKER, 

41) 

42from camcops_server.cc_modules.cc_string import AS 

43from camcops_server.cc_modules.cc_task import ( 

44 get_from_dict, 

45 Task, 

46 TaskHasPatientMixin, 

47) 

48 

49 

50# ============================================================================= 

51# Abstract base class 

52# ============================================================================= 

53 

54class AbstractSatisfaction(object): 

55 # noinspection PyMethodParameters 

56 @declared_attr 

57 def service(cls) -> Column: 

58 return Column( 

59 "service", UnicodeText, 

60 comment="Clinical service being rated" 

61 ) 

62 

63 # noinspection PyMethodParameters 

64 @declared_attr 

65 def rating(cls) -> Column: 

66 return CamcopsColumn( 

67 "rating", Integer, 

68 permitted_value_checker=ZERO_TO_FOUR_CHECKER, 

69 comment="Rating (0 very poor - 4 excellent)" 

70 ) 

71 

72 # noinspection PyMethodParameters 

73 @declared_attr 

74 def good(cls) -> Column: 

75 return Column( 

76 "good", UnicodeText, 

77 comment="What has been good?" 

78 ) 

79 

80 # noinspection PyMethodParameters 

81 @declared_attr 

82 def bad(cls) -> Column: 

83 return Column( 

84 "bad", UnicodeText, 

85 comment="What could be improved?" 

86 ) 

87 

88 TASK_FIELDS = ["service", "rating", "good", "bad"] 

89 

90 def is_complete(self) -> bool: 

91 # noinspection PyUnresolvedReferences 

92 return self.rating is not None and self.field_contents_valid() 

93 # ... self.field_contents_valid() is from Task, and we are a mixin 

94 

95 def get_rating_text(self, req: CamcopsRequest) -> Optional[str]: 

96 ratingdict = { 

97 None: None, 

98 0: req.wappstring(AS.SATIS_RATING_A_PREFIX + "0"), 

99 1: req.wappstring(AS.SATIS_RATING_A_PREFIX + "1"), 

100 2: req.wappstring(AS.SATIS_RATING_A_PREFIX + "2"), 

101 3: req.wappstring(AS.SATIS_RATING_A_PREFIX + "3"), 

102 4: req.wappstring(AS.SATIS_RATING_A_PREFIX + "4"), 

103 } 

104 return get_from_dict(ratingdict, self.rating) 

105 

106 def get_common_task_html(self, 

107 req: CamcopsRequest, 

108 rating_q: str, 

109 good_q: str, 

110 bad_q: str) -> str: 

111 if self.rating is not None: 

112 r = f"{self.rating}. {self.get_rating_text(req)}" 

113 else: 

114 r = None 

115 # noinspection PyUnresolvedReferences 

116 return f""" 

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

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

119 {self.get_is_complete_tr(req)} 

120 </table> 

121 </div> 

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

123 <tr> 

124 <th width="50%">Question</th> 

125 <th width="50%">Answer</th> 

126 </tr> 

127 {tr_qa(req.wappstring(AS.SATIS_SERVICE_BEING_RATED), 

128 self.service)} 

129 {tr_qa(f"{rating_q} {self.service}?", r)} 

130 {tr_qa(good_q, self.good)} 

131 {tr_qa(bad_q, self.bad)} 

132 </table> 

133 """ 

134 # ... self.get_is_complete_tr() is from Task, and we are a mixin 

135 

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

137 raise NotImplementedError("implement in subclass") 

138 

139 

140# ============================================================================= 

141# PatientSatisfaction 

142# ============================================================================= 

143 

144class PatientSatisfaction(TaskHasPatientMixin, AbstractSatisfaction, Task): 

145 """ 

146 Server implementation of the PatientSatisfaction task. 

147 """ 

148 __tablename__ = "pt_satis" 

149 shortname = "PatientSatisfaction" 

150 

151 @staticmethod 

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

153 _ = req.gettext 

154 return _("Patient Satisfaction Scale") 

155 

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

157 return self.get_common_task_html( 

158 req, 

159 req.wappstring(AS.SATIS_PT_RATING_Q), 

160 req.wappstring(AS.SATIS_GOOD_Q), 

161 req.wappstring(AS.SATIS_BAD_Q) 

162 ) 

163 

164 

165# ============================================================================= 

166# ReferrerSatisfactionGen 

167# ============================================================================= 

168 

169class ReferrerSatisfactionGen(AbstractSatisfaction, Task): 

170 """ 

171 Server implementation of the ReferrerSatisfactionSurvey task. 

172 """ 

173 __tablename__ = "ref_satis_gen" 

174 shortname = "ReferrerSatisfactionSurvey" 

175 

176 @staticmethod 

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

178 _ = req.gettext 

179 return _("Referrer Satisfaction Scale, survey") 

180 

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

182 return self.get_common_task_html( 

183 req, 

184 req.wappstring(AS.SATIS_REF_GEN_RATING_Q), 

185 req.wappstring(AS.SATIS_GOOD_Q), 

186 req.wappstring(AS.SATIS_BAD_Q) 

187 ) 

188 

189 

190# ============================================================================= 

191# ReferrerSatisfactionSpec 

192# ============================================================================= 

193 

194class ReferrerSatisfactionSpec(TaskHasPatientMixin, AbstractSatisfaction, 

195 Task): 

196 """ 

197 Server implementation of the ReferrerSatisfactionSpecific task. 

198 """ 

199 __tablename__ = "ref_satis_spec" 

200 shortname = "ReferrerSatisfactionSpecific" 

201 

202 @staticmethod 

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

204 _ = req.gettext 

205 return _("Referrer Satisfaction Scale, patient-specific") 

206 

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

208 return self.get_common_task_html( 

209 req, 

210 req.wappstring(AS.SATIS_REF_SPEC_RATING_Q), 

211 req.wappstring(AS.SATIS_GOOD_Q), 

212 req.wappstring(AS.SATIS_BAD_Q) 

213 )