Coverage for tasks/ors.py: 58%
53 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-08 23:14 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-08 23:14 +0000
1#!/usr/bin/env python
3"""
4camcops_server/tasks/ors.py
6===============================================================================
8 Copyright (C) 2012, University of Cambridge, Department of Psychiatry.
9 Created by Rudolf Cardinal (rnc1001@cam.ac.uk).
11 This file is part of CamCOPS.
13 CamCOPS is free software: you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
18 CamCOPS is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with CamCOPS. If not, see <https://www.gnu.org/licenses/>.
26===============================================================================
28- By Joe Kearney, Rudolf Cardinal.
30"""
32from typing import List
34from sqlalchemy.sql.sqltypes import Date, Float, Integer, UnicodeText
36from camcops_server.cc_modules.cc_constants import CssClass
37from camcops_server.cc_modules.cc_html import tr_qa
38from camcops_server.cc_modules.cc_request import CamcopsRequest
39from camcops_server.cc_modules.cc_sqla_coltypes import (
40 CamcopsColumn,
41 ZERO_TO_10_CHECKER,
42)
43from camcops_server.cc_modules.cc_summaryelement import SummaryElement
44from camcops_server.cc_modules.cc_task import Task, TaskHasPatientMixin
47# =============================================================================
48# ORS
49# =============================================================================
52class Ors(TaskHasPatientMixin, Task):
53 """
54 Server implementation of the PHQ9 task.
55 """
57 __tablename__ = "ors"
58 shortname = "ORS"
59 provides_trackers = True
61 COMPLETED_BY_SELF = 0
62 COMPLETED_BY_OTHER = 1
64 VAS_MIN_INT = 0
65 VAS_MAX_INT = 10
67 q_session = CamcopsColumn("q_session", Integer, comment="Session number")
68 q_date = CamcopsColumn("q_date", Date, comment="Session date")
69 q_who = CamcopsColumn("q_who", Integer, comment="Completed by")
70 q_who_other = CamcopsColumn(
71 "q_who_other", UnicodeText, comment="Completed by other: who?"
72 )
73 q_individual = CamcopsColumn(
74 "q_individual",
75 Float,
76 comment="Individual rating (0-10, 10 better)",
77 permitted_value_checker=ZERO_TO_10_CHECKER,
78 )
79 q_interpersonal = CamcopsColumn(
80 "q_interpersonal",
81 Float,
82 comment="Interpersonal rating (0-10, 10 better)",
83 permitted_value_checker=ZERO_TO_10_CHECKER,
84 )
85 q_social = CamcopsColumn(
86 "q_social",
87 Float,
88 comment="Social rating (0-10, 10 better)",
89 permitted_value_checker=ZERO_TO_10_CHECKER,
90 )
91 q_overall = CamcopsColumn(
92 "q_overall",
93 Float,
94 comment="Overall rating (0-10, 10 better)",
95 permitted_value_checker=ZERO_TO_10_CHECKER,
96 )
98 @staticmethod
99 def longname(req: "CamcopsRequest") -> str:
100 _ = req.gettext
101 return _("Outcome Rating Scale")
103 def is_complete(self) -> bool:
104 required_always = [
105 "q_session",
106 "q_date",
107 "q_who",
108 "q_individual",
109 "q_interpersonal",
110 "q_social",
111 "q_overall",
112 ]
113 for field in required_always:
114 if getattr(self, field) is None:
115 return False
116 if self.q_who == self.COMPLETED_BY_OTHER:
117 if not self.q_who_other:
118 return False
119 return True
121 def get_summaries(self, req: CamcopsRequest) -> List[SummaryElement]:
122 return self.standard_task_summary_fields()
124 def who(self) -> str:
125 if self.q_who == self.COMPLETED_BY_OTHER:
126 return "Other: " + (self.q_who_other or "Unknown")
127 if self.q_who == self.COMPLETED_BY_SELF:
128 return "Patient"
129 return "Unknown"
131 def get_task_html(self, req: CamcopsRequest) -> str:
132 fields = ["q_individual", "q_interpersonal", "q_social", "q_overall"]
133 q_a = ""
134 for field in fields:
135 question = field.split("_")[1].capitalize()
136 q_a += tr_qa(question, getattr(self, field))
138 return f"""
139 <div class="{CssClass.SUMMARY}">
140 <table class="{CssClass.SUMMARY}">
141 {self.get_is_complete_tr(req)}
142 {tr_qa("Session number", self.q_session)}
143 {tr_qa("Completed by", self.who())}
144 </table>
145 </div>
146 <div class="{CssClass.EXPLANATION}">
147 Scores represent a selection on a scale from
148 {self.VAS_MIN_INT} to {self.VAS_MAX_INT}
149 ({self.VAS_MAX_INT} better). Scores reflect the patient’s
150 feelings about the indicated life areas over the past week.
151 </div>
152 <table class="{CssClass.TASKDETAIL}">
153 <tr>
154 <th width="60%">Question</th>
155 <th width="40%">Answer</th>
156 </tr>
157 {q_a}
158 </table>
159 <div class="{CssClass.FOOTNOTES}">
160 </div>
161 """