Coverage for tasks/gaf.py: 63%

41 statements  

« prev     ^ index     » next       coverage.py v7.9.2, created at 2025-07-15 14:23 +0100

1""" 

2camcops_server/tasks/gaf.py 

3 

4=============================================================================== 

5 

6 Copyright (C) 2012, University of Cambridge, Department of Psychiatry. 

7 Created by Rudolf Cardinal (rnc1001@cam.ac.uk). 

8 

9 This file is part of CamCOPS. 

10 

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. 

15 

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. 

20 

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

23 

24=============================================================================== 

25 

26""" 

27 

28from typing import List, Optional 

29 

30from sqlalchemy.orm import Mapped 

31 

32from camcops_server.cc_modules.cc_constants import ( 

33 CssClass, 

34 DATA_COLLECTION_ONLY_DIV, 

35) 

36from camcops_server.cc_modules.cc_ctvinfo import CTV_INCOMPLETE, CtvInfo 

37from camcops_server.cc_modules.cc_html import answer, tr 

38from camcops_server.cc_modules.cc_request import CamcopsRequest 

39from camcops_server.cc_modules.cc_snomed import SnomedExpression, SnomedLookup 

40from camcops_server.cc_modules.cc_sqla_coltypes import ( 

41 mapped_camcops_column, 

42 PermittedValueChecker, 

43) 

44from camcops_server.cc_modules.cc_string import AS 

45from camcops_server.cc_modules.cc_summaryelement import SummaryElement 

46from camcops_server.cc_modules.cc_task import ( 

47 Task, 

48 TaskHasPatientMixin, 

49 TaskHasClinicianMixin, 

50) 

51from camcops_server.cc_modules.cc_trackerhelpers import TrackerInfo 

52 

53 

54# ============================================================================= 

55# GAF (crippled) 

56# ============================================================================= 

57 

58 

59class Gaf(TaskHasClinicianMixin, TaskHasPatientMixin, Task): # type: ignore[misc] # noqa: E501 

60 """ 

61 Server implementation of the GAF task. 

62 """ 

63 

64 __tablename__ = "gaf" 

65 shortname = "GAF" 

66 provides_trackers = True 

67 

68 score: Mapped[Optional[int]] = mapped_camcops_column( 

69 permitted_value_checker=PermittedValueChecker(minimum=0, maximum=100), 

70 comment="GAF score (1-100 or 0 for insufficient information)", 

71 ) 

72 

73 @staticmethod 

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

75 _ = req.gettext 

76 return _("Global Assessment of Functioning (data collection only)") 

77 

78 def is_complete(self) -> bool: 

79 return ( 

80 self.score is not None 

81 and self.score != 0 

82 and self.field_contents_valid() 

83 ) 

84 

85 def get_trackers(self, req: CamcopsRequest) -> List[TrackerInfo]: 

86 return [ 

87 TrackerInfo( 

88 value=self.total_score(), 

89 plot_label="GAF score (rating overall functioning)", 

90 axis_label="Score (1-100)", 

91 axis_min=0.5, 

92 axis_max=100.5, 

93 ) 

94 ] 

95 

96 def get_clinical_text(self, req: CamcopsRequest) -> List[CtvInfo]: 

97 if not self.is_complete(): 

98 return CTV_INCOMPLETE 

99 return [CtvInfo(content=f"GAF score {self.total_score()}")] 

100 

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

102 return self.standard_task_summary_fields() 

103 

104 def total_score(self) -> Optional[int]: 

105 if self.score == 0: 

106 return None 

107 return self.score 

108 

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

110 return f""" 

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

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

113 {self.get_is_complete_tr(req)} 

114 {tr(req.wappstring(AS.GAF_SCORE), answer(self.score))} 

115 </table> 

116 </div> 

117 {DATA_COLLECTION_ONLY_DIV} 

118 """ 

119 

120 def get_snomed_codes(self, req: CamcopsRequest) -> List[SnomedExpression]: 

121 if not self.is_complete(): 

122 return [] 

123 return [SnomedExpression(req.snomed(SnomedLookup.GAF_SCALE))]