Coverage for tasks/srs.py: 67%
42 statements
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-15 14:23 +0100
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-15 14:23 +0100
1"""
2camcops_server/tasks/srs.py
4===============================================================================
6 Copyright (C) 2012, University of Cambridge, Department of Psychiatry.
7 Created by Rudolf Cardinal (rnc1001@cam.ac.uk).
9 This file is part of CamCOPS.
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.
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.
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/>.
24===============================================================================
26- By Joe Kearney, Rudolf Cardinal.
28"""
30import datetime
31from typing import List, Optional
33from sqlalchemy.orm import Mapped
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 mapped_camcops_column,
40 ZERO_TO_10_CHECKER,
41)
42from camcops_server.cc_modules.cc_summaryelement import SummaryElement
43from camcops_server.cc_modules.cc_task import Task, TaskHasPatientMixin
46# =============================================================================
47# SRS
48# =============================================================================
51class Srs(TaskHasPatientMixin, Task): # type: ignore[misc]
52 """
53 Server implementation of the SRS task.
54 """
56 __tablename__ = "srs"
57 shortname = "SRS"
58 provides_trackers = True
60 COMPLETED_BY_SELF = 0
61 COMPLETED_BY_OTHER = 1
63 VAS_MIN_INT = 0
64 VAS_MAX_INT = 10
66 q_session: Mapped[Optional[int]] = mapped_camcops_column(
67 comment="Session number"
68 )
69 q_date: Mapped[Optional[datetime.date]] = mapped_camcops_column(
70 comment="Session date"
71 )
72 q_relationship: Mapped[Optional[float]] = mapped_camcops_column(
73 comment="Rating of patient-therapist relationship (0-10, 10 better)",
74 permitted_value_checker=ZERO_TO_10_CHECKER,
75 )
76 q_goals: Mapped[Optional[float]] = mapped_camcops_column(
77 comment="Rating for topics discussed (0-10, 10 better)",
78 permitted_value_checker=ZERO_TO_10_CHECKER,
79 )
80 q_approach: Mapped[Optional[float]] = mapped_camcops_column(
81 comment="Rating for therapist's approach (0-10, 10 better)",
82 permitted_value_checker=ZERO_TO_10_CHECKER,
83 )
84 q_overall: Mapped[Optional[float]] = mapped_camcops_column(
85 comment="Overall rating (0-10, 10 better)",
86 permitted_value_checker=ZERO_TO_10_CHECKER,
87 )
89 @staticmethod
90 def longname(req: "CamcopsRequest") -> str:
91 _ = req.gettext
92 return _("Session Rating Scale")
94 def is_complete(self) -> bool:
95 required_always = [
96 "q_session",
97 "q_date",
98 "q_relationship",
99 "q_goals",
100 "q_approach",
101 "q_overall",
102 ]
103 for field in required_always:
104 if getattr(self, field) is None:
105 return False
106 return True
108 def get_summaries(self, req: CamcopsRequest) -> List[SummaryElement]:
109 return self.standard_task_summary_fields()
111 def get_task_html(self, req: CamcopsRequest) -> str:
112 fields = ["q_relationship", "q_goals", "q_approach", "q_overall"]
113 q_a = ""
114 for field in fields:
115 question = field.split("_")[1].capitalize()
116 q_a += tr_qa(question, getattr(self, field))
118 return f"""
119 <div class="{CssClass.SUMMARY}">
120 <table class="{CssClass.SUMMARY}">
121 {self.get_is_complete_tr(req)}
122 {tr_qa("Session number", self.q_session)}
123 </table>
124 </div>
125 <div class="{CssClass.EXPLANATION}">
126 Scores represent a selection on a scale from
127 {self.VAS_MIN_INT} to {self.VAS_MAX_INT}
128 ({self.VAS_MAX_INT} better). Scores indicate the patient’s
129 feelings about different aspects of the day’s therapy session.
130 </div>
131 <table class="{CssClass.TASKDETAIL}">
132 <tr>
133 <th width="60%">Question</th>
134 <th width="40%">Answer</th>
135 </tr>
136 {q_a}
137 </table>
138 <div class="{CssClass.FOOTNOTES}">
139 </div>
140 """