Coverage for tasks/contactlog.py: 78%

1"""

2 camcops_server/tasks/contactlog.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

28 from typing import List, Optional

29

30 from cardinal_pythonlib.datetimefunc import format_datetime, get_duration_h_m

31 import cardinal_pythonlib.rnc_web as ws

32 from pendulum import DateTime as Pendulum

33 from sqlalchemy.orm import Mapped, mapped_column

34 from sqlalchemy.sql.sqltypes import UnicodeText

35

36 from camcops_server.cc_modules.cc_constants import CssClass, DateFormat

37 from camcops_server.cc_modules.cc_ctvinfo import CTV_INCOMPLETE, CtvInfo

38 from camcops_server.cc_modules.cc_html import (

39 italic,

40 get_yes_no_none,

41 tr,

42 tr_qa,

43)

44 from camcops_server.cc_modules.cc_request import CamcopsRequest

45 from camcops_server.cc_modules.cc_sqla_coltypes import (

46 mapped_camcops_column,

47 BIT_CHECKER,

48 PendulumDateTimeAsIsoTextColType,

49)

50 from camcops_server.cc_modules.cc_task import (

51 Task,

52 TaskHasClinicianMixin,

53 TaskHasPatientMixin,

54)

55

56

57# =============================================================================

58# ContactLog

59# =============================================================================

60

61

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

63 """

64 Server implementation of the ContactLog task.

65 """

66

67 __tablename__ = "contactlog"

68 shortname = "ContactLog"

69 info_filename_stem = "clinical"

70

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

72 UnicodeText, comment="Location"

73 )

74 start: Mapped[Optional[Pendulum]] = mapped_column(

75 PendulumDateTimeAsIsoTextColType,

76 comment="Date/time that contact started",

77 )

78 end: Mapped[Optional[Pendulum]] = mapped_column(

79 "end",

80 PendulumDateTimeAsIsoTextColType,

81 comment="Date/time that contact ended",

82 )

83 patient_contact: Mapped[Optional[int]] = mapped_camcops_column(

84 permitted_value_checker=BIT_CHECKER,

85 comment="Patient contact involved (0 no, 1 yes)?",

86 )

87 staff_liaison: Mapped[Optional[int]] = mapped_camcops_column(

88 permitted_value_checker=BIT_CHECKER,

89 comment="Liaison with staff involved (0 no, 1 yes)?",

90 )

91 other_liaison: Mapped[Optional[int]] = mapped_camcops_column(

92 permitted_value_checker=BIT_CHECKER,

93 comment="Liaison with others (e.g. family) involved (0 no, 1 yes)?",

94 )

95 comment: Mapped[Optional[str]] = mapped_column(

96 "comment", UnicodeText, comment="Comment"

97 )

98

99 @staticmethod

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

101 _ = req.gettext

102 return _("Clinical contact log")

103

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

105 if not self.is_complete():

106 return CTV_INCOMPLETE

107 contact_type = "Patient" if self.patient_contact else "Non-patient"

108 return [

109 CtvInfo(

110 content=(

111 f"{contact_type} contact. Duration (hours:minutes) "

112 f"{get_duration_h_m(self.start, self.end)}."

113 )

114 )

115 ]

116

117 def is_complete(self) -> bool:

118 return (

119 self.start is not None

120 and self.end is not None

121 and self.field_contents_valid()

122 )

123

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

125 return f"""

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

127 <tr>

128 <td width="33%">Location:</td>

129 <td width="67%"><b>{ws.webify(self.location)}</b></td>

130 </tr>

131 {tr_qa("Start:", format_datetime(self.start,

132 DateFormat.SHORT_DATETIME,

133 None))}

134 {tr_qa("End:", format_datetime(self.end,

135 DateFormat.SHORT_DATETIME,

136 None))}

137 {tr(italic("Calculated duration (hours:minutes)"),

138 italic(get_duration_h_m(self.start, self.end)))}

139 {tr_qa("Patient contact?",

140 get_yes_no_none(req, self.patient_contact))}

141 {tr_qa("Staff liaison?",

142 get_yes_no_none(req, self.staff_liaison))}

143 {tr_qa("Other liaison?",

144 get_yes_no_none(req, self.other_liaison))}

145 {tr_qa("Comment:", self.comment)}

146 </table>

147 """