Coverage for tasks/progressnote.py: 70%

33 statements  

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

1""" 

2camcops_server/tasks/progressnote.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 Dict, List, Optional 

29 

30import cardinal_pythonlib.rnc_web as ws 

31from sqlalchemy.orm import Mapped, mapped_column 

32from sqlalchemy.sql.sqltypes import UnicodeText 

33 

34from camcops_server.cc_modules.cc_constants import CssClass 

35from camcops_server.cc_modules.cc_ctvinfo import CtvInfo 

36from camcops_server.cc_modules.cc_html import answer 

37from camcops_server.cc_modules.cc_request import CamcopsRequest 

38from camcops_server.cc_modules.cc_snomed import ( 

39 SnomedConcept, 

40 SnomedExpression, 

41 SnomedLookup, 

42) 

43from camcops_server.cc_modules.cc_task import ( 

44 Task, 

45 TaskHasClinicianMixin, 

46 TaskHasPatientMixin, 

47) 

48from camcops_server.cc_modules.cc_text import SS 

49 

50 

51# ============================================================================= 

52# ProgressNote 

53# ============================================================================= 

54 

55 

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

57 """ 

58 Server implementation of the ProgressNote task. 

59 """ 

60 

61 __tablename__ = "progressnote" 

62 shortname = "ProgressNote" 

63 info_filename_stem = "clinical" 

64 

65 location: Mapped[Optional[str]] = mapped_column( 

66 UnicodeText, comment="Location" 

67 ) 

68 note: Mapped[Optional[str]] = mapped_column( 

69 UnicodeText, comment="Clinical note" 

70 ) 

71 

72 @staticmethod 

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

74 _ = req.gettext 

75 return _("Clinical progress note") 

76 

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

78 return [CtvInfo(content=ws.webify(self.note))] 

79 

80 def is_complete(self) -> bool: 

81 return bool(self.note) 

82 

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

84 # Avoid tables - PDF generator crashes if text is too long. 

85 return f""" 

86 <div class="{CssClass.HEADING}"> 

87 {req.sstring(SS.LOCATION)} 

88 </div> 

89 <div> 

90 {answer(ws.webify(self.location), 

91 default_for_blank_strings=True)} 

92 </div> 

93 <div class="{CssClass.HEADING}"> 

94 {req.sstring(SS.NOTE)} 

95 </div> 

96 <div> 

97 {answer(self.note, default_for_blank_strings=True)} 

98 </div> 

99 """ 

100 

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

102 refinement = {} # type: Dict[SnomedConcept, str] 

103 if self.note: 

104 refinement[req.snomed(SnomedLookup.CLINICAL_NOTE)] = self.note 

105 codes = [ 

106 SnomedExpression( 

107 req.snomed(SnomedLookup.PROGRESS_NOTE_PROCEDURE), 

108 refinement=refinement or None, # type: ignore[arg-type] 

109 ) 

110 ] 

111 return codes